added two aux libraries for parsing and formatting floating point
numbers.
This commit is contained in:
parent
b324709e86
commit
0cc2aae7dc
|
@ -1,5 +1,7 @@
|
|||
libikarusdir=$(pkglibdir)/ikarus
|
||||
dist_libikarus_DATA=ikarus/foreign.ss ikarus/ipc.ss ikarus/include.ss
|
||||
dist_libikarus_DATA= ikarus/foreign.ss ikarus/ipc.ss \
|
||||
ikarus/include.ss \
|
||||
ikarus/flonum-parser.sls ikarus/flonum-formatter.sls
|
||||
libCocoadir=$(pkglibdir)/Cocoa
|
||||
dist_libCocoa_DATA=Cocoa/helpers.ss
|
||||
|
||||
|
|
|
@ -162,7 +162,10 @@ top_build_prefix = @top_build_prefix@
|
|||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
libikarusdir = $(pkglibdir)/ikarus
|
||||
dist_libikarus_DATA = ikarus/foreign.ss ikarus/ipc.ss ikarus/include.ss
|
||||
dist_libikarus_DATA = ikarus/foreign.ss ikarus/ipc.ss \
|
||||
ikarus/include.ss \
|
||||
ikarus/flonum-parser.sls ikarus/flonum-formatter.sls
|
||||
|
||||
libCocoadir = $(pkglibdir)/Cocoa
|
||||
dist_libCocoa_DATA = Cocoa/helpers.ss
|
||||
dist_pkglib_DATA = match.ss gl.ss glut.ss \
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
;;; Copyright (c) 2009 Abdulaziz Ghuloum
|
||||
;;;
|
||||
;;; Permission is hereby granted, free of charge, to any person obtaining a
|
||||
;;; copy of this software and associated documentation files (the "Software"),
|
||||
;;; to deal in the Software without restriction, including without limitation
|
||||
;;; the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
;;; and/or sell copies of the Software, and to permit persons to whom the
|
||||
;;; Software is furnished to do so, subject to the following conditions:
|
||||
;;;
|
||||
;;; The above copyright notice and this permission notice shall be included in
|
||||
;;; all copies or substantial portions of the Software.
|
||||
;;;
|
||||
;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
;;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
;;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
;;; THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
;;; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
;;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
;;; DEALINGS IN THE SOFTWARE.
|
||||
|
||||
(library (ikarus flonum-formatter)
|
||||
(export ikarus-format-flonum)
|
||||
(import (rnrs))
|
||||
|
||||
(define (ikarus-format-flonum pos? digits expt)
|
||||
(define fixnum->string number->string)
|
||||
(define (next x)
|
||||
(if (null? x)
|
||||
(values #\0 '())
|
||||
(values (car x) (cdr x))))
|
||||
(define (format-flonum-no-expt expt d0 d*)
|
||||
(cond
|
||||
[(= expt 1)
|
||||
(cons d0 (if (null? d*) '(#\. #\0) (cons #\. d*)))]
|
||||
[else
|
||||
(cons d0
|
||||
(let-values ([(d0 d*) (next d*)])
|
||||
(format-flonum-no-expt (- expt 1) d0 d*)))]))
|
||||
(define (format-flonum-no-expt/neg expt d*)
|
||||
(cond
|
||||
[(= expt 0) d*]
|
||||
[else (cons #\0 (format-flonum-no-expt/neg (+ expt 1) d*))]))
|
||||
(define (sign pos? ls)
|
||||
(if pos?
|
||||
(list->string ls)
|
||||
(list->string (cons #\- ls))))
|
||||
(let ([d0 (car digits)] [d* (cdr digits)])
|
||||
(cond
|
||||
[(null? d*)
|
||||
(if (char=? d0 #\0)
|
||||
(if pos? "0.0" "-0.0")
|
||||
(if (= expt 1)
|
||||
(if pos?
|
||||
(string d0 #\. #\0)
|
||||
(string #\- d0 #\. #\0))
|
||||
(if (= expt 0)
|
||||
(if pos?
|
||||
(string #\0 #\. d0)
|
||||
(string #\- #\0 #\. d0))
|
||||
(string-append
|
||||
(if pos? "" "-")
|
||||
(string d0) "e" (fixnum->string (- expt 1))))))]
|
||||
[(and (null? d*) (char=? d0 #\0)) (if pos? "0.0" "-0.0")]
|
||||
[(<= 1 expt 9)
|
||||
(sign pos? (format-flonum-no-expt expt d0 d*))]
|
||||
[(<= -3 expt 0)
|
||||
(sign pos? (cons* #\0 #\. (format-flonum-no-expt/neg expt digits)))]
|
||||
[else
|
||||
(string-append
|
||||
(if pos? "" "-")
|
||||
(string d0) "." (list->string d*)
|
||||
"e" (fixnum->string (- expt 1)))]))))
|
|
@ -0,0 +1,167 @@
|
|||
;;; The code here is extracted from
|
||||
;;; ``Printing Floating-Point Numbers Quickly and Accurately''
|
||||
;;; http://www.cs.indiana.edu/~burger/FP-Printing-PLDI96.pdf
|
||||
;;; It is believed to be in the public domain.
|
||||
;;; The copyright below is for the R6RS implementation not part
|
||||
;;; of the original work.
|
||||
|
||||
;;; Copyright (c) 2009 Abdulaziz Ghuloum
|
||||
;;;
|
||||
;;; Permission is hereby granted, free of charge, to any person obtaining a
|
||||
;;; copy of this software and associated documentation files (the "Software"),
|
||||
;;; to deal in the Software without restriction, including without limitation
|
||||
;;; the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
;;; and/or sell copies of the Software, and to permit persons to whom the
|
||||
;;; Software is furnished to do so, subject to the following conditions:
|
||||
;;;
|
||||
;;; The above copyright notice and this permission notice shall be included in
|
||||
;;; all copies or substantial portions of the Software.
|
||||
;;;
|
||||
;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
;;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
;;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
;;; THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
;;; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
;;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
;;; DEALINGS IN THE SOFTWARE.
|
||||
|
||||
|
||||
|
||||
|
||||
;;; (parse-flonum <fl>
|
||||
;;; (lambda (positive? digits:list-of-chars exponent:int)
|
||||
;;; ---)
|
||||
;;; (lambda (inf/nan:string)
|
||||
;;; ---))
|
||||
;;; calls one of the two procedures depending on whether the
|
||||
;;; number has a real value or not.
|
||||
|
||||
(library (ikarus flonum-parser)
|
||||
(export parse-flonum)
|
||||
|
||||
(import (rnrs))
|
||||
|
||||
(define fxsll fxarithmetic-shift-left)
|
||||
(define fxsra fxarithmetic-shift-right)
|
||||
|
||||
(define (flonum-bytes f k)
|
||||
(let ([bv (make-bytevector 8)])
|
||||
(bytevector-ieee-double-set! bv 0 f (endianness big))
|
||||
(k (bytevector-u8-ref bv 0)
|
||||
(bytevector-u8-ref bv 1)
|
||||
(bytevector-u8-ref bv 2)
|
||||
(bytevector-u8-ref bv 3)
|
||||
(bytevector-u8-ref bv 4)
|
||||
(bytevector-u8-ref bv 5)
|
||||
(bytevector-u8-ref bv 6)
|
||||
(bytevector-u8-ref bv 7))))
|
||||
|
||||
(define (flonum-parts x)
|
||||
(flonum-bytes x
|
||||
(lambda (b0 b1 b2 b3 b4 b5 b6 b7)
|
||||
(values
|
||||
(zero? (fxand b0 128))
|
||||
(+ (fxsll (fxand b0 127) 4)
|
||||
(fxsra b1 4))
|
||||
(+ (+ b7 (fxsll b6 8) (fxsll b5 16))
|
||||
(* (+ b4
|
||||
(fxsll b3 8)
|
||||
(fxsll b2 16)
|
||||
(fxsll (fxand b1 #b1111) 24))
|
||||
(expt 2 24)))))))
|
||||
|
||||
(define flonum->digits
|
||||
(lambda (f e min-e p b B)
|
||||
;;; flonum v = f * b^e
|
||||
;;; p = precision (p >= 1)
|
||||
(let ([round? (even? f)])
|
||||
(if (>= e 0)
|
||||
(if (not (= f (expt b (- p 1))))
|
||||
(let ([be (expt b e)])
|
||||
(scale (* f be 2) 2 be be 0 B round? f e))
|
||||
(let* ([be (expt b e)] [be1 (* be b)])
|
||||
(scale (* f be1 2) (* b 2) be1 be 0 B round? f e)))
|
||||
(if (or (= e min-e) (not (= f (expt b (- p 1)))))
|
||||
(scale (* f 2) (* (expt b (- e)) 2) 1 1 0 B round? f e)
|
||||
(scale (* f b 2) (* (expt b (- 1 e)) 2) b 1 0 B round? f e))))))
|
||||
|
||||
(define (len n)
|
||||
(let f ([n n] [i 0])
|
||||
(cond
|
||||
[(zero? n) i]
|
||||
[else (f (div n 2) (+ i 1))])))
|
||||
|
||||
(define scale
|
||||
(lambda (r s m+ m- k B round? f e)
|
||||
(let ([est (exact
|
||||
(ceiling
|
||||
(- (* (+ e (len f) -1) (invlog2of B))
|
||||
1e-10)))])
|
||||
(if (>= est 0)
|
||||
(fixup r (* s (exptt B est)) m+ m- est B round?)
|
||||
(let ([scale (exptt B (- est))])
|
||||
(fixup (* r scale) s (* m+ scale) (* m- scale) est B round?))))))
|
||||
|
||||
(define fixup
|
||||
(lambda (r s m+ m- k B round?)
|
||||
(if ((if round? >= >) (+ r m+) s) ; too low?
|
||||
(values (+ k 1) (generate r s m+ m- B round?))
|
||||
(values k (generate (* r B) s (* m+ B) (* m- B) B round?)))))
|
||||
|
||||
(define (chr x)
|
||||
(vector-ref '#(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9) x))
|
||||
|
||||
(define generate
|
||||
(lambda (r s m+ m- B round?)
|
||||
(let-values ([(q r) (div-and-mod r s)])
|
||||
(let ([tc1 ((if round? <= <) r m-)]
|
||||
[tc2 ((if round? >= >) (+ r m+) s)])
|
||||
(if (not tc1)
|
||||
(if (not tc2)
|
||||
(cons (chr q) (generate (* r B) s (* m+ B) (* m- B) B round?))
|
||||
(list (chr (+ q 1))))
|
||||
(if (not tc2)
|
||||
(list (chr q))
|
||||
(if (< (* r 2) s)
|
||||
(list (chr q))
|
||||
(list (chr (+ q 1))))))))))
|
||||
|
||||
(define invlog2of
|
||||
(let ([table (make-vector 37)]
|
||||
[log2 (log 2)])
|
||||
(do ([B 2 (+ B 1)])
|
||||
((= B 37))
|
||||
(vector-set! table B (/ log2 (log B))))
|
||||
(lambda (B)
|
||||
(if (<= 2 B 36)
|
||||
(vector-ref table B)
|
||||
(/ log2 (log B))))))
|
||||
|
||||
(define exptt
|
||||
(let ([table (make-vector 326)])
|
||||
(do ([k 0 (+ k 1)] [v 1 (* v 10)])
|
||||
((= k 326))
|
||||
(vector-set! table k v))
|
||||
(lambda (B k)
|
||||
(if (and (= B 10) (<= 0 k 325))
|
||||
(vector-ref table k)
|
||||
(expt B k)))))
|
||||
|
||||
(define (convert-real-flonum pos? m e p k)
|
||||
(let-values ([(expt digits) (flonum->digits m e 10 p 2 10)])
|
||||
(k pos? digits expt)))
|
||||
|
||||
(define (parse-flonum x k0 k1)
|
||||
(assert (flonum? x))
|
||||
(assert (procedure? k0))
|
||||
(assert (procedure? k1))
|
||||
(let-values ([(pos? be m) (flonum-parts x)])
|
||||
(cond
|
||||
[(<= 1 be 2046) ; normalized flonum
|
||||
(convert-real-flonum pos? (+ m (expt 2 52)) (- be 1075) 53 k0)]
|
||||
[(= be 0)
|
||||
(convert-real-flonum pos? m -1074 52 k0)]
|
||||
[(= be 2047)
|
||||
(k1 (if (= m 0) (if pos? "+inf.0" "-inf.0") "+nan.0"))]
|
||||
[else (error 'flonum->string "cannot happen")]))))
|
||||
|
|
@ -1 +1 @@
|
|||
1819
|
||||
1820
|
||||
|
|
Loading…
Reference in New Issue