if to expr…wtf?

Jan 20, 2014 at 11:52am

if to expr…wtf?

Can someone kindly tell me why the combined expression in the included patch is not a valid substitute for the split expression that utilizes [if]? Logically, how do they differ?

Specifically, why is the “else” element of [if $f1<0.5 then $f1 else out2 $f1] not equivalent to ($f1>=0.5) ?

I suspect the nan error is related to the sqrt but it doesn’t make sense why the same error doesn’t occur with the variation using [if].

– Pasted Max Patch, click to expand. –
#278668
Jan 20, 2014 at 12:24pm

The result of ($f1>=0.5) is 0 or 1. $f1 can be any value.

#278671
Jan 20, 2014 at 12:50pm

The result of ($f1>=0.5) is 0 or 1. $f1 can be any value.

That’s the whole point of using a relational function in the expression.

If ($f1=0.5) is true, then ($f1>=0.5) is false and vice versa.. so the expression reduces to one of two possibilities: [0*x + 1*y] or [1*x + 0*y]. Hence, it should output either x or y for any input [0..1].

– Pasted Max Patch, click to expand. –
#278673
Jan 20, 2014 at 1:23pm

hold

#278678
Jan 20, 2014 at 1:31pm

The “else” statement of [if $f1==0.5 then $f1 else out2 $f1] is ($f1!=0.5).

If $f1 = 15 then ($f1==0.5) = 0 and ($f1!=0.5) = 1.

#278680
Jan 20, 2014 at 1:34pm

Look at it this way

"Specifically, why is the “else” element of [if $f1<0.5 then $f1 else out2 $f1] not equivalent to ($f1>=0.5) ?"

"Specifically, why is the “else” element of[ if 15.<0.5 then 15. else out2 15.] not equivalent to (15.>=0.5) = 1?"

#278681
Jan 20, 2014 at 1:44pm

I think you are right, the issue is the ‘nan’ mixed with floats.

<code>

– Pasted Max Patch, click to expand. –

</code>

G

PS the difference, I guess, is that in one case the if is within the expression and thus the ‘nan’ is messing up the computation as it is always calculated (the sum of the two and in one there is ‘nan’).

in the other case the if is outside the computation and the program checks for what is true and based on that compute a value.

#278682
Jan 20, 2014 at 1:45pm

"Specifically, why is the “else” element of[ if 15.<0.5 then 15. else out2 15.] not equivalent to (15.>=0.5) = 1?"

(15<0.5) is false. (15>=0.5) is true. So the value of 15 gets passed out the second outlet instead of the first. Perfectly logical.

By the same token, [(15<0.5)*x + (15>=0.5)*y] is equivalent to [0*x + 1*y] = y

Again, no logical inconsistency.

#278683
Jan 20, 2014 at 1:50pm

The if outputs 15. The expr outputs 1.

#278684
Jan 20, 2014 at 2:02pm

OK… answering my own question – at least in terms of getting the expression to work. I’m still not sure why the same expression doesn’t fail when split by the if object. Somehow, a negative value is generated within expr as it is evaluating the two conditions.

– Pasted Max Patch, click to expand. –
#278685
Jan 20, 2014 at 2:06pm

as I said above I think the issue is an expression with a non number as one of the element to be calculated.
By adding the ‘abs’ you are getting rid of the ‘nan’ from the negative value inside of ‘sqrt’
that’s all…
see my example above and the expression adding nan to real, the result is surprise surprise nan.
G

PS to be sure it is clear:
<code>

– Pasted Max Patch, click to expand. –

</code>

#278687
Jan 20, 2014 at 2:35pm

The if outputs 15. The expr outputs 1.

No… using your example, the expr outputs 1 * 15.

Follow me here… [if $f1<0.5 then $f1 else out2 $f1] ( with out1 feeding to x and out2 to feeding to y) you can use [expr ($f1<0.5)*$f1*x + ($f1>=0.5)*$f1*y]. iow, the if object outputs the input to one of two outputs, which is then processed by an expression. The expr object multiplies 1 or 0 by the input * an expression. It’s the same logic in a single object.

#278689
Jan 20, 2014 at 2:44pm

By adding the ‘abs’ you are getting rid of the ‘nan’ from the negative value inside of ‘sqrt’ that’s all…

Well, yeah.. that’s why I used it. I admit it came in a “duh” moment.

But my original confusion still hasn’t been addressed… Why does the same sqrt expression fail when the logic is evaluated internally by the expression object yet work when the logical is handled by the if object?

#278690
Jan 20, 2014 at 6:12pm

because inside the expr object there is no type check?

#278697
Jan 20, 2014 at 6:29pm

just had a quick look, can it be that you need to put another bracket around everything behind the boolean?
[expr ($f1>0.5)*((0.5)*...) + ... ]

Nope.. that was the first thing I checked. But I agree the 0.5 does look kinda naked.

There is something internal happening in [expr].. somehow signed values are being created in the process of evaluating the logic.. even if for only a flash moment.. and then whammo… NAN.

#278698
Jan 20, 2014 at 6:36pm

because inside the expr object there is no type check?

I thought that was defined by the operators… > is boolean… sqrt is not, etc.

#278699
Jan 20, 2014 at 9:22pm

as you can see i deleted my first response before you copied it.

now lets see if my second version is better. :)

#278701
Jan 21, 2014 at 4:25am

“Why does the same sqrt expression fail when the logic is evaluated internally by the expression object yet work when the logical is handled by the if object?”

Because in the combined expr equation one side is always nan. The if removes the nan.

<code>

– Pasted Max Patch, click to expand. –

</code>

#278714
Jan 21, 2014 at 9:04am

Rick, you’re right! I don’t know how I missed that. For some reason I was thinking that a false evaluation would equal 0… while somehow overlooking 0 * x. In most cases, multiplying by zero generates a zero.. which is enough to get the job done. But this time, I was one who was goosed. Thanks for the exchange.

#278755
Jan 22, 2014 at 3:41am

0*NaN => NaN. Always.

The other thing that trips people up is evaluating (x == x) when x=NaN.

#278835
Jan 22, 2014 at 8:12am

0*NaN => NaN. Always.

It’s as though 0 and 1 are the Trumps in the deck of numbers… but NaN is the Joker.

#278865
Jan 23, 2014 at 6:36am

Don’t forget to watch out for infinity.

What do you expect to get from 0*Inf?

#278952
Jan 23, 2014 at 11:11am

What do you expect to get from 0*Inf?

Well it looks like NaN reigns supreme.. but maybe there is a way to cheat? :)

– Pasted Max Patch, click to expand. –
#278968
Jan 24, 2014 at 11:02am

Yes, in fact you really need to do something like this if your calculations can produce an Inf or NaN and you don’t want your patch to trip up because of it.

There is a convenience object for this in the MSP domain: [bitsafe~] (“Replace NaN and infinite signal values with 0″).

My favorite way to filter out NaN in Max (not MSP) is [if $f1==$f1 then $f1 else 0.]. The IEEE spec for floating point explicitly states that the expression (NaN == NaN) must evaluate to false (which makes sense, if you think about it).

#279061
Jan 24, 2014 at 12:38pm

Ahh, that’s very helpful. Thank you.

Of course, now I’m confused by all this inf business.. and [if $f1==$f1 then $f1 else 0.] doesn’t address the problem of inf.

Even if something like if ($f1==$f1&&$f1<=2147483647) then $f1 else 0] was adequate to filter inf output, I still don’t understand why the max window will handle up to 2^1023 and flonum will handle up to 2^127.. and I would’t want to filter those larger values unnecessarily. Yet Max is only 32-bit and I always seem limited to 6 decimal places of precision. Seems inconsistent.

Anyway, I don’t mean to take advantage of your time. It’s too bad I can’t buy a round of beers to motivate you to stick around. :)

#279071
Jan 26, 2014 at 9:20am

No, my little code example only addresses NaN. In C one could write an ISINF macro as follows:

#define ISNAN(x) ((x) != (x))
#define ISINF(x) (!ISNAN(x) && ISNAN(x-x))

Except nowadays I’d write them as inline functions (to avoid the standard unwanted macro side effects). And except if I were writing in a compiled code environment it would arguably be better to use compiler-supplied test functions. But hopefully you get the idea.

Yet Max is only 32-bit and I always seem limited to 6 decimal places of precision.

Max 6.1 is only 32-bit if you tell it to be so. It is 64-bit if you allow it to be so.

The “six decimal places of precision” is, largely, a display issue only. When posting to the Max window, [print] seems to call the standard C function sprintf() with a default “%f” parameter, which rounds the output to six decimal digits. Some other objects display other degrees of precision (capture~, for instance, normally displays three digits after the decimal point, and so on). But floats are always passed between objects with full 32-bit precision (and most objects use 64-bit precision internally).

The 2,147,483,647 you cite is the highest value for a 32-bit signed integer. Floats and integers are different animals and have different min/max values (comparing a float to the maximum integer value is of somewhat limited value, btw). 2^127 is the largest exponent a 32-bit float can have (the largest possible value is greater than that, since the mantissa can be as large as just-less-than-two). 2^1023 is the highest exponent for 64-bit floats.

You might want to spend some quality time with http://en.wikipedia.org/wiki/IEEE_floating_point if you want this to all really make sense.

Finally, one reason the sprintf() function has a default precision of six significant decimal places for floats is because the most common size for floats when the C Standard Libraries were first being developed was 32 bits, and 32-bit floats have 24-bit mantissas, which gives approximately six decimal places of precision. Not much point in the default display precision being higher than that.

#279192
Jan 27, 2014 at 8:54am

Enlightening. It’s still a bit ambiguous to me if the “full 32-bit precision” that is passed between objects entails 24-bit mantissas/6 decimal places – which would mean that 6 decimal places is more than just a display issue. I’ll check out the IEEE info and see if I can’t clear that up myself… :) Thanks for all the insight.

#279257

You must be logged in to reply to this topic.