Primitive ratnum operations implemented.
authorTim Vaughan <tgvaughan@gmail.com>
Tue, 20 Dec 2016 07:05:56 +0000 (20:05 +1300)
committerTim Vaughan <tgvaughan@gmail.com>
Sun, 15 Jan 2017 08:01:21 +0000 (21:01 +1300)
src/integer.4th [new file with mode: 0644]
src/scheme-library.scm
src/scheme-primitives.4th
src/scheme.4th

diff --git a/src/integer.4th b/src/integer.4th
new file mode 100644 (file)
index 0000000..3ecabfc
--- /dev/null
@@ -0,0 +1,32 @@
+\ Integer arithmetic words
+
+: sort-pair
+    2dup > if
+        swap
+    then
+;
+
+( Find the GCD of n1 and n2 where n2 < n1. )
+: gcd ( n1 n2 -- m )
+    sort-pair
+    over 0= if
+        swap drop
+    else
+        over mod
+        recurse
+    then
+;
+
+: simplify ( n d -- n' d' )
+    swap dup 0< -rot abs swap
+    2dup gcd 
+    swap over ( b n1 c n2 c )
+    / ( b n1 c n2' )
+    -rot / ( b n2' n1' )
+
+    rot if
+        negate
+    then
+
+    swap
+;
index f8c0ec4..85580fd 100644 (file)
 
 ;; NUMBERS
 
+; Rational primitives
+
+(define (numerator x)
+  (if (ratnum? x)
+    (rat:numerator x)
+    x))
+
+(define (denominator x)
+  (if (ratnum? x)
+    (rat:denominator x)
+    (if (fixnum? x)
+      1
+      1.0)))
+
+(define (rat:+ x y)
+  (make-rational (fix:+ (fix:* (numerator x) (denominator y))
+                        (fix:* (denominator x) (numerator y)))
+                 (fix:* (denominator x) (denominator y))))
+
+(define (rat:- x y)
+  (make-rational (fix:- (fix:* (numerator x) (denominator y))
+                        (fix:* (denominator x) (numerator y)))
+                 (fix:* (denominator x) (denominator y))))
+
+(define (rat:* x y)
+  (make-rational (fix:* (numerator x) (numerator y))
+                 (fix:* (denominator x) (denominator y))))
+
+(define (rat:/ x y)
+  (make-rational (fix:* (numerator x) (denominator y))
+                 (fix:* (denominator x) (numerator y))))
+
+(define (rat:1/ x)
+  (make-rational (denominator x) (numerator x)))
+
 ; Type dispatch and promotion
 
 (define (type-dispatch ops x)
index 7e123f7..ba48b9e 100644 (file)
     flonum-type istype? -rot 2drop boolean-type
 ; 1 make-fa-primitive flonum?
 
+:noname ( args -- boolobj )
+    ratnum-type istype? -rot 2drop boolean-type
+; 1 make-fa-primitive ratnum?
+
 :noname ( args -- boolobj )
     character-type istype? -rot 2drop boolean-type
 ; 1 make-fa-primitive char?
     swap abs swap
 ; 1 make-fa-primitive fix:abs
 
-: sort-pair
-    2dup > if
-        swap
-    then
-;
-
-( Find the GCD of n1 and n2 where n2 < n1. )
-: gcd ( n1 n2 -- m )
-    sort-pair
-    over 0= if
-        swap drop
-    else
-        over mod
-        recurse
-    then
-;
-
 :noname ( fixnum fixnum -- fixnum' )
     drop swap drop gcd fixnum-type
 ; 2 make-fa-primitive fix:gcd
     drop swap drop f/ fatan flonum-type
 ; 2 make-fa-primitive flo:atan2
 
+\ --- Rationals ---
+
+' make-rational 2 make-fa-primitive make-rational
+
+:noname ( ratnum -- fixnum )
+    drop pair-type car
+; 1 make-fa-primitive rat:numerator
+
+:noname ( ratnum -- fixnum )
+    drop pair-type cdr
+; 1 make-fa-primitive rat:denominator
 
 \ --- Conversion ---
 
index 5babf09..16939d3 100644 (file)
@@ -4,6 +4,7 @@ scheme definitions
 include term-colours.4th
 include defer-is.4th
 include catch-throw.4th
+include integer.4th
 include float.4th
 
 include debugging.4th
@@ -25,6 +26,7 @@ variable nexttype
 
 make-type fixnum-type
 make-type flonum-type
+make-type ratnum-type
 make-type boolean-type
 make-type character-type
 make-type string-type
@@ -786,6 +788,42 @@ parse-idx-stack parse-idx-sp !
     pop-parse-idx
 ;
 
+: ratnum? ( -- bool )
+    push-parse-idx
+
+    minus? plus? or if
+        inc-parse-idx
+    then
+
+    digit? invert if
+        pop-parse-idx false exit
+    else
+        inc-parse-idx
+    then
+
+    begin digit? while
+        inc-parse-idx
+    repeat
+
+    [char] / nextchar <> if
+        pop-parse-idx false exit
+    else
+        inc-parse-idx
+    then
+
+    digit? invert if
+        pop-parse-idx false exit
+    else
+        inc-parse-idx
+    then
+
+    begin digit? while
+        inc-parse-idx
+    repeat
+
+    delim? pop-parse-idx
+;
+
 : boolean? ( -- bool )
     nextchar [char] # <> if false exit then
 
@@ -906,6 +944,23 @@ parse-idx-stack parse-idx-sp !
     flonum-type
 ;
 
+: make-rational ( fixnum fixnum -- ratnum|fixnum )
+    drop swap drop
+    simplify
+
+    dup 1 = if
+        drop fixnum-type
+    else
+        fixnum-type swap fixnum-type
+        cons drop ratnum-type
+    then
+;
+
+: readratnum ( -- ratnum )
+    readfixnum inc-parse-idx readfixnum
+    make-rational
+;
+
 : readbool ( -- bool-obj )
     inc-parse-idx
     
@@ -1032,6 +1087,11 @@ parse-idx-stack parse-idx-sp !
         exit
     then
 
+    ratnum? if
+        readratnum
+        exit
+    then
+
     boolean? if
         readbool
         exit
@@ -1122,6 +1182,7 @@ parse-idx-stack parse-idx-sp !
     boolean-type istype? if true exit then
     fixnum-type istype? if true exit then
     flonum-type istype? if true exit then
+    ratnum-type istype? if true exit then
     character-type istype? if true exit then
     string-type istype? if true exit then
     nil-type istype? if true exit then
@@ -1615,6 +1676,11 @@ hide env
 
 : printflonum ( flonum -- ) drop f. ;
 
+: printratnum ( ratnum -- )
+    drop pair-type 2dup
+    car print ." /" cdr print
+;
+
 : printbool ( bool -- )
     drop if
         ." #t"
@@ -1686,6 +1752,7 @@ hide env
 :noname ( obj -- )
     fixnum-type istype? if printfixnum exit then
     flonum-type istype? if printflonum exit then
+    ratnum-type istype? if printratnum exit then
     boolean-type istype? if printbool exit then
     character-type istype? if printchar exit then
     string-type istype? if printstring exit then