shithub: femtolisp

Download patch

ref: 9bfee88015312110df5100c28e5db198e79dbd2b
parent: bac0583ae0eef43a040806983b74cd36c17cf6f4
author: Sigrid Solveig Haflínudóttir <ftrvxmtrx@gmail.com>
date: Mon Nov 30 07:25:37 EST 2020

fix more floating point issues

--- a/flmain.c
+++ b/flmain.c
@@ -30,7 +30,7 @@
     char fname_buf[1024];
 
 #ifdef __plan9__
-    setfcr(FPPDBL|FPRNR|FPINVAL|FPOVFL);
+    setfcr(FPPDBL|FPRNR|FPOVFL);
 #endif
 
     fl_init(512*1024);
--- a/llt/lltinit.c
+++ b/llt/lltinit.c
@@ -29,16 +29,21 @@
 
     ios_init_stdstreams();
 
+#ifdef __plan9__
+    D_PNAN = NaN();
+    D_NNAN = NaN(); *(u64int*)&D_NNAN |= 1<<31;
+    D_PINF = Inf(1);
+    D_NINF = Inf(-1);
+    u32int x;
+    x = 0x7fc00000; memcpy(&F_PNAN, &x, 4);
+    x = 0xffc00000; memcpy(&F_NNAN, &x, 4);
+    x = 0x7f800000; memcpy(&F_PINF, &x, 4);
+    x = 0xff800000; memcpy(&F_NINF, &x, 4);
+#else
     D_PNAN = strtod("+NaN",NULL);
     D_NNAN = -strtod("+NaN",NULL);
     D_PINF = strtod("+Inf",NULL);
     D_NINF = strtod("-Inf",NULL);
-#ifdef __plan9__
-    F_PNAN = D_PNAN;
-    F_NNAN = D_NNAN;
-    F_PINF = D_PINF;
-    F_NINF = D_NINF;
-#else
     F_PNAN = strtof("+NaN",NULL);
     F_NNAN = -strtof("+NaN",NULL);
     F_PINF = strtof("+Inf",NULL);
--- a/operators.c
+++ b/operators.c
@@ -3,15 +3,17 @@
 #include "ieee754.h"
 
 #ifdef __plan9__
-#define trunc(x) floor(x)
+STATIC_INLINE double fpart(double arg)
+{
+    return modf(arg, NULL);
+}
 #else
 extern double trunc(double x);
-#endif
-
 STATIC_INLINE double fpart(double arg)
 {
     return arg - trunc(arg);
 }
+#endif
 
 // given a number, determine an appropriate type for storing it
 #if 0
@@ -170,7 +172,11 @@
     case T_INT64:  return *(int64_t*)a < *(int64_t*)b;
     case T_UINT64: return *(uint64_t*)a < *(uint64_t*)b;
     case T_FLOAT:  return *(float*)a < *(float*)b;
-    case T_DOUBLE: return *(double*)a < *(double*)b;
+    case T_DOUBLE: return *(double*)a < *(double*)b
+#ifdef __plan9__
+    && !isNaN(*(double*)a) && !isNaN(*(double*)b)
+#endif
+    ;
     }
     return 0;
 }
@@ -187,7 +193,11 @@
     case T_INT64:  return *(int64_t*)a == *(int64_t*)b;
     case T_UINT64: return *(uint64_t*)a == *(uint64_t*)b;
     case T_FLOAT:  return *(float*)a == *(float*)b;
-    case T_DOUBLE: return *(double*)a == *(double*)b;
+    case T_DOUBLE: return *(double*)a == *(double*)b
+#ifdef __plan9__
+    && !isNaN(*(double*)a)
+#endif
+    ;
     }
     return 0;
 }
@@ -200,9 +210,14 @@
     double da = conv_to_double(a, atag);
     double db = conv_to_double(b, btag);
 
+#ifdef __plan9__
+    if (isNaN(da) || isNaN(db))
+        return 0;
+#endif
+
     // casting to double will only get the wrong answer for big int64s
     // that differ in low bits
-    if (da < db)
+    if (da < db && !isNaN(da) && !isNaN(db))
         return 1;
     if (db < da)
         return 0;