srfi-4.scm 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. ; Part of Scheme 48 1.9. See file COPYING for notices and license.
  2. ; Authors: David van Horn
  3. ; SRFI 4: Homogeneous numeric vector datatypes
  4. ; Does not include hacks to the reader (intentionally).
  5. (define (sub1 i) (- i 1))
  6. (define-syntax define-vector-types
  7. (syntax-rules ()
  8. ((define-vector-types spec ...)
  9. (begin (define-vector-type spec) ...))))
  10. (define-syntax define-vector-type
  11. (syntax-rules ()
  12. ((define-vector-type
  13. (size :tagvector
  14. tagvector? make-tagvector tagvector tagvector-length
  15. tagvector-ref tagvector-set! tagvector->list list->tagvector
  16. blob-ref blob-set!
  17. f->i i->f))
  18. (begin
  19. (define-record-type tagvector :tagvector
  20. (really-make-tagvector blob)
  21. tagvector?
  22. (blob tagvector-blob))
  23. (define make-tagvector
  24. (case-lambda
  25. ((n)
  26. (really-make-tagvector (make-blob (* size n))))
  27. ((n x)
  28. (let* ((v (really-make-tagvector (make-blob (* size n))))
  29. (b (tagvector-blob v)))
  30. (do ((i n (sub1 i)))
  31. ((zero? i) v)
  32. (blob-set! b (* size (sub1 i)) (f->i x)))))))
  33. (define (tagvector . elems)
  34. (let* ((n (length elems))
  35. (v (really-make-tagvector (make-blob (* size n))))
  36. (b (tagvector-blob v)))
  37. (do ((i n (sub1 i))
  38. (e (reverse elems) (cdr e)))
  39. ((zero? i) v)
  40. (blob-set! b (* size (sub1 i)) (f->i (car e))))))
  41. (define (tagvector-length v)
  42. (/ (blob-length (tagvector-blob v)) size))
  43. (define (tagvector-ref v i)
  44. (i->f (blob-ref (tagvector-blob v) (* size i))))
  45. (define (tagvector-set! v i n)
  46. (blob-set! (tagvector-blob v) (* size i) (f->i n)))
  47. (define (tagvector->list v)
  48. (map i->f
  49. (blob->uint-list size (endianness native) (tagvector-blob v))))
  50. (define (list->tagvector ls)
  51. (really-make-tagvector
  52. (uint-list->blob size (endianness native) (map f->i ls))))
  53. ))))
  54. (define-vector-types
  55. (1 :s8vector
  56. s8vector? make-s8vector s8vector s8vector-length
  57. s8vector-ref s8vector-set! s8vector->list list->s8vector
  58. blob-s8-ref blob-s8-set! no-op no-op)
  59. ;; u8vector is provided by SRFI 66.
  60. ;;(1 :u8vector
  61. ;; u8vector? make-u8vector u8vector u8vector-length
  62. ;; u8vector-ref u8vector-set! u8vector->list list->u8vector
  63. ;; blob-u8-ref blob-u8-set! no-op no-op)
  64. (2 :s16vector
  65. s16vector? make-s16vector s16vector s16vector-length
  66. s16vector-ref s16vector-set! s16vector->list list->s16vector
  67. blob-s16-native-ref blob-s16-native-set! no-op no-op)
  68. (2 :u16vector
  69. u16vector? make-u16vector u16vector u16vector-length
  70. u16vector-ref u16vector-set! u16vector->list list->u16vector
  71. blob-u16-native-ref blob-u16-native-set! no-op no-op)
  72. (4 :s32vector
  73. s32vector? make-s32vector s32vector s32vector-length
  74. s32vector-ref s32vector-set! s32vector->list list->s32vector
  75. blob-s32-native-ref blob-s32-native-set! no-op no-op)
  76. (4 :u32vector
  77. u32vector? make-u32vector u32vector u32vector-length
  78. u32vector-ref u32vector-set! u32vector->list list->u32vector
  79. blob-u32-native-ref blob-u32-native-set! no-op no-op)
  80. (8 :s64vector
  81. s64vector? make-s64vector s64vector s64vector-length
  82. s64vector-ref s64vector-set! s64vector->list list->s64vector
  83. blob-s64-native-ref blob-s64-native-set! no-op no-op)
  84. (8 :u64vector
  85. u64vector? make-u64vector u64vector u64vector-length u64vector-ref
  86. u64vector-set! u64vector->list list->u64vector
  87. blob-u64-native-ref blob-u64-native-set! no-op no-op)
  88. (4 :f32vector
  89. f32vector? make-f32vector f32vector f32vector-length f32vector-ref
  90. f32vector-set! f32vector->list list->f32vector
  91. blob-u32-native-ref blob-u32-native-set! fl->u32 u32->fl)
  92. (8 :f64vector
  93. f64vector? make-f64vector f64vector f64vector-length f64vector-ref
  94. f64vector-set! f64vector->list list->f64vector
  95. blob-u64-native-ref blob-u64-native-set! fl->u64 u64->fl))
  96. (define make-u8vector
  97. (case-lambda
  98. ((n)
  99. (srfi-66:make-u8vector n 0))
  100. ((n x)
  101. (srfi-66:make-u8vector n x))))
  102. ;; --
  103. ;; Flonum <-> Integer conversions.
  104. ;; Based on SRFI 56 Reference Implementation by Alex Shinn.
  105. ;; Both use big endian.
  106. (define (combine . bytes)
  107. (combine-ls bytes))
  108. (define (combine-ls bytes)
  109. (let loop ((b bytes) (acc 0))
  110. (if (null? b) acc
  111. (loop (cdr b) (+ (arithmetic-shift acc 8) (car b))))))
  112. ;; Takes an unsigned 32 bit integer to the flonum it represents.
  113. (define (u32->fl n)
  114. (define (mantissa expn b2 b3 b4)
  115. (case expn ; recognize special literal exponents
  116. ((255) #f) ; won't handle NaN and +/- Inf
  117. ((0) ; denormalized
  118. (exact->inexact (* (expt 2 (- 1 (+ 127 23)))
  119. (combine b2 b3 b4))))
  120. (else
  121. (exact->inexact
  122. (* (expt 2 (- expn (+ 127 23)))
  123. (combine (+ b2 128) b3 b4)))))) ; hidden bit
  124. (define (exponent b1 b2 b3 b4)
  125. (if (> b2 127) ; 1st bit of b2 is low bit of expn
  126. (mantissa (+ (* 2 b1) 1) (- b2 128) b3 b4)
  127. (mantissa (* 2 b1) b2 b3 b4)))
  128. (define (sign b1 b2 b3 b4)
  129. (if (> b1 127) ; 1st bit of b1 is sign
  130. (cond ((exponent (- b1 128) b2 b3 b4) => -)
  131. (else #f))
  132. (exponent b1 b2 b3 b4)))
  133. (let* ((b (uint-list->blob 4 (endianness big) (list n)))
  134. (b1 (blob-u8-ref b 0))
  135. (b2 (blob-u8-ref b 1))
  136. (b3 (blob-u8-ref b 2))
  137. (b4 (blob-u8-ref b 3)))
  138. (sign b1 b2 b3 b4)))
  139. ;; Takes an unsigned 64 bit integer to the flonum it represents.
  140. (define (u64->fl n)
  141. (define (mantissa expn b2 b3 b4 b5 b6 b7 b8)
  142. (case expn ; recognize special literal exponents
  143. ((255) #f) ; won't handle NaN and +/- Inf
  144. ((0) ; denormalized
  145. (exact->inexact (* (expt 2 (- 1 (+ 1023 52)))
  146. (combine b2 b3 b4 b5 b6 b7 b8))))
  147. (else
  148. (exact->inexact
  149. (* (expt 2 (- expn (+ 1023 52)))
  150. (combine (+ b2 16) b3 b4 b5 b6 b7 b8)))))) ; hidden bit
  151. (define (exponent b1 b2 b3 b4 b5 b6 b7 b8)
  152. (mantissa (bitwise-ior (arithmetic-shift b1 4) ; 7 bits
  153. (extract-bit-field 4 4 b2)) ; + 4 bits
  154. (extract-bit-field 4 0 b2) b3 b4 b5 b6 b7 b8))
  155. (define (sign b1 b2 b3 b4 b5 b6 b7 b8)
  156. (if (> b1 127) ; 1st bit of b1 is sign
  157. (cond ((exponent (- b1 128) b2 b3 b4 b5 b6 b7 b8) => -)
  158. (else #f))
  159. (exponent b1 b2 b3 b4 b5 b6 b7 b8)))
  160. (let* ((b (uint-list->blob 8 (endianness big) (list n)))
  161. (b1 (blob-u8-ref b 0)) (b2 (blob-u8-ref b 1))
  162. (b3 (blob-u8-ref b 2)) (b4 (blob-u8-ref b 3))
  163. (b5 (blob-u8-ref b 4)) (b6 (blob-u8-ref b 5))
  164. (b7 (blob-u8-ref b 6)) (b8 (blob-u8-ref b 7)))
  165. (sign b1 b2 b3 b4 b5 b6 b7 b8)))
  166. (define (call-with-mantissa&exponent num f)
  167. (cond
  168. ((negative? num) (call-with-mantissa&exponent (- num) f))
  169. ((zero? num) (f 0 0))
  170. (else
  171. (let ((base 2) (mant-size 23) (exp-size 8))
  172. (let* ((bot (expt base mant-size))
  173. (top (* base bot)))
  174. (let loop ((n (exact->inexact num)) (e 0))
  175. (cond
  176. ((>= n top)
  177. (loop (/ n base) (+ e 1)))
  178. ((< n bot)
  179. (loop (* n base) (- e 1)))
  180. (else
  181. (f (inexact->exact (round n)) e)))))))))
  182. (define (extract-bit-field size position n)
  183. (bitwise-and (bitwise-not (arithmetic-shift -1 size))
  184. (arithmetic-shift n (- position))))
  185. ;; Takes a flonum to its representation as an unsigned 32 bit integer.
  186. (define (fl->u32 num)
  187. (cond
  188. ((zero? num) 0)
  189. (else
  190. (combine-ls
  191. (call-with-mantissa&exponent num
  192. (lambda (f e)
  193. (let ((e0 (+ e 127 23)))
  194. (cond
  195. ((negative? e0)
  196. (let* ((f1 (inexact->exact (round (* f (expt 2 (- e0 1))))))
  197. (b2 (extract-bit-field 7 16 f1)) ; mant:16-23
  198. (b3 (extract-bit-field 8 8 f1)) ; mant:8-15
  199. (b4 (extract-bit-field 8 0 f1))) ; mant:0-7
  200. (list (if (negative? num) 128 0) b2 b3 b4)))
  201. ((> e0 255) ; XXXX here we just write infinity
  202. (list (if (negative? num) 255 127) 128 0 0))
  203. (else
  204. (let* ((b0 (arithmetic-shift e0 -1))
  205. (b1 (if (negative? num) (+ b0 128) b0)) ; sign + exp:1-7
  206. (b2 (bitwise-ior
  207. (if (odd? e0) 128 0) ; exp:0
  208. (extract-bit-field 7 16 f))) ; + mant:16-23
  209. (b3 (extract-bit-field 8 8 f)) ; mant:8-15
  210. (b4 (extract-bit-field 8 0 f))) ; mant:0-7
  211. (list b1 b2 b3 b4)))))))))))
  212. ;; Takes a flonum to its representation as an unsigned 64 bit integer.
  213. (define (fl->u64 num)
  214. (cond
  215. ((zero? num) 0)
  216. (else
  217. (combine-ls
  218. (call-with-mantissa&exponent num 2 52 11
  219. (lambda (f e)
  220. (let ((e0 (+ e 1023 52)))
  221. (cond
  222. ((negative? e0)
  223. (let* ((f1 (inexact->exact (round (* f (expt 2 (- e0 1))))))
  224. (b2 (extract-bit-field 4 48 f1))
  225. (b3 (extract-bit-field 8 40 f1))
  226. (b4 (extract-bit-field 8 32 f1))
  227. (b5 (extract-bit-field 8 24 f1))
  228. (b6 (extract-bit-field 8 16 f1))
  229. (b7 (extract-bit-field 8 8 f1))
  230. (b8 (extract-bit-field 8 0 f1)))
  231. (list (if (negative? num) 128 0) b2 b3 b4 b5 b6 b7 b8)))
  232. ((> e0 4095) ; infinity
  233. (list (if (negative? num) 255 127) 224 0 0 0 0 0 0))
  234. (else
  235. (let* ((b0 (extract-bit-field 7 4 e0))
  236. (b1 (if (negative? num) (+ b0 128) b0))
  237. (b2 (bitwise-ior (arithmetic-shift
  238. (extract-bit-field 4 0 e0)
  239. 4)
  240. (extract-bit-field 4 48 f)))
  241. (b3 (extract-bit-field 8 40 f))
  242. (b4 (extract-bit-field 8 32 f))
  243. (b5 (extract-bit-field 8 24 f))
  244. (b6 (extract-bit-field 8 16 f))
  245. (b7 (extract-bit-field 8 8 f))
  246. (b8 (extract-bit-field 8 0 f)))
  247. (list b1 b2 b3 b4 b5 b6 b7 b8)))))))))))
  248. ;; --
  249. ;; Reader Hacks
  250. ; Commented out since incompatible with R5RS, and float vector hacks
  251. ; are ommited entirely.
  252. ; (define (vector-reader char port)
  253. ; (define (err)
  254. ; (reading-error port "expected 8, 16, 32, or 64"))
  255. ; (define (s fs fu)
  256. ; (lambda (args)
  257. ; (apply (if (char=? #\s char) fs fu) args)))
  258. ; (read-char port)
  259. ; (let ((f (case (read-char port)
  260. ; ((#\8) (s s8vector u8vector))
  261. ; ((#\1) (case (read-char port)
  262. ; ((#\6) (s s16vector u16vector))
  263. ; (else (err))))
  264. ; ((#\3) (case (read-char port)
  265. ; ((#\2) (s s32vector u32vector))
  266. ; (else (err))))
  267. ; ((#\6) (case (read-char port)
  268. ; ((#\4) (s s64vector u64vector))
  269. ; (else (err))))
  270. ; (else (err)))))
  271. ; (f (sub-read-carefully port))))
  272. ; (define-sharp-macro #\s vector-reader)
  273. ; (define-sharp-macro #\u vector-reader)