From 1317d29d0e4ac9cedd682bc43bca5e30a647244b Mon Sep 17 00:00:00 2001 From: Rose Hogenson Date: Mon, 8 Aug 2022 19:43:22 -0700 Subject: Fix the bugs in the number library. I did some extensive manual testing. Hopefully there are no bugs left :) --- lib/scheme/base/80-number.csc | 388 ++++++++++++++++++++++++------------------ 1 file changed, 218 insertions(+), 170 deletions(-) (limited to 'lib') diff --git a/lib/scheme/base/80-number.csc b/lib/scheme/base/80-number.csc index 20f8db8..171bbd0 100644 --- a/lib/scheme/base/80-number.csc +++ b/lib/scheme/base/80-number.csc @@ -55,7 +55,7 @@ (define (small-int? obj) - (call-builtin eq? 1 (call-builtin typeof obj))) + (call-builtin eq 1 (call-builtin typeof obj))) (define (integer? obj) @@ -66,15 +66,15 @@ (define (int=? n1 n2) (cond ((and (small-int? n1) (small-int? n2)) - (call-builtin eq? n1 n2)) + (call-builtin eq n1 n2)) ((and (boxed-int? n1) (boxed-int? n2)) (let ((n1-digits (boxed-int-digits n1)) (n2-digits (boxed-int-digits n2))) (and (boolean=? (boxed-int-positive? n1) (boxed-int-positive? n2)) - (call-builtin eq? (vector-length n1-digits) (vector-length n2-digits)) + (call-builtin eq (vector-length n1-digits) (vector-length n2-digits)) (let loop ((i 0)) - (if (call-builtin int n2 @@ -134,7 +135,7 @@ (define (zero? obj) - (call-builtin eq? 0 obj)) + (call-builtin eq 0 obj)) (define (odd? n) @@ -159,89 +160,84 @@ (define small-int-min (- #x4000000000000000)) ; -(2^62) - (define digit-mask #x2000000000000000) ; 2^61. Digits are 61-bit unsigned numbers. - + (define (digits n) + (if (small-int? n) + (vector n) + (boxed-int-digits n))) - (define (split-carry-bit n) - (values - (call-builtin div n digit-mask) - (call-builtin mod n digit-mask))) + ; adds two small positive ints. + (define (add2 x y) + (define z (call-builtin add x y)) + (if (negative? z) + (values 1 (call-builtin add + 1 + (call-builtin add + z + small-int-max))) + (values 0 z))) - (define (denormalized-int n) - (define-values (sgn n*) (if (int-positive? n) - (values #t n) - (values #f (- n)))) - (define-values (n2 n1) (split-carry-bit n*)) - (if (zero? n2) - (make-boxed-int sgn (vector n1)) - (make-boxed-int sgn (vector n1 n2)))) - - (define (big-int+ n1 n2) + (define (big-int+ x y) (cond - ((and (boxed-int-positive? n1) (boxed-int-negative? n2)) - (big-int- n1 (- n2))) - ((and (boxed-int-negative? n1) (boxed-int-positive? n2)) - (big-int- n2 (- n1))) - ((and (boxed-int-negative? n1) (boxed-int-negative? n2)) - (- (big-int+ (- n1) (- n2)))) + ((and (int-negative? x) (int-negative? y)) + (- (int+ (- x) (- y)))) + ((int-negative? x) + (int- y (- x))) + ((int-negative? y) + (int- x (- y))) (else - (let* ((n1-digits (boxed-int-digits n1)) - (n2-digits (boxed-int-digits n2)) - (n1-ndigits (vector-length n1-digits)) - (n2-ndigits (vector-length n2-digits)) - (out-digits (make-vector (max n1-ndigits - n2-ndigits)))) + (let* ((x-digits (digits x)) + (y-digits (digits y)) + (x-ndigits (vector-length x-digits)) + (y-ndigits (vector-length y-digits)) + (out-digits (make-vector (max x-ndigits + y-ndigits)))) (let loop ((i 0) (carry 0)) (cond - ((and (int? lo hi) + (error "binary search is hard")) ((negative? check) ; guess was too big - (loop lo guess)) + (loop lo (- guess 1))) ((int (gcd d1 d2))) (int)) (* (numerator x2) - (quotient d1 g)))))) + (quotient d1 >)))))) (define < @@ -640,7 +685,7 @@ (define (min x1 . xs) (let loop ((xs xs) - (m m1)) + (m x1)) (if (null? xs) m (loop (cdr xs) @@ -658,9 +703,9 @@ (else (let* ((d1 (denominator x1)) (d2 (denominator x2)) - (g (gcd d1 d2)) - (s1 (quotient d2 g)) - (s2 (quotient d1 g))) + (> (gcd d1 d2)) + (s1 (quotient d2 >)) + (s2 (quotient d1 >))) (/ (+ (* s1 (numerator x1)) (* s2 (numerator x2))) (* d1 s1)))))) @@ -695,6 +740,8 @@ (case-lambda ((z) (cond + ((int=? z small-int-min) + #x4000000000000000) ((small-int? z) (call-builtin sub 0 z)) ((boxed-int? z) @@ -717,14 +764,14 @@ (define (normalize-quotient q) - (when (negative? d) + (when (negative? q) (set! q (make-quotient (- (numerator q)) (- (denominator q))))) (let* ((n (numerator q)) (d (denominator q)) - (g (gcd n d))) - (make-quotient (quotient n g) - (quotient d g)))) + (> (gcd n d))) + (make-quotient (quotient n >) + (quotient d >)))) (define / @@ -738,8 +785,10 @@ (set! z1 (- z1)) (set! z2 (- z2))) (let ((g (gcd z1 z2))) - (make-quotient (quotient z1 g) - (quotient z2 g)))) + (if (= g z2) + (quotient z1 g) + (make-quotient (quotient z1 g) + (quotient z2 g))))) (else (* z1 (/ (denominator z2) @@ -801,12 +850,11 @@ (define (exact-integer-sqrt k) (if (zero? k) (values 0 0) - (let loop ((x (/ k 4))) ; initial estimate - (define y (/ (+ x (/ k x)) - 2)) ; 1/2 (x + k/x) - (if (> 1 (abs (- x y))) - (let ((s (truncate y))) - (values s (- k (* s s)))) + (let loop ((x (quotient k 2))) ; initial estimate + (define y (quotient (+ x (quotient k x)) + 2)) + (if (>= y x) + (values x (- k (square x))) (loop y))))) -- cgit v1.3.1