#Floating point difference between C++ and zig code

1 messages · Page 1 of 1 (latest)

lilac fog
#

Hi I'm rewriting a c++ library in zig and there's a few functions that I've attempted to port over but there is floating point error even though I thought it looks like it does the exact same thing. I've attached the files:

thread 11060 panic: Mismatch in solution 0 of 1: Cpp: 2.2549496033751737e0, Zig: 2.254949603375173e0 (a: 1.3475418090820312e-3, b: -1.0535717010498047e-2, c: 3.935861587524414e-2, d: -5.063056945800781e-2)
#

I'm 90% sure the zig one is broken somewhere because it causes artifacts if I use it

#

but I have no idea how to find it

#

I corrected the t = std.math.cos(t); to t = std.math.acos(t); but still same issue

#

I'm super sure its occurring somewhere in the cubic solver

#

It's a very small bit off but I need it to match exactly

fickle nexus
#

It may be that the difference is not the calculation, but a difference in how floating point values are converted to text.

lilac fog
#

both are getting the same f64s

#

but the zig one is producing ones that differ from C++

#

I'm checking with approxEqRel too when I should be checking by direct comparison

#

because its basically the same code it should give the exact same values right?

fickle nexus
#

Just proposing a variable to eliminate. I'd write the binary values to files and compare the bits.

lilac fog
south swan
#

Does the C++ lib use the -ffast-math flag?

verbal flint
#

the differences reported are tiny, I kinda doubt it is causing the artifacts

lilac fog
lilac fog
#

While the C++ version doesn't

#

Ill try using the libc acos

sturdy wraith
#

the only IEEE 754 float ops that are hard-specified to require implementations to produce correctly rounded results are addition, subtraction, multiplication, division, fused multiply-add and square root. trancendental functions like sin/cos are not guaranteed to be correctly rounded (implementers are recommended to round correctly, but for f64/f128 this is infeasible in practice) and will in practice often differ between math library implementations

#

so if you want bit-by-bit reproducible results you need to use the exact same math library compiled with the exact same compiler settings

lilac fog
#

Ill test by using the libc variants of the functions

lilac fog
#

I think I found out why:

#

seems like there's a small difference in precision when dividing

#

same operands but the zig one has less precision it looks like

#

or maybe the c++ one is wrong

lilac fog
#

Ok I just increased the precision to f80 and it seems to not have the artifacts i mentioned previously anymore

sturdy wraith
#

if you're comparing precision by printing values you should either print using the hexadecimal float format or print the byte values directly

#

the results of a simple division should not vary between c++ and zig unless you're deliberately messing around with things like rounding modes

lilac fog
#

but if it's on strict it should be doing basically the same thing right?

sturdy wraith
#

the default is strict so it shouldn't change anything

#

but once again, the only way to get the exact same results between c++ and zig is to use the exact same math routine implementations. this means that you can't use std.math or @cos()/@sin() (the only builtin that is safe is @sqrt()), you have to explicitly use the math functions from libc even from zig and you need to ensure that zig and c++ both use the exact same libc, not just any libc

#

I'm not very knowledgeable about c++ but you might also want to check your assumptions about how floating point math works in c++ and whether there are any external factors that can affect results. some languages are allowed to secretly promote f64 to a higher precision like f80 behind the scenes for greater precision for intermediate results

verbal flint
lilac fog
#

I'm on 0.15.0-dev.666

#

so yeah a bit behind