srfi-4.scm 11 KB

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