1
$\begingroup$

Here is a piecewise function

$$f(x,y) = \begin{cases} 1-y(1-x), & \text{if $y > 0$} \\ \frac{1}{1+y(1-x)}, & \text{if $y < 0$} \\ 1, & \text{if $y = 0$} \end{cases}$$

I would like to express this same function without relying on checking in which range of values $y$ falls in?


For the simple case where $y$ could take only the values -1,1 and 0, then $f(x,y)=\left(1-y(1-x)\right)^y$ would work fine. This is as far as I could get.


Just for fun, below is a plot of this function for a given value of $x$:

### R code ###

f = function(x,y)
{
    if (y>0)
    {
        1-y*(1-x)
    } else{
        1/(1+y*(1-x))
    }
}

x=0.72
ys = seq(-2,2,0.01)
image=c()
for (y in ys) image[length(image)+1] = f(x=x,y=y)

plot(y=image,x=ys)

enter image description here


FYI, I am asking this question in the hope of fastening my C code by avoiding a potentially useless if statement.

$\endgroup$
  • 1
    $\begingroup$ This kind of if statement cost very little. I would be really surprised if this was the place where optimization could get significant return. For exemple, if you want to calculate the value of this function and store it in an array, it's the "store" part that will take the most time : memory access is slow $\endgroup$ – Tryss Aug 5 '16 at 1:15
2
$\begingroup$

The time cost associated with the if statement is going to be less than any mathematical trick which turns it all into one equation. Any equation produced which would evaluate this appropriately in one line will end up involving more operations and more time than the single if statement. Also from a point of readability the way you have is better than a single equation.

If however this is for an assignment or something where you have to reduce it to one equation you could try the following:

$$\left(1-y(1-x)\right)\frac{1}{2}\left(\frac{|y|}{y}+1\right)+\left(\frac{1}{1+y(1-x)}\right)\frac{1}{2}\left(\frac{|y|}{y}-1\right)$$

This however will not work correctly for $y=0$.

A way to get around that and utilizing the symmetry of your two equations would be:

$$\left(1-|y|(1-x)\right)^{sgn(y)}$$

where $sgn(y)$ is the sign of $y$. Most programming languages have it.

Implementing it in Mathematica as:

With[{x = 0.72}, Plot[(1 - Abs[y] (1 - x))^Sign[y], {y, -2, 2}]]

gives me the graph:

enter image description here

$\endgroup$
  • $\begingroup$ You're right, I was just about to delete the comment. $\endgroup$ – John Wayland Bales Aug 5 '16 at 1:35
  • $\begingroup$ Thank you. Searching the sign is testing condition and end up being equivalent. But as you said and showed, a math trick would anyway take more time than a simple if statement. It was good to learn about the generation form of a piecewise function where pieces are defined by the 0 boundary. $\endgroup$ – Remi.b Aug 5 '16 at 1:55
2
$\begingroup$

You can usually recode "if" statements with crude tricks like this:

To write

$$ f(x) = x $$ if $x > 1$ but $$ f(x) = 1 $$ if $x < 1$, you can write (in Matlab, but I assume R is similar)

u = (x >= 0) .* x + (x < 0) .* 1;

Yeah, you end up computing both values and throwing one away. On the other hand, it's really easy to vectorize, etc.

$\endgroup$
  • $\begingroup$ Thank you. Unfortunately, I am not literate in Matlab (only a little bit in Mathematica and other languages that are not specific to math) and I don't fully understand your answer. The code I am trying to speed up is coded in C (info added to the post; therefore, the concept of vectorization does not really apply). I was willing to avoid a potentially unnecessary if statement and was willing to satisfy my curiosity about the nature of this function. $\endgroup$ – Remi.b Aug 5 '16 at 1:10
2
$\begingroup$

In general if you have a function of the sort

$$f(x)= \begin{cases} g(x)\text{ for }x>0\\h(x)\text{ for }x<0 \end{cases}$$

it can be written as

$$ f(x)=\dfrac{1}{2}\left[ g(x)+h(x)+\dfrac{\vert x\vert}{x}(g(x)-h(x))\right]$$

but you would still have to handle the $0$ case.

I'm not familiar with R syntax but if it evaluates true statements a $1$ and false statements as $0$ then you could use something like

$$ f(x)=(x>0)\cdot g(x)+(x<0)\cdot h(x)+(x=0)\cdot 1$$

$\endgroup$
  • 2
    $\begingroup$ While interesting, it's worth noticing that this kind of expression would be far worse from a computational point of view ;) $\endgroup$ – Tryss Aug 5 '16 at 1:18
  • $\begingroup$ You would need to define the functions $f(x)+g(x)$ and $f(x)-g(x)$ instead of $f(x)$ and $g(x)$, start with a default value of $1$ and have some sort of escape for division by $0$. $\endgroup$ – John Wayland Bales Aug 5 '16 at 1:21
  • 1
    $\begingroup$ "Far worse from a computational point of view" is in the eye of the compiler and machine. On a parallel processor, exactly this trick ("take both branches; pick the answer you want later") is used all the time, and even in a single processor architecture, the time taken to compute the alternative value may be trivial compared to the wait-cost for fetching the value of $x$, even from relatively fast cache. Big-O analysis is great for asymptotics, but not much use in cases like this where architecture matters. (And it took me a long time to learn that...) $\endgroup$ – John Hughes Aug 5 '16 at 3:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.