fmod() unexpected sign
#1
fmod() unexpected sign
Hi there,

Im having a problem using fmod function (man fmod). On my O2 I get a signed result when it shouldnt be signed.

Could someone kindly try the following code and report back the result?

#include <stdio.h>
#include <math.h>

int main()
{
double a;

a = fmod(4.0L, 2.0L);

printf("a = %fL\n", a);

}

Compile with:

cc -o fmod fmod.c -lm

and

cc -o fmod fmod.c -lmx

My results are:

a = -0.000000 with both libraries.

The workaround I have found is to use drem() with -lm43 instead, which gives the expected result.

Strange.
TruHobbyist
Developer

Trade Count: (0)
Posts: 195
Threads: 21
Joined: May 2018
Find Reply
08-25-2019, 03:50 PM
#2
RE: fmod() unexpected sign
I can attest the sign being negative when executing the binary with either -lm or -lmx library

This violates C standard because the sign of the first operand should be preserved. But on the other hand, positive zero compares with negative zero.
You could wrap fmod into an other function and copy the sign from the x operand like
Code:
double fmodwrapper(double x, double y)
{
    double r = fmod(x,y);
    return abs(r)*sgn(x); /* not sure if C has a sign function like sgn, but it can be macro'd */
}
dexter1
Administrator

Trade Count: (1)
Posts: 297
Threads: 17
Joined: May 2018
Location: The Netherlands
Find Reply
08-26-2019, 01:49 PM
#3
RE: fmod() unexpected sign
(08-26-2019, 01:49 PM)dexter1 Wrote:  I can attest the sign being negative when executing the binary with either -lm or -lmx library

This violates C standard because the sign of the first operand should be preserved. But on the other hand, positive zero compares with negative zero.
You could wrap fmod into an other function and copy the sign from the x operand like
Code:
double fmodwrapper(double x, double y)
{
    double r = fmod(x,y);
    return abs(r)*sgn(x); /* not sure if C has a sign function like sgn, but it can be macro'd */
}

Hi dexter. First off, thanks for your help. It's alaways a pleasure to see you around.

This fmod bug is something to note for other projects. Surprisingly, the manpage states the correct behaviour for this function.

Thanks for the proposed workaround. Since there are only two cases when the sign is wrong, I've come up with my own inline sign correcting solution:

f = x >= 0.0L ? 1.0L : -1.0L;

if (((f == 1.0L) && (mod <= -0.0L)) || ((f == -1.0L) && (mod >= 0.0L)))
mod = -1.0L * mod;

Greets
TruHobbyist
Developer

Trade Count: (0)
Posts: 195
Threads: 21
Joined: May 2018
Find Reply
08-26-2019, 04:31 PM


Forum Jump:


Users browsing this thread: 1 Guest(s)