If possible, I'd like a function f(i,j)=k defined as follows

1. Apr 18, 2014

Jamin2112

I'm writing a piece of code and I want to simplify a bunch of if/else statements.

I need f:{-1,1}x{-1,1}-->{1,2,3,4} with

f(1,-1)=1
f(1,1)=2
f(-1,1)=3
f(-1,-1)=4

Can anyone think of a mathematical function that will give me the desired output?

2. Apr 18, 2014

Jamin2112

In other words, I want a fancy way of simplifying

Code (Text):

if (dx == 1 && dy == -1)
th = 1;
else if (dx == 1 && dy == 1)
th = 2;
else if (dx == -1 && dy == 1)
th = 3;
else // (dx == -1 && dy == -1)
th == 4;

I want to write 1 line:

Code (Text):

th = ??? // some operation(s) on dx and dy

3. Apr 18, 2014

Staff: Mentor

I haven't given much though to a math function to do this, but you could simplify your if block like so:
Code (Text):
if (dx == 1)
{
th = (int)(1.5 + 0.5 * dy);
}
else if (dx == -1)
{
th = (int)(3.5  - 0.5 *dy);
}

If there are only the four possible combinations of -1 and 1, the else clause I have above could be further simplified by changing "else if (dx == -1)" to simply "else".

Last edited: Apr 19, 2014
4. Apr 18, 2014

ModusPwnd

I just did some curve fitting in Excel and got this;

=-(1/6)*(dx+2*dy)^3+(1/8)*(dx+2*dy)^2+(7/6)*(dx+2*dy)+(15/8)

In Excel that rounds to the exact numbers you need. If that doesnt round correctly for you, you can do a higher order fit.

Probably not the "best" function, but its "a" function. :)

5. Apr 18, 2014

jbunniii

How about
$$f(x,y) = -x + \frac{5 + xy}{2}$$
Solved by presuming a form $f(x,y) = ax + by + c + dxy$, which gives us the following 4x4 linear equation
$$\begin{bmatrix} 1 & -1 & 1 & -1 \\ 1 & 1 & 1 & 1 \\ -1 & 1 & 1 & -1 \\ -1 & -1 & 1 & 1\\ \end{bmatrix} \begin{bmatrix} a \\ b \\ c \\ d \\ \end{bmatrix} = \begin{bmatrix} 1 \\ 2 \\ 3 \\ 4 \\ \end{bmatrix}$$
I let Matlab do the dirty work, which gave me $a=-1, b = 0, c = 5/2, d = 1/2$.

Last edited: Apr 18, 2014
6. Apr 18, 2014

ModusPwnd

Did you know there could be a solution of that form before letting Matlab do the dirty work?

7. Apr 18, 2014

jbunniii

At first I thought there would be a solution of the form $ax + by + c$: first linearly map the values of $x$ into 0 and 1, and the same with $y$, then map the resulting pair into the values 0, 1, 2, 3 (binary representation with two "bits"), then add one. It would have worked if he had wanted

f(1,-1)=1
f(1,1)=2
f(-1,-1)=3
f(-1,1)=4

but his map reverses the 3 and 4. If this had worked, the problem would have had 4 equations and 3 unknowns, but the 4th equation would be a linear combination of the first 3, hence consistent Since it didn't work, I needed a 4th unknown, thus one more term involving $x$ and $y$. Instead of $dxy$ you can use $d$ times just about any function $g(x,y)$ as long as the 4th column of the matrix is linearly independent of the first three. But $xy$ has the advantage of being easy to calculate for $x,y = \pm 1$.

8. Apr 18, 2014

jbunniii

P.S. As it happens, we only needed 3 unknowns, namely $a,c,d$, since $b$ ended up being zero. So I could have used the form $ax + c + dxy$. But I didn't know that until after the fact.

9. Apr 18, 2014

Staff: Mentor

Simplifying code to a math function is probably not a great idea, in this particular case, although it is really interesting.

Mark's simplification is still readable.

Something to solve jbunnii's function would not be inherently enlightening nor would it be "self documenting" the way Mark's code is.

And the machine code for if/else is really elementary and fast. jbunnii's function is actually quite cool, but it involves 2 additions, a negation, a multiplication and a division. So if this has to be fast it may be possible the division could slow you down. Depends on your platform and compiler.

My comment about performance was posted without seeing jbunnii's last post. Oops.

FWIW, if you don't care about overhead, create an associative array, then statically assign results {1...4} to each element:
Code (Text):
th = assoc_arr[ to_string(dx, dy)];
. This is more than bit much, but the result is just as elegant as the math function approach.

If you have many if then else checks, consider changing to a switch() construct. Function pointer arrays are great for simplifying multiple branches into functions that take identical datatypes.
http://www.newty.de/fpt/fpt.html#arrays

10. Apr 18, 2014

jbunniii

Agree fully with jim mcnamara that you should NOT implement it this way in software if you care about efficiency and, much more importantly, readability/maintainability. In my day job as a software engineer, if I were to encounter a smartass function like this in our source code, I would want to strangle whoever wrote it. But it would be an interesting interview question. :tongue:

Much better to write something like your original code:
Code (Text):

if (dx == 1 && dy == -1)
th = 1;
else if (dx == 1 && dy == 1)
th = 2;
else if (dx == -1 && dy == 1)
th = 3;
else // (dx == -1 && dy == -1)
th == 4;

 removed alternate code which calculated the wrong answer

11. Apr 19, 2014

Staff: Mentor

jbunni, I agree. I don't see any problem with the if ... else block as shown in post #2. "Clever" code is seldom the best way to go, and a straightforward algorithm is to be preferred, not least for the sake of being more understandable to the maintenance programmer.

12. Apr 19, 2014

Jamin2112

Good answers, guys. Thanks!

13. Apr 19, 2014

FactChecker

x= 1+(1-i)+(j*i+1)/2 works.
But I agree that simpler is better in programming.
You can use the if/then or define a doubly-dimensioned array to look up the correct value.

14. Apr 19, 2014

AlephZero

If you want speed, just use a lookup table.
Code (Text):

static const int fdata[2][2] = {{4,0,3},{0,0,0},{(1,0,2}};

int f(int x, int y)
{
return fdata[x+1][y+1];
}

15. Apr 19, 2014

Staff: Mentor

The fdata array has too many elements in it. You're probably thinking that the array is 3 X 3, and that the indexes run 0, 1, 2. There is also an extra left paren in the last group of three numbers.

16. Apr 19, 2014

AlephZero

True. I mostly use languages that support arrays properly (unlike C and C++), so the dimensions would run from -1 to 1 and you would just return fdata(i.j).

17. Apr 20, 2014

Staff: Mentor

Unless you're referring to Fortran, then whatever languages you're talking about are newer than C, which has been around since the early 70's. Newer languages don't have the need to maintain compatability with existing code, so can start on a clean page. For me, it's not a hardship to forgo negative array subscripts.

18. Apr 20, 2014

jbunniii

As a side note, I will point out that it is possible to use negative indices in C and C++. For example, I can write

Code (Text):

int data[] = {1, 2, 3};
int *pData = &data[1];

Then I can access the elements of the array using either data[0],data[1],data[2] or pData[-1],pData[0],pData[1].

For two-dimensional arrays it can still be done, but setting it up is uglier.

Code (Text):

int data[3][3] = {{1,2,3}, {4,5,6}, {7,8,9}};
int *pData[3] = {&data[0][1], &data[1][1], &data[2][1]};
int **ppData = &pData[1];

This allows me to write ppData[n-1][m-1] instead of data[m][n], where $0 \leq m,n \leq 2$.

It's usually too hideous to contemplate doing this sort of thing in code for public consumption, but if you encapsulate the ugly implementation in a class, the ability to use negative subscripts can sometimes make the code that uses the array clearer, e.g. if the 2d array represents a kernel being used in an image processing operation.

19. Apr 20, 2014

FactChecker

The original solution by Mark44 is a simple, direct solution. (The dimensions were off and a typo, but without a compiler it is hard to get it right the first time.) Regarding array indices and table look-ups, nothing can beat the versatility of well implemented associative arrays (aka hash tables, dictionaries, etc.). C++ hash tables (unordered_map) are awkward to use, Perl is very good, Python looks good but I have no experience with it.

20. Apr 20, 2014

Staff: Mentor

I'm not sure what you're talking about. I didn't use arrays at all. You might be referring to the code that AlephZero wrote that I quoted in one post.

21. Apr 20, 2014

AlephZero

IIRC, PL/1 (which I used back in the days of IBM S/360 mainframes) had this feature before Fortran.

C's model of arrays (like almost everything else in C) is tied much too closely to the "standard" computer hardware designs when it was invented. But at least the same people didn't make the same mistake twice when they invented Unix.

22. Apr 20, 2014

FactChecker

Sorry. You're right. It was AlephZero.

Share this great discussion with others via Reddit, Google+, Twitter, or Facebook