Forums > MaxMSP

signal division bug??


gs
March 27, 2008 | 11:52 am

try to divide a signal with itself!!!
it does not produce always 1.000
this doesn’t happen with the non signal object!
is this a bug of some kind or normal behavior?
check out the following very simple patch and try numbers that are a power of 2 and numbers that are not
and you will see what I mean…
this also happens with the !/~ object.
any suggestions on why is this happening and any workarounds?

gs

max v2;
#N vpatcher 99 61 496 456;
#P origin 147 0;
#P toggle 208 298 15 0;
#P window setfont "Sans Serif" 9.;
#P window linecount 1;
#P newex 208 270 50 9109513 == 1.;
#P user number~ 1 298 74 313 9 139 3 2 0. 0. 0 0. 250 0. 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 1 270 50 9109513 ==~ 1.;
#P comment 214 49 66 9109513 SCHEDULER;
#P flonum 220 210 83 9 0 0 0 139 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 220 184 50 9109513 * 10000.;
#P flonum 285 185 83 9 0 0 0 139 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 285 159 50 9109513 * 10000.;
#P button 228 100 15 0;
#P newex 220 123 27 9109513 11.;
#P newex 220 157 50 9109513 / 11.;
#P toggle 105 188 15 0;
#P newex 105 210 50 9109513 dac~;
#P user number~ 14 215 87 230 9 139 3 2 0. 0. 0 0. 250 0. 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 15 189 50 9109513 *~ 10000;
#P flonum 134 67 35 9 0 0 0 139 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 14 95 50 9109513 sig~ 11;
#P user number~ 97 166 170 181 9 139 3 2 0. 0. 0 0. 250 0. 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 98 140 50 9109513 *~ 10000;
#P newex 14 164 74 9109513 /~ 11.;
#P comment 18 48 42 9109513 DSP;
#P window linecount 2;
#P comment 103 99 74 9109513 divide a number with itself;
#P comment 10 234 81 9109513 the signal output is not exatly unity;
#P comment 218 231 106 9109513 the scheduler produces the correct result;
#P comment 49 10 100 9109513 try numbers like 3 , 5 , 6 , 7 , 9 , 10 , 11…;
#P comment 151 9 100 9109513 and numbers like 2 , 4 , 8 , 16….;
#P fasten 6 0 23 0 19 185 6 185;
#P connect 23 0 24 0;
#P fasten 10 0 9 0 139 92 19 92;
#P connect 9 0 6 0;
#P connect 11 0 12 0;
#P connect 6 0 11 0;
#P fasten 10 0 6 1 139 92 83 92;
#P connect 7 0 8 0;
#P connect 9 0 7 0;
#P connect 14 0 13 0;
#P fasten 15 0 25 0 225 179 213 179;
#P connect 25 0 26 0;
#P fasten 10 0 16 0 139 92 225 92;
#P fasten 17 0 16 0 233 117 225 117;
#P connect 16 0 15 0;
#P connect 15 0 20 0;
#P connect 20 0 21 0;
#P fasten 10 0 15 1 139 92 265 92;
#P connect 16 0 18 0;
#P connect 18 0 19 0;
#P pop;


March 27, 2008 | 1:49 pm

On 27 mars 08, at 12:52, hmutant wrote:

> try to divide a signal with itself!!!

I generally have better things to do ;-)

> it does not produce always 1.000
> this doesn’t happen with the non signal object!

This is not true. 7.97 is OK on my system for the DSP part of your
patch, but not for the Max part. For 7.92, it’s the opposite.

> is this a bug of some kind or normal behavior?

It’s normal.

_____________________________
Patrick Delges

Centre de Recherches et de Formation Musicales de Wallonie asbl

http://www.crfmw.be/max



gs
March 27, 2008 | 3:05 pm

you are right about the fact that the non signal object also produces wrong results in certain cases but not for the same numbers as in your system!!

It doesn’t seem normal.

I created a java class for use with mxj~ and a C++ external for windows that perform a simple division like the /~ object. They are working fine whatever number you feed them. The result is always 1 and the test [==~ 1] always results to true!
If it is normal behavior just for the cycling’s objects for some reason I don’t understand, could someone explain it to me?
Anyway shouldn’t at least be consistent between different OS and between signal and non signal objects? How can I predict if it is going to work on a different machine than mine?

It is not just a philosophical question. If you try to quantize a number you need to perform this kind of operation, and the fact that the result is not the same on every machine makes it very difficult to develop a reliable application

gs


March 27, 2008 | 9:51 pm

This is not a bug but an artifact of how finite-precision floating point arithmetic works.

Google the list a bit about floating point precision. Check out Peter Elsea’s tutorial on the subject while you’re at it. Reading the fine print on optimizations in the /~ object is also worthwhile.

The answer is insanely obvious if you understand how the /~ object works and a little bit about numeric arithmetic. But I don’t want to give away the punch line.



gs
March 28, 2008 | 2:31 pm

I read some parts of Peter Elsea’s tutorials
and they are very nice and informative…
I need to read them more carefully when I find some time.

Still… I don’t understand what finite precision of
floats (32Bit or 64Bit or any precision) have to do with
what I am experiencing with the [/] objects!!

If it is a finite precision problem, since in all systems
Max AND MSP use floating point numbers of the same precision
shouldn’t always produce the same result? Why is
it system dependent????
This doesn’t happen in jitter using [jit.op] and float32 or float64
type of matrix!!! If it was due to finite precision it should
produce the same results in jitter too!!! The [expr]
object in MAX also works fine in my system.
There is also an inconsistency between the [== 1.0] object
and the [if $f1==1.0] object (check out the patch below).
The [if] object seems to work better.
Can someone explain which objects use what types of variables
in each system so we can know what kind of casting occurs
each time?
I think max msp should be able to handle things like that
in a more consistent way.

In other programming languages like C++, java…
the division and comparison operators give the correct
result when dividing a floating point number with itself.
As long as you are not mixing different types of variables
(single precision with double or int) comparing the result
with 1.0 (1.0 being of the same type) results always to true.
I understand that 1.0 as a float is not equal to 1 as integer
because of finite precision. But since the comparison is
performed with the same type (float32) as the result of the division,
this should not be a problem.
Correct me if I am wrong, but I tested it that in C++, java
and jitter (see the patch bellow) with 32bit floats (it works also
with 64bit floats).

thanks a lot for your patience
this was a loooooong one
George

#P toggle 386 256 15 0;
#P window setfont "Sans Serif" 9.;
#P window linecount 1;
#P newex 386 228 84 9109513 if $f1==$f2 then 1;
#P toggle 482 253 15 0;
#P newex 482 229 34 9109513 == 1.;
#P toggle 236 312 15 0;
#P newex 236 284 84 9109513 if $f1==1.0 then 1;
#P toggle 347 256 15 0;
#P newex 347 230 29 9109513 == 1.;
#P toggle 284 258 15 0;
#P newex 284 229 29 9109513 == 1.;
#P newex 347 128 61 9109513 expr $f1/$f2;
#P newex 284 127 60 9109513 expr $f1/$f1;
#P toggle 106 260 15 0;
#P newex 106 232 50 9109513 == 1.;
#P newex 106 117 115 9109513 t b f;
#P newex 106 208 40 9109513 jit.iter;
#P window linecount 2;
#P newex 106 145 89 9109513 jit.matrix 1 float32 1 @thru 1;
#P window linecount 1;
#P newex 106 185 115 9109513 jit.op 1 float32 1 @op /;
#B color 5;
#P toggle 245 257 15 0;
#P newex 245 231 34 9109513 == 1.;
#P flonum 171 59 74 9 0 0 0 139 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 245 129 27 9109513 / 1.;
#P window linecount 2;
#P comment 152 25 201 9109513 10.03 produces wrong result in max and correct result in jitter in my windows XP;
#P window linecount 3;
#P comment 373 25 196 9109513 scroll the numbers with the mouse to see that the only object that does not always results to 1. is the [/ 1.];
#P window setfont "Sans Serif" 14.;
#P window linecount 1;
#P comment 144 343 342 9109518 These toggles should be the same… but they are not;
#P window setfont "Sans Serif" 9.;
#P comment 205 257 40 9109513 ———>;
#P comment 498 253 40 9109513 < ---------;
#P fasten 6 0 12 0 176 77 111 77;
#P fasten 12 1 10 0 216 140 111 140;
#P connect 12 0 10 0;
#P connect 10 0 9 0;
#P connect 9 0 11 0;
#P connect 11 0 13 0;
#P connect 13 0 14 0;
#P fasten 10 0 9 1 111 181 216 181;
#P fasten 5 0 21 0 250 220 241 220;
#P connect 21 0 22 0;
#P fasten 6 0 5 0 176 101 250 101;
#P connect 5 0 7 0;
#P connect 7 0 8 0;
#P fasten 6 0 5 1 176 101 267 101;
#P fasten 6 0 15 0 176 91 289 91;
#P lcolor 13;
#P connect 15 0 17 0;
#P connect 17 0 18 0;
#P fasten 6 0 16 0 176 80 352 80;
#P lcolor 5;
#P connect 16 0 19 0;
#P connect 19 0 20 0;
#P fasten 5 0 25 0 250 188 391 188;
#P lcolor 5;
#P connect 25 0 26 0;
#P fasten 6 0 16 1 176 80 403 80;
#P lcolor 5;
#P fasten 15 0 25 1 289 181 465 181;
#P lcolor 3;
#P fasten 5 0 23 0 250 174 487 174;
#P lcolor 8;
#P connect 23 0 24 0;
#P fasten 15 0 23 1 289 165 511 165;
#P lcolor 8;
#P window clipboard copycount 27;


March 28, 2008 | 10:15 pm

/~ optimizes division by a constant. Float division is expensive, taking about five times longer than float multiplication.

So [/~ 3] does not divide every sample by three. It calculates the inverse (1.0/3.0) once and only once and stores the result, then multiplies every incoming sample by 0.333333 (actually more like 0.333332975).

I said you needed to read the fine print of /~. Cf. p.17 MSP Reference Manual.

I really oughta start charging for this.


March 29, 2008 | 10:27 am

Anyhow, this implies that only with integers it is safe to do comparisons. Floats should be tested for being within some range. The ==~ object is of an optimistic kind.

_
johan


March 29, 2008 | 11:11 am

I was taught 40 years ago to never compare floating point values for equality. If you’re going to test, do something like abs(x-y)< ε where ε is some appropriately small value.

This is the first rule of digital floating point arithmetic. Learn it.

The second rule is "never say never" and since the development and implementation of the IEEE 754 standard you can actually test floats for equality. Sometimes. Knowing when is advanced programming. If you haven’t learned the first rule yet, don’t even think about the second one.


March 29, 2008 | 11:12 am

I was taught 40 years ago to never compare floating point values for equality. If you’re going to test, do something like abs(x-y)< ε where ε is some appropriately small value.

This is the first rule of digital floating point arithmetic. Learn it.

The second rule is "never say never" and since the development and implementation of the IEEE 754 standard you can actually test floats for equality. Sometimes. Knowing when is advanced programming. If you haven’t learned the first rule yet, don’t even think about the second one.


Viewing 9 posts - 1 through 9 (of 9 total)