mirror of
https://github.com/ashinn/chibi-scheme.git
synced 2025-05-19 05:39:18 +02:00
supporting non-native endianness and non-finite floating values
This commit is contained in:
parent
9af77c9b4f
commit
3aae0e8481
2 changed files with 175 additions and 142 deletions
|
@ -9,12 +9,16 @@
|
||||||
integer->bytevector bytevector->integer
|
integer->bytevector bytevector->integer
|
||||||
integer->hex-string hex-string->integer
|
integer->hex-string hex-string->integer
|
||||||
bytevector->hex-string hex-string->bytevector
|
bytevector->hex-string hex-string->bytevector
|
||||||
|
bytevector-ieee-single-ref
|
||||||
bytevector-ieee-single-native-ref
|
bytevector-ieee-single-native-ref
|
||||||
|
bytevector-ieee-single-set!
|
||||||
bytevector-ieee-single-native-set!
|
bytevector-ieee-single-native-set!
|
||||||
|
bytevector-ieee-double-ref
|
||||||
bytevector-ieee-double-native-ref
|
bytevector-ieee-double-native-ref
|
||||||
|
bytevector-ieee-double-set!
|
||||||
bytevector-ieee-double-native-set!
|
bytevector-ieee-double-native-set!
|
||||||
)
|
)
|
||||||
(import (scheme base))
|
(import (scheme base) (scheme inexact))
|
||||||
(cond-expand
|
(cond-expand
|
||||||
(big-endian
|
(big-endian
|
||||||
(begin
|
(begin
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
;;; Copyright (c) 2004-2018 by Alex Shinn.
|
;;; Copyright (c) 2004-2018 by Alex Shinn.
|
||||||
|
|
||||||
;; Adapted from SRFI-56.
|
;; Adapted from SRFI 56.
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; syntax
|
;; syntax
|
||||||
|
@ -12,6 +12,22 @@
|
||||||
((combine b1 b2 b3 ...)
|
((combine b1 b2 b3 ...)
|
||||||
(combine (+ (arithmetic-shift b1 8) b2) b3 ...))))
|
(combine (+ (arithmetic-shift b1 8) b2) b3 ...))))
|
||||||
|
|
||||||
|
(define-syntax bytes-u8-set-all!
|
||||||
|
(syntax-rules ()
|
||||||
|
((_) bv off i)
|
||||||
|
((_ bv off i b1) (bytevector-u8-set! bv (+ off i) b1))
|
||||||
|
((_ bv off i b1 b2 b3 ...)
|
||||||
|
(begin
|
||||||
|
(bytevector-u8-set! bv (+ off i) b1)
|
||||||
|
(bytes-u8-set-all! bv off (+ i 1) b2 b3 ...)))))
|
||||||
|
|
||||||
|
(define-syntax bytevector-u8-set-all!
|
||||||
|
(syntax-rules ()
|
||||||
|
((_ bvapp iapp b1 ...)
|
||||||
|
(let ((bv bvapp)
|
||||||
|
(i iapp))
|
||||||
|
(bytes-u8-set-all! bv i 0 b1 ...)))))
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; reading floating point numbers
|
;; reading floating point numbers
|
||||||
|
|
||||||
|
@ -26,12 +42,11 @@
|
||||||
;; http://babbage.cs.qc.edu/courses/cs341/IEEE-754references.html
|
;; http://babbage.cs.qc.edu/courses/cs341/IEEE-754references.html
|
||||||
;; as references to IEEE 754.
|
;; as references to IEEE 754.
|
||||||
|
|
||||||
(define (bytevector-ieee-single-native-ref bytevector k)
|
(define (bytevector-ieee-single-ref bytevector k endianness)
|
||||||
(define (mantissa expn b2 b3 b4)
|
(define (mantissa expn b2 b3 b4)
|
||||||
(case expn ; recognize special literal exponents
|
(case expn
|
||||||
((255)
|
((255) ; special exponents
|
||||||
;;(if (zero? (combine b2 b3 b4)) +/0. 0/0.) ; XXXX for SRFI-70
|
(if (zero? (combine b2 b3 b4)) (/ 1. 0.) (/ 0. 0.)))
|
||||||
#f)
|
|
||||||
((0) ; denormalized
|
((0) ; denormalized
|
||||||
(inexact (* (expt 2.0 (- 1 (+ 127 23))) (combine b2 b3 b4))))
|
(inexact (* (expt 2.0 (- 1 (+ 127 23))) (combine b2 b3 b4))))
|
||||||
(else
|
(else
|
||||||
|
@ -44,20 +59,24 @@
|
||||||
(mantissa (* 2 b1) b2 b3 b4)))
|
(mantissa (* 2 b1) b2 b3 b4)))
|
||||||
(define (sign b1 b2 b3 b4)
|
(define (sign b1 b2 b3 b4)
|
||||||
(if (> b1 127) ; 1st bit of b1 is sign
|
(if (> b1 127) ; 1st bit of b1 is sign
|
||||||
(cond ((exponent (- b1 128) b2 b3 b4) => -) (else #f))
|
(- (exponent (- b1 128) b2 b3 b4))
|
||||||
(exponent b1 b2 b3 b4)))
|
(exponent b1 b2 b3 b4)))
|
||||||
(let* ((b1 (bytevector-u8-ref bytevector (+ k 0)))
|
(let* ((b1 (bytevector-u8-ref bytevector (+ k 0)))
|
||||||
(b2 (bytevector-u8-ref bytevector (+ k 1)))
|
(b2 (bytevector-u8-ref bytevector (+ k 1)))
|
||||||
(b3 (bytevector-u8-ref bytevector (+ k 2)))
|
(b3 (bytevector-u8-ref bytevector (+ k 2)))
|
||||||
(b4 (bytevector-u8-ref bytevector (+ k 3))))
|
(b4 (bytevector-u8-ref bytevector (+ k 3))))
|
||||||
(if (eq? (native-endianness) 'big)
|
(if (eq? endianness 'big)
|
||||||
(sign b1 b2 b3 b4)
|
(sign b1 b2 b3 b4)
|
||||||
(sign b4 b3 b2 b1))))
|
(sign b4 b3 b2 b1))))
|
||||||
|
|
||||||
(define (bytevector-ieee-double-native-ref bytevector k)
|
(define (bytevector-ieee-single-native-ref bytevector k)
|
||||||
|
(bytevector-ieee-single-ref bytevector k (native-endianness)))
|
||||||
|
|
||||||
|
(define (bytevector-ieee-double-ref bytevector k endianness)
|
||||||
(define (mantissa expn b2 b3 b4 b5 b6 b7 b8)
|
(define (mantissa expn b2 b3 b4 b5 b6 b7 b8)
|
||||||
(case expn ; recognize special literal exponents
|
(case expn
|
||||||
((255) #f) ; won't handle NaN and +/- Inf
|
((255) ; special exponents
|
||||||
|
(if (zero? (combine b2 b3 b4 b5 b6 b7 b8)) (/ 1. 0.) (/ 0. 0.)))
|
||||||
((0) ; denormalized
|
((0) ; denormalized
|
||||||
(inexact (* (expt 2.0 (- 1 (+ 1023 52)))
|
(inexact (* (expt 2.0 (- 1 (+ 1023 52)))
|
||||||
(combine b2 b3 b4 b5 b6 b7 b8))))
|
(combine b2 b3 b4 b5 b6 b7 b8))))
|
||||||
|
@ -72,8 +91,7 @@
|
||||||
b3 b4 b5 b6 b7 b8))
|
b3 b4 b5 b6 b7 b8))
|
||||||
(define (sign b1 b2 b3 b4 b5 b6 b7 b8)
|
(define (sign b1 b2 b3 b4 b5 b6 b7 b8)
|
||||||
(if (> b1 127) ; 1st bit of b1 is sign
|
(if (> b1 127) ; 1st bit of b1 is sign
|
||||||
(cond ((exponent (- b1 128) b2 b3 b4 b5 b6 b7 b8) => -)
|
(- (exponent (- b1 128) b2 b3 b4 b5 b6 b7 b8))
|
||||||
(else #f))
|
|
||||||
(exponent b1 b2 b3 b4 b5 b6 b7 b8)))
|
(exponent b1 b2 b3 b4 b5 b6 b7 b8)))
|
||||||
(let* ((b1 (bytevector-u8-ref bytevector (+ k 0)))
|
(let* ((b1 (bytevector-u8-ref bytevector (+ k 0)))
|
||||||
(b2 (bytevector-u8-ref bytevector (+ k 1)))
|
(b2 (bytevector-u8-ref bytevector (+ k 1)))
|
||||||
|
@ -83,10 +101,13 @@
|
||||||
(b6 (bytevector-u8-ref bytevector (+ k 5)))
|
(b6 (bytevector-u8-ref bytevector (+ k 5)))
|
||||||
(b7 (bytevector-u8-ref bytevector (+ k 6)))
|
(b7 (bytevector-u8-ref bytevector (+ k 6)))
|
||||||
(b8 (bytevector-u8-ref bytevector (+ k 7))))
|
(b8 (bytevector-u8-ref bytevector (+ k 7))))
|
||||||
(if (eq? (native-endianness) 'big)
|
(if (eq? endianness 'big)
|
||||||
(sign b1 b2 b3 b4 b5 b6 b7 b8)
|
(sign b1 b2 b3 b4 b5 b6 b7 b8)
|
||||||
(sign b8 b7 b6 b5 b4 b3 b2 b1))))
|
(sign b8 b7 b6 b5 b4 b3 b2 b1))))
|
||||||
|
|
||||||
|
(define (bytevector-ieee-double-native-ref bytevector k)
|
||||||
|
(bytevector-ieee-double-ref bytevector k (native-endianness)))
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; writing floating point numbers
|
;; writing floating point numbers
|
||||||
|
|
||||||
|
@ -117,8 +138,12 @@
|
||||||
(else
|
(else
|
||||||
(proc (exact (round n)) e))))))))
|
(proc (exact (round n)) e))))))))
|
||||||
|
|
||||||
(define (bytevector-ieee-single-native-set! bytevector k num)
|
(define (bytevector-ieee-single-set! bytevector k num endianness)
|
||||||
(define (bytes)
|
(define output
|
||||||
|
(if (eq? endianness 'big)
|
||||||
|
(lambda (b1 b2 b3 b4) (bytevector-u8-set-all! bytevector k b1 b2 b3 b4))
|
||||||
|
(lambda (b1 b2 b3 b4) (bytevector-u8-set-all! bytevector k b4 b3 b2 b1))))
|
||||||
|
(define (compute)
|
||||||
(call-with-mantissa&exponent num 2 23 8
|
(call-with-mantissa&exponent num 2 23 8
|
||||||
(lambda (f e)
|
(lambda (f e)
|
||||||
(let ((e0 (+ e 127 23)))
|
(let ((e0 (+ e 127 23)))
|
||||||
|
@ -128,9 +153,9 @@
|
||||||
(b2 (bit-field f1 16 24)) ; mant:16-23
|
(b2 (bit-field f1 16 24)) ; mant:16-23
|
||||||
(b3 (bit-field f1 8 16)) ; mant:8-15
|
(b3 (bit-field f1 8 16)) ; mant:8-15
|
||||||
(b4 (bit-field f1 0 8))) ; mant:0-7
|
(b4 (bit-field f1 0 8))) ; mant:0-7
|
||||||
(list (if (negative? num) 128 0) b2 b3 b4)))
|
(output (if (negative? num) 128 0) b2 b3 b4)))
|
||||||
((> e0 255) ; XXXX here we just write infinity
|
((> e0 255) ; infinity
|
||||||
(list (if (negative? num) 255 127) 128 0 0))
|
(output (if (negative? num) 255 127) 128 0 0))
|
||||||
(else
|
(else
|
||||||
(let* ((b0 (arithmetic-shift e0 -1))
|
(let* ((b0 (arithmetic-shift e0 -1))
|
||||||
(b1 (if (negative? num) (+ b0 128) b0)) ; sign + exp:1-7
|
(b1 (if (negative? num) (+ b0 128) b0)) ; sign + exp:1-7
|
||||||
|
@ -139,18 +164,23 @@
|
||||||
(bit-field f 16 23))) ; + mant:16-23
|
(bit-field f 16 23))) ; + mant:16-23
|
||||||
(b3 (bit-field f 8 16)) ; mant:8-15
|
(b3 (bit-field f 8 16)) ; mant:8-15
|
||||||
(b4 (bit-field f 0 8))) ; mant:0-7
|
(b4 (bit-field f 0 8))) ; mant:0-7
|
||||||
(list b1 b2 b3 b4))))))))
|
(output b1 b2 b3 b4))))))))
|
||||||
(let ((result (cond
|
(cond
|
||||||
((zero? num) '(0 0 0 0))
|
((zero? num) (output 0 0 0 0))
|
||||||
((eq? (native-endianness) 'big) (bytes))
|
((nan? num) (output #xff #xff #xff #xff))
|
||||||
(else (reverse (bytes))))))
|
(else (compute))))
|
||||||
(bytevector-u8-set! bytevector (+ k 0) (list-ref result 0))
|
|
||||||
(bytevector-u8-set! bytevector (+ k 1) (list-ref result 1))
|
|
||||||
(bytevector-u8-set! bytevector (+ k 2) (list-ref result 2))
|
|
||||||
(bytevector-u8-set! bytevector (+ k 3) (list-ref result 3))))
|
|
||||||
|
|
||||||
(define (bytevector-ieee-double-native-set! bytevector k num)
|
(define (bytevector-ieee-single-native-set! bytevector k num)
|
||||||
(define (bytes)
|
(bytevector-ieee-single-set! bytevector k num (native-endianness)))
|
||||||
|
|
||||||
|
(define (bytevector-ieee-double-set! bytevector k num endianness)
|
||||||
|
(define output
|
||||||
|
(if (eq? endianness 'big)
|
||||||
|
(lambda (b1 b2 b3 b4 b5 b6 b7 b8)
|
||||||
|
(bytevector-u8-set-all! bytevector k b1 b2 b3 b4 b5 b6 b7 b8))
|
||||||
|
(lambda (b1 b2 b3 b4 b5 b6 b7 b8)
|
||||||
|
(bytevector-u8-set-all! bytevector k b8 b7 b6 b5 b4 b3 b2 b1))))
|
||||||
|
(define (compute)
|
||||||
(call-with-mantissa&exponent num 2 52 11
|
(call-with-mantissa&exponent num 2 52 11
|
||||||
(lambda (f e)
|
(lambda (f e)
|
||||||
(let ((e0 (+ e 1023 52)))
|
(let ((e0 (+ e 1023 52)))
|
||||||
|
@ -164,9 +194,9 @@
|
||||||
(b6 (bit-field f1 16 24))
|
(b6 (bit-field f1 16 24))
|
||||||
(b7 (bit-field f1 8 16))
|
(b7 (bit-field f1 8 16))
|
||||||
(b8 (bit-field f1 0 8)))
|
(b8 (bit-field f1 0 8)))
|
||||||
(list (if (negative? num) 128 0) b2 b3 b4 b5 b6 b7 b8)))
|
(output (if (negative? num) 128 0) b2 b3 b4 b5 b6 b7 b8)))
|
||||||
((> e0 4095) ; infinity
|
((> e0 4095) ; infinity
|
||||||
(list (if (negative? num) 255 127) 224 0 0 0 0 0 0))
|
(output (if (negative? num) 255 127) 224 0 0 0 0 0 0))
|
||||||
(else
|
(else
|
||||||
(let* ((b0 (bit-field e0 4 11))
|
(let* ((b0 (bit-field e0 4 11))
|
||||||
(b1 (if (negative? num) (+ b0 128) b0))
|
(b1 (if (negative? num) (+ b0 128) b0))
|
||||||
|
@ -180,16 +210,15 @@
|
||||||
(b6 (bit-field f 16 24))
|
(b6 (bit-field f 16 24))
|
||||||
(b7 (bit-field f 8 16))
|
(b7 (bit-field f 8 16))
|
||||||
(b8 (bit-field f 0 8)))
|
(b8 (bit-field f 0 8)))
|
||||||
(list b1 b2 b3 b4 b5 b6 b7 b8))))))))
|
(output b1 b2 b3 b4 b5 b6 b7 b8))))))))
|
||||||
(let ((result (cond
|
(cond
|
||||||
((zero? num) '(0 0 0 0 0 0 0 0))
|
((zero? num) (output 0 0 0 0 0 0 0 0))
|
||||||
((eq? (native-endianness) 'big) (bytes))
|
((nan? num) (output #xff #xff #xff #xff #xff #xff #xff #xff))
|
||||||
(else (reverse (bytes))))))
|
(else (compute))))
|
||||||
(bytevector-u8-set! bytevector (+ k 0) (list-ref result 0))
|
|
||||||
(bytevector-u8-set! bytevector (+ k 1) (list-ref result 1))
|
(define (bytevector-ieee-double-native-set! bytevector k num)
|
||||||
(bytevector-u8-set! bytevector (+ k 2) (list-ref result 2))
|
(bytevector-ieee-double-set! bytevector k num (native-endianness)))
|
||||||
(bytevector-u8-set! bytevector (+ k 3) (list-ref result 3))
|
|
||||||
(bytevector-u8-set! bytevector (+ k 4) (list-ref result 4))
|
;; Local Variables:
|
||||||
(bytevector-u8-set! bytevector (+ k 5) (list-ref result 5))
|
;; eval: (put 'call-with-mantissa&exponent 'scheme-indent-function 4)
|
||||||
(bytevector-u8-set! bytevector (+ k 6) (list-ref result 6))
|
;; End:
|
||||||
(bytevector-u8-set! bytevector (+ k 7) (list-ref result 7))))
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue