Dear @jan, dear @ridgeworks,
1- The unit test for swipl/rational/test_ieee754 fails under Windows, testing for the sign of the fractional part of “negative zero”.
assertion(float_parts(-0.0, -0.0, -0.0)), % fails
I tested it in a separate C snippet:
#include <stdio.h>
#include <math.h>
int main()
{
double u = -0.0 ;
double integ, fract ;
fract = modf(u, &integ) ;
fprintf(stderr, "u = %lf, integ = %lf, fract = %lf\n", u, integ, fract) ;
/* fix */
fract = copysign(modf(u, &integ), u) ;
fprintf(stderr, "copysign: integ = %lf, fract = %lf\n", integ, fract) ;
return 0 ;
}
The mistake can be fixed by an extra “copysign” :
$ ./a.exe
u = -0.000000, integ = -0.000000, fract = 0.000000
copysign: integ = -0.000000, fract = -0.000000
I guess, this would go into pl-arith.c (line 3800f)
case V_FLOAT:
{ double ip;
#ifdef MODF_BROKEN
r->value.f = copysign(modf(n1->value.f, &ip), n1->value.f);
#else
r->value.f = modf(n1->value.f, &ip);
#endif
r->type = V_FLOAT;
return check_float(r);
}
By the way, according to the MinGW sources (see below), the “ip” is not needed, so that this might work as well:
r->value.f = modf(n1->value.f, NULL);
2- Moreover, there’s a typo in a comment:
** <module> Test IEEEE754 float handling
The mistake can be fixed by removing one E
3- MinGW code for modf
/**
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the mingw-w64 runtime package.
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
*/
#include <fenv.h>
#include <math.h>
#include <errno.h>
double
modf (double value, double* iptr)
{
double int_part = 0.0;
/* truncate */
#if defined(_AMD64_) || defined(__x86_64__)
asm volatile ("subq $8, %%rsp\n"
"fnstcw 4(%%rsp)\n"
"movzwl 4(%%rsp), %%eax\n"
"orb $12, %%ah\n"
"movw %%ax, (%%rsp)\n"
"fldcw (%%rsp)\n"
"frndint\n"
"fldcw 4(%%rsp)\n"
"addq $8, %%rsp\n" : "=t" (int_part) : "0" (value) : "eax"); /* round */
#elif defined(_X86_) || defined(__i386__)
asm volatile ("push %%eax\n\tsubl $8, %%esp\n"
"fnstcw 4(%%esp)\n"
"movzwl 4(%%esp), %%eax\n"
"orb $12, %%ah\n"
"movw %%ax, (%%esp)\n"
"fldcw (%%esp)\n"
"frndint\n"
"fldcw 4(%%esp)\n"
"addl $8, %%esp\n\tpop %%eax\n" : "=t" (int_part) : "0" (value) : "eax"); /* round */
#else
int_part = trunc(value);
#endif
if (iptr)
*iptr = int_part;
return (isinf (value) ? 0.0 : value - int_part);
}