[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elk] reading rational numbers patch



On Mon, Feb 02, 2004 at 11:43:40AM +0100, Sam Hocevar wrote:
>    Yes, R5RS support is the plan for Elk 5.0. I plan to release 4.0
> (which is only R4RS compliant -- notice how the version numbers
> pleasantly match :D) when it has proved to be stable enough. The only

great.  ahh, i didn't notice that reading of rationals is not part of
R4RS...

> > issues when adding ratnum support (like exact/inexact stuff etc.)
> > that i am overlooking?
> 
>    I don't know. There are certainly issues that won't be noticed right

with the reader extension patch for rational numbers:

> (exact? 8/4)
#t

which seems to be true, since 8 and 4 are exact and / is in this case
an integer operation which produces exact results.  in the patch
Make_Reduced_Flonum() is used.

> 4.0 because it might be too big a change, but I will create a 4.99.*
> development series (which will lead to 5.0) and apply your patch to that

it's just a few lines inside Parse_Number in read.c.  seems to be
quite stable, since it worked for ten years on the original NeXTStep
version of the sound synthesis program...  but if it's not R4RS
conformant, it's possibly better to include it in the 4.99 branch.

all the best,

martin

diff -rpuN elk-trunk/src/read.c elk-trunk-patched/src/read.c
--- elk-trunk/src/read.c	2004-01-28 15:36:17.000000000 +0100
+++ elk-trunk-patched/src/read.c	2004-02-05 20:27:48.000000000 +0100
@@ -616,6 +616,7 @@ Object Parse_Number (Object port, char c
     int gotradix = 0, exact = 0, inexact = 0;
     unsigned int max;
     int maxdig;
+    int enumi, denom, slash = 0;
     Object ret;
 
     for ( ; *buf == '#'; buf++) {
@@ -651,10 +652,13 @@ Object Parse_Number (Object port, char c
         p++;
     for ( ; (c = *p); p++) {
         if (c == '.') {
-            if (expo || point++)
+            if (slash || expo || point++)
+                return Null;
+        } else if (c == '/') {
+            if (expo || point || slash++ || radix != 10)
                 return Null;
         } else if (radix != 16 && (c == 'e' || c == 'E')) {
-            if (expo++)
+            if (slash || expo++)
                 return Null;
             if (p[1] == '+' || p[1] == '-')
                 p++;
@@ -683,6 +687,11 @@ Object Parse_Number (Object port, char c
          */
         return Make_Flonum (atof (buf));
     }
+    if (slash) {
+        if (sscanf(buf, "%d/%d", &enumi, &denom) != 2)
+            return Null;
+        return Make_Reduced_Flonum (((double) enumi) / denom);
+    }
     max = (neg ? -(unsigned int)INT_MIN : INT_MAX);
     maxdig = max % radix;
     max /= radix;