Home > Enterprise >  Convert conditional logic for edge wrapping to math expression
Convert conditional logic for edge wrapping to math expression

Time:08-17

I have a simple function that takes a float parameter x in the range [-1.0, 2.0] and maps it to range [0.0, 1.0] such that values below 0.0 are mapped to 1.0 and values above 1.0 are mapped to 0.0:

float wrap_ternary(x) {
  // result is between [0.0, 1.0]
  return x < 0.0 ? x   1.0 : x > 1.0 ? x - 1.0 : x;
}

I want to convert that function to use math expressions instead of conditionals. I've come up with the following algorithm:

float wrap_mod(x) { 
  return (((x   1.0) % 2.0   1.0) % 1.0);
}

However the edge wrapping of this algorithm is inclusive i.e. 1.0/2.0 are mapped to 0.0 whereas the ternary version would map these values to 1.0:

X wrap_ternary wrap_mod wrong
-1.0 0.0 0.0
-0.5 0.5 0.5
0.0 0.0 0.0
0.5 0.5 0.5
1.0 1.0 0.0 x
1.5 0.5 0.5
2.0 1.0 0.0 x

How would I modify my algorithm so that it produces the same results as the ternary version? I've tried to subtract EPSILON from my modulo but that didn't really work... I just can't wrap my head around this. No pun intended.

CodePudding user response:

The frac function, which returns the fractional part of a float, seems to have the behaviour you want for all inputs other than 1.0 and 2.0. So this would work:

float wrap_ternary(x) {
  return (x == 1.0 || x == 2.0) ? 1.0 : frac(x);
}

CodePudding user response:

This might work as expected, though...

float wrap_somehow(x) {
    return 0.5 - (frac(1.5 - abs(x - 0.5)) - 0.5) * sign(x - 0.5);
}
  • Related