shithub: MicroHs

Download patch

ref: e94e1019b438c6a9a8361d7580ba7aebc62ce476
parent: 1435e35574c9dac90f3d29faf40989caf2130bc6
author: Lennart Augustsson <lennart.augustsson@epicgames.com>
date: Mon Sep 25 12:50:47 EDT 2023

Fix conversion from double to string.

--- a/README.md
+++ b/README.md
@@ -82,7 +82,7 @@
 But in general, the `Prelude` contains much, much less.
 
 ## Types
-There are some primitive data types, e.g `Int`, `Handle`, and `Double`.  These are known by the runtime system and various primitive operations work on them.  The function type, `->`, is (of course) also built in. The support for rendering (printing) `Double`s is a bit primitive, and only at most 6 decimal places will be shown. The actual value can contain more precise values, however.
+There are some primitive data types, e.g `Int`, `Handle`, and `Double`.  These are known by the runtime system and various primitive operations work on them.  The function type, `->`, is (of course) also built in.
 
 All other types are defined with the language.  They are converted to lambda terms using
 the Scott encoding.   The runtime system knows how lists are encoded and booleans are encoded.
--- a/src/runtime/eval.c
+++ b/src/runtime/eval.c
@@ -1618,6 +1618,9 @@
     case T_QUOT: ARITHBIN(/);
     case T_REM:  ARITHBIN(%);
     case T_SUBR: OPINT2(r = yi - xi); SETINT(n, r); RET;
+    case T_UQUOT: ARITHBINU(/);
+    case T_UREM:  ARITHBINU(%);
+
     case T_FADD: FARITHBIN(+);
     case T_FSUB: FARITHBIN(-);
     case T_FMUL: FARITHBIN(*);
@@ -1642,25 +1645,17 @@
     case T_FSHOW:
       // check that the double exists
       CHECK(1);
-
       // evaluate it
       xd = evaldouble(ARG(TOP(0)));
-
       // turn it into a string
-      char str[25];
-      int idx = snprintf(str, 25, "%f", xd);
-
-      /* C will render floats with potentially many training zeros, shave the
-      off by moving the NULL terminator */
-      for(int i = idx - 1; i >= 0; i--) {
-        if(str[i] == '.') {
-          str[i+2] = '\0'; // number is x.0, create {x, '.', '0', '\0'}
-          break;
-        }
-        if(str[i] != '0') {
-          str[i+1] = '\0';
-          break;
-        }
+      char str[30];
+      /* Using 16 decimals will lose some precision.
+       * 17 would keep the precision, but it frequently looks very ugly.
+       */
+      (void)snprintf(str, 25, "%.16g", xd);
+      if (!strchr(str, '.') && !strchr(str, 'e') && !strchr(str, 'E')) {
+        /* There is no decimal point and no exponent, so add a decimal point */
+        strcat(str, ".0");
       }
 
       // turn it into a mhs string
@@ -1669,11 +1664,8 @@
       // remove the double from the stack
       POP(1);
       n = TOP(-1);
-
       // update n to be s
       GOIND(s);
-    case T_UQUOT: ARITHBINU(/);
-    case T_UREM:  ARITHBINU(%);
 
     case T_EQ:   CMP(==);
     case T_NE:   CMP(!=);
--- a/tests/FArith.ref
+++ b/tests/FArith.ref
@@ -1,6 +1,6 @@
-[-200.686482,0.0,10068.766014,-153.668138,-47.018344,5350.793021,-100.343241,-100.343241,0.0,-100.343241,-100.343241,-0.0,-99.343241,-101.343241,-100.343241,-99.108706,-101.577776,-123.877266,3243434.002099,-3243634.688581,-325466748.506229,899.655759,-1100.342241,-100343.140657,-153.668138,47.018344,5350.793021,-106.649795,0.0,2843.544672,-53.324897,-53.324897,0.0,-53.324897,-53.324897,-0.0,-52.324897,-54.324897,-53.324897,-52.090362,-54.559433,-65.831464,3243481.020443,-3243587.670237,-172961135.854278,946.674103,-1053.323897,-53324.843975,-100.343241,100.343241,0.0,-53.324897,53.324897,0.0,-0.0,0.0,0.0,0.0,-0.0,-0.0,1.0,-1.0,-0.0,1.234535,-1.234535,-0.0,3243534.34534,-3243534.34534,-0.0,999.999,-999.999,-0.0,-100.343241,100.343241,-0.0,-53.324897,53.324897,-0.0,0.0,0.0,-0.0,0.0,0.0,0.0,1.0,-1.0,0.0,1.234535,-1.234535,0.0,3243534.34534,-3243534.34534,0.0,999.999,-999.999,0.0,-99.343241,101.343241,-100.343241,-52.324897,54.324897,-53.324897,1.0,1.0,-0.0,1.0,1.0,0.0,2.0,0.0,1.0,2.234535,-0.234535,1.234535,3243535.34534,-3243533.34534,3243534.34534,1000.999,-998.999,999.999,-99.108706,101.577776,-123.877266,-52.090362,54.559433,-65.831464,1.234535,1.234535,-0.0,1.234535,1.234535,0.0,2.234535,0.234535,1.234535,2.46907,0.0,1.524077,3243535.579875,-3243533.110805,4004257.419037,1001.233535,-998.764465,1234.533995,3243434.002099,3243634.688581,-325466748.506229,3243481.020443,3243587.670237,-172961135.854278,3243534.34534,3243534.34534,-0.0,3243534.34534,3243534.34534,0.0,3243535.34534,3243533.34534,3243534.34534,3243535.579875,3243533.110805,4004257.419037,6487068.69068,0.0,10520515049400.181641,3244534.34434,3242534.34634,3243531101.805655,899.655759,1100.342241,-100343.140657,946.674103,1053.323897,-53324.843975,999.999,999.999,-0.0,999.999,999.999,0.0,1000.999,998.999,999.999,1001.233535,998.764465,1234.533995,3244534.34434,-3242534.34634,3243531101.805655,1999.998,0.0,999998.000001]
+[-200.686482,0.0,10068.76601438408,-153.6681383,-47.0183437,5350.79302107415,-100.343241,-100.343241,0.0,-100.343241,-100.343241,-0.0,-99.34324100000001,-101.343241,-100.343241,-99.10870577,-101.57777623,-123.8772661068804,3243434.002099,-3243634.688581,-325466748.5062289,899.655759,-1100.342241,-100343.140656759,-153.6681383,47.0183437,5350.79302107415,-106.6497946,0.0,2843.544672055548,-53.3248973,-53.3248973,0.0,-53.3248973,-53.3248973,-0.0,-52.3248973,-54.3248973,-53.3248973,-52.09036207,-54.55943253,-65.83146435298188,3243481.0204427,-3243587.6702373,-172961135.8542782,946.6741027,-1053.3238973,-53324.8439751027,-100.343241,100.343241,0.0,-53.3248973,53.3248973,0.0,-0.0,0.0,0.0,0.0,-0.0,-0.0,1.0,-1.0,-0.0,1.23453523,-1.23453523,-0.0,3243534.34534,-3243534.34534,-0.0,999.999,-999.999,-0.0,-100.343241,100.343241,-0.0,-53.3248973,53.3248973,-0.0,0.0,0.0,-0.0,0.0,0.0,0.0,1.0,-1.0,0.0,1.23453523,-1.23453523,0.0,3243534.34534,-3243534.34534,0.0,999.999,-999.999,0.0,-99.34324100000001,101.343241,-100.343241,-52.3248973,54.3248973,-53.3248973,1.0,1.0,-0.0,1.0,1.0,0.0,2.0,0.0,1.0,2.23453523,-0.2345352300000001,1.23453523,3243535.34534,-3243533.34534,3243534.34534,1000.999,-998.999,999.999,-99.10870577,101.57777623,-123.8772661068804,-52.09036207,54.55943253,-65.83146435298188,1.23453523,1.23453523,-0.0,1.23453523,1.23453523,0.0,2.23453523,0.2345352300000001,1.23453523,2.46907046,0.0,1.524077234111153,3243535.57987523,-3243533.11080477,4004257.419037217,1001.23353523,-998.76446477,1234.53399546477,3243434.002099,3243634.688581,-325466748.5062289,3243481.0204427,3243587.6702373,-172961135.8542782,3243534.34534,3243534.34534,-0.0,3243534.34534,3243534.34534,0.0,3243535.34534,3243533.34534,3243534.34534,3243535.57987523,3243533.11080477,4004257.419037217,6487068.69068,0.0,10520515049400.18,3244534.34434,3242534.34634,3243531101.805655,899.655759,1100.342241,-100343.140656759,946.6741027,1053.3238973,-53324.8439751027,999.999,999.999,-0.0,999.999,999.999,0.0,1000.999,998.999,999.999,1001.23353523,998.76446477,1234.53399546477,3244534.34434,-3242534.34634,3243531101.805655,1999.998,0.0,999998.000001]
 [True,False,False,True,False,True,False,True,True,True,False,False,False,True,True,True,False,False,False,True,True,True,False,False,False,True,True,True,False,False,False,True,True,True,False,False,False,True,True,True,False,False,False,True,True,True,False,False,False,True,False,False,True,True,True,False,False,True,False,True,False,True,True,True,False,False,False,True,True,True,False,False,False,True,True,True,False,False,False,True,True,True,False,False,False,True,True,True,False,False,False,True,True,True,False,False,False,True,False,False,True,True,False,True,False,False,True,True,True,False,False,True,False,True,True,False,False,True,False,True,False,True,True,True,False,False,False,True,True,True,False,False,False,True,True,True,False,False,False,True,True,True,False,False,False,True,False,False,True,True,False,True,False,False,True,True,True,False,False,True,False,True,True,False,False,True,False,True,False,True,True,True,False,False,False,True,True,True,False,False,False,True,True,True,False,False,False,True,True,True,False,False,False,True,False,False,True,True,False,True,False,False,True,True,False,True,False,False,True,True,False,True,False,False,True,True,True,False,False,True,False,True,False,True,True,True,False,False,False,True,True,True,False,False,False,True,True,True,False,False,False,True,False,False,True,True,False,True,False,False,True,True,False,True,False,False,True,True,False,True,False,False,True,True,False,True,False,False,True,True,True,False,False,True,False,True,False,True,True,True,False,False,False,True,True,True,False,False,False,True,False,False,True,True,False,True,False,False,True,True,False,True,False,False,True,True,False,True,False,False,True,True,False,True,False,False,True,True,False,True,False,False,True,True,True,False,False,True,False,True,False,True,False,False,True,True,False,True,False,False,True,True,False,True,False,False,True,True,False,True,False,False,True,True,False,True,False,False,True,True,False,True,False,False,True,True,False,True,False,False,True,True,False,True,True,True,False,False,True,False,False,True,False,True]
-[2.234983,0.446997,0.223498,0.02235,1.232,0.2464,0.1232,0.01232,23.0,4.6,2.3,0.23]
-[-2.234983,0.446997,-0.223498,0.02235,-1.232,0.2464,-0.1232,0.01232,-23.0,4.6,-2.3,0.23]
+[2.234983,0.4469966,0.2234983,0.02234983,1.232,0.2464,0.1232,0.01232,23.0,4.6,2.3,0.23]
+[-2.234983,0.4469966,-0.2234983,0.02234983,-1.232,0.2464,-0.1232,0.01232,-23.0,4.6,-2.3,0.23]
 1.576
 3.5
--