improves upon the representation of arrays
svn: r3591
This commit is contained in:
parent
ee4748f66d
commit
ba5c6607d8
|
@ -1,23 +1,78 @@
|
|||
;; SRFI 63: Homogeneous and Heterogeneous Arrays
|
||||
;; Implementation of SRFI 63 "Homogeneous and Heterogeneous Arrays" for PLT
|
||||
;; Scheme.
|
||||
|
||||
;; Copyright (C) 2006 David Van Horn
|
||||
|
||||
;; Released under the same terms as the SRFI reference implementation.
|
||||
|
||||
;; Parts of this file are based on SLIB "array.scm" Arrays for Scheme.
|
||||
;; Copyright (C) 2001, 2003, 2005, 2006 Aubrey Jaffer
|
||||
|
||||
(module |63| mzscheme
|
||||
(require (lib "4.ss" "srfi")
|
||||
(lib "9.ss" "srfi")
|
||||
(lib "16.ss" "srfi")
|
||||
(lib "contract.ss"))
|
||||
|
||||
(define-syntax enumerate
|
||||
(syntax-rules ()
|
||||
((enumerate name (const val) ...)
|
||||
(define-syntax name
|
||||
(syntax-rules (const ...)
|
||||
((name const) val) ...)))))
|
||||
|
||||
(enumerate a:
|
||||
(vector 0)
|
||||
(floc128b 1) (floc64b 2) (floc32b 3) (floc16b 4)
|
||||
(flor128b 5) (flor64b 6) (flor32b 7) (flor16b 8)
|
||||
(floq128d 9) (floq64d 10) (floq32d 11)
|
||||
(fixz64b 12) (fixz32b 13) (fixz16b 14) (fixz8b 15)
|
||||
(fixn64b 16) (fixn32b 17) (fixn16b 18) (fixn8b 19)
|
||||
(bool 20)
|
||||
(string 21))
|
||||
|
||||
(define-record-type :strict-array ;:strict-array
|
||||
(make-strict-array
|
||||
dimensions scales offset store store-ref store-set store-make)
|
||||
;; This implementation uses SRFI-4 vectors as the store for
|
||||
;; several of the homogeneous array types, but several types
|
||||
;; are implemented using plain vectors. To improve the
|
||||
;; implementation, simply update the appropriate entry in
|
||||
;; this table.
|
||||
(define implementation-list
|
||||
(let ((ls list-immutable))
|
||||
(ls (ls (a: vector) make-vector vector-ref vector-set!)
|
||||
(ls (a: floc128b) make-vector vector-ref vector-set!)
|
||||
(ls (a: floc64b) make-f64vector f64vector-ref f64vector-set!)
|
||||
(ls (a: floc32b) make-f32vector f32vector-ref f32vector-set!)
|
||||
(ls (a: floc16b) make-vector vector-ref vector-set!)
|
||||
(ls (a: flor128b) make-vector vector-ref vector-set!)
|
||||
(ls (a: flor64b) make-vector vector-ref vector-set!)
|
||||
(ls (a: flor32b) make-vector vector-ref vector-set!)
|
||||
(ls (a: flor16b) make-vector vector-ref vector-set!)
|
||||
(ls (a: floq128d) make-vector vector-ref vector-set!)
|
||||
(ls (a: floq64d) make-vector vector-ref vector-set!)
|
||||
(ls (a: floq32d) make-vector vector-ref vector-set!)
|
||||
(ls (a: fixz64b) make-s64vector s64vector-ref s64vector-set!)
|
||||
(ls (a: fixz32b) make-s32vector s32vector-ref s32vector-set!)
|
||||
(ls (a: fixz16b) make-s16vector s16vector-ref s16vector-set!)
|
||||
(ls (a: fixz8b) make-s8vector s8vector-ref s8vector-set!)
|
||||
(ls (a: fixn64b) make-u64vector u64vector-ref u64vector-set!)
|
||||
(ls (a: fixn32b) make-u32vector u32vector-ref u32vector-set!)
|
||||
(ls (a: fixn16b) make-u16vector u16vector-ref u16vector-set!)
|
||||
(ls (a: fixn8b) make-u8vector u8vector-ref u8vector-set!)
|
||||
(ls (a: bool) make-vector vector-ref vector-set!)
|
||||
(ls (a: string) make-string string-ref string-set!))))
|
||||
|
||||
;; PLTisms: list-immutable, vector-immutable, sub1, add1,
|
||||
;; arithmetic-shift, contracts.
|
||||
|
||||
(define-record-type :strict-array
|
||||
(make-strict-array dimensions scales offset store store-type)
|
||||
strict-array?
|
||||
(dimensions strict-array-dimensions)
|
||||
(scales strict-array-scales)
|
||||
(offset strict-array-offset)
|
||||
(store strict-array-store)
|
||||
(store-ref strict-array-store-ref) ; each array contains
|
||||
(store-set strict-array-store-set) ; its ref, acc, and maker
|
||||
(store-make strict-array-store-make)) ; procedures for its storage type.
|
||||
; maybe theres a better approach?
|
||||
|
||||
(store-type strict-array-store-type))
|
||||
|
||||
(define (array-dimensions array)
|
||||
(cond ((vector? array) (list (vector-length array)))
|
||||
((string? array) (list (string-length array)))
|
||||
|
@ -32,21 +87,32 @@
|
|||
(cond ((string? array) array)
|
||||
((vector? array) array)
|
||||
(else (strict-array-store array))))
|
||||
|
||||
(define store-makers
|
||||
(apply vector-immutable
|
||||
(map (lambda (item) (list-ref item 1)) implementation-list)))
|
||||
|
||||
(define store-reffers
|
||||
(apply vector-immutable
|
||||
(map (lambda (item) (list-ref item 2)) implementation-list)))
|
||||
|
||||
(define store-setters
|
||||
(apply vector-immutable
|
||||
(map (lambda (item) (list-ref item 3)) implementation-list)))
|
||||
|
||||
(define (array-store-type array)
|
||||
(cond ((string? array) (a: string))
|
||||
((vector? array) (a: vector))
|
||||
(else (strict-array-store-type array))))
|
||||
|
||||
(define (array-store-ref array)
|
||||
(cond ((string? array) string-ref)
|
||||
((vector? array) vector-ref)
|
||||
(else (strict-array-store-ref array))))
|
||||
(vector-ref store-reffers (array-store-type array)))
|
||||
|
||||
(define (array-store-set array)
|
||||
(cond ((string? array) string-set!)
|
||||
((vector? array) vector-set!)
|
||||
(else (strict-array-store-set array))))
|
||||
(vector-ref store-setters (array-store-type array)))
|
||||
|
||||
(define (array-store-make array)
|
||||
(cond ((string? array) make-string)
|
||||
((vector? array) make-vector)
|
||||
(else (strict-array-store-make array))))
|
||||
(define (array-store-maker array-type)
|
||||
(vector-ref store-makers array-type))
|
||||
|
||||
(define (array-offset array)
|
||||
(cond ((string? array) 0)
|
||||
|
@ -86,15 +152,14 @@
|
|||
((and onedim? (vector? prot))
|
||||
(apply make-vector (car dimensions) initializer))
|
||||
(else
|
||||
(let ((store (apply (array-store-make prototype)
|
||||
(let* ((store-type (array-store-type prototype))
|
||||
(store (apply (array-store-maker store-type)
|
||||
tcnt initializer)))
|
||||
(let loop ((dims (reverse dimensions)) (scales '(1)))
|
||||
(if (null? dims)
|
||||
(make-strict-array dimensions (cdr scales) 0
|
||||
(make-strict-array dimensions (cdr scales) 0
|
||||
store
|
||||
(array-store-ref prototype)
|
||||
(array-store-set prototype)
|
||||
(array-store-make prototype))
|
||||
store-type)
|
||||
(loop (cdr dims)
|
||||
(cons (* (car dims) (car scales)) scales))))))))))
|
||||
|
||||
|
@ -120,9 +185,7 @@
|
|||
(array-offset array)
|
||||
(map * odl (apply mapper (map car shape))))
|
||||
(array-store array)
|
||||
(array-store-ref array)
|
||||
(array-store-set array)
|
||||
(array-store-make array))))))
|
||||
(array-store-type array))))))
|
||||
|
||||
(define (list->array rank proto lst)
|
||||
(define dimensions
|
||||
|
@ -203,74 +266,165 @@
|
|||
(apply + (array-offset array) (map * (array-scales array) indices))
|
||||
obj))
|
||||
|
||||
(define (tag-maker make-tagvector tagvector-ref tagvector-set)
|
||||
(define (tag-maker array-type)
|
||||
(case-lambda
|
||||
(() (make-strict-array
|
||||
'(1) '(1) 0 (make-tagvector 1 0)
|
||||
tagvector-ref tagvector-set make-tagvector))
|
||||
((x) (make-strict-array
|
||||
'(1) '(1) 0 (make-tagvector 1 x)
|
||||
tagvector-ref tagvector-set make-tagvector))))
|
||||
(() (make-strict-array
|
||||
'(0) '(1) 0
|
||||
((array-store-maker array-type) 0)
|
||||
array-type))
|
||||
|
||||
((x) (make-strict-array
|
||||
'(1) '(1) 0
|
||||
((array-store-maker array-type) 1 x)
|
||||
array-type))))
|
||||
|
||||
(define a:fixz8b (tag-maker make-s8vector s8vector-ref s8vector-set!))
|
||||
(define a:fixz16b (tag-maker make-s16vector s16vector-ref s16vector-set!))
|
||||
(define a:fixz32b (tag-maker make-s32vector s32vector-ref s32vector-set!))
|
||||
(define a:fixz64b (tag-maker make-s64vector s64vector-ref s64vector-set!))
|
||||
(define a:fixn8b (tag-maker make-u8vector u8vector-ref u8vector-set!))
|
||||
(define a:fixn16b (tag-maker make-u16vector u16vector-ref u16vector-set!))
|
||||
(define a:fixn32b (tag-maker make-u32vector u32vector-ref u32vector-set!))
|
||||
(define a:fixn64b (tag-maker make-u64vector u64vector-ref u64vector-set!))
|
||||
(define a:floc128b (tag-maker (a: floc128b)))
|
||||
(define a:floc64b (tag-maker (a: floc64b)))
|
||||
(define a:floc32b (tag-maker (a: floc32b)))
|
||||
(define a:floc16b (tag-maker (a: floc16b)))
|
||||
|
||||
(define a:floc32b (tag-maker make-f32vector f32vector-ref f32vector-set!))
|
||||
(define a:floc64b (tag-maker make-f64vector f64vector-ref f64vector-set!))
|
||||
(define a:flor128b (tag-maker (a: flor128b)))
|
||||
(define a:flor64b (tag-maker (a: flor64b)))
|
||||
(define a:flor32b (tag-maker (a: flor32b)))
|
||||
(define a:flor16b (tag-maker (a: flor16b)))
|
||||
|
||||
(define a:floq128d (tag-maker (a: floq128d)))
|
||||
(define a:floq64d (tag-maker (a: floq64d)))
|
||||
(define a:floq32d (tag-maker (a: floq32d)))
|
||||
|
||||
(define a:fixz64b (tag-maker (a: fixz64b)))
|
||||
(define a:fixz16b (tag-maker (a: fixz16b)))
|
||||
(define a:fixz32b (tag-maker (a: fixz32b)))
|
||||
(define a:fixz8b (tag-maker (a: fixz8b)))
|
||||
|
||||
(define a:fixn64b (tag-maker (a: fixn64b)))
|
||||
(define a:fixn32b (tag-maker (a: fixn32b)))
|
||||
(define a:fixn16b (tag-maker (a: fixn16b)))
|
||||
(define a:fixn8b (tag-maker (a: fixn8b)))
|
||||
|
||||
;; Don't have anything better to do in these cases.
|
||||
(define a:bool (tag-maker (a: bool)))
|
||||
|
||||
|
||||
(define (vector-maker)
|
||||
(case-lambda
|
||||
(() (vector))
|
||||
((x) (vector x))))
|
||||
;; --
|
||||
;; Contracts for module |63|.
|
||||
|
||||
(define a:floc16b (vector-maker))
|
||||
(define a:floc128b (vector-maker))
|
||||
;; Returns a contract for a binary flonum complex prototype function
|
||||
;; given the number of bits (NOT USED).
|
||||
(define (make-floc/c _)
|
||||
(case-> (-> array?)
|
||||
(-> (and/c inexact? complex?) array?)))
|
||||
|
||||
(define a:flor16b (vector-maker))
|
||||
(define a:flor32b (vector-maker))
|
||||
(define a:flor64b (vector-maker))
|
||||
(define a:flor128b (vector-maker))
|
||||
;; Returns a contract for a binary flonum real prototype function
|
||||
;; given the number of bits (NOT USED).
|
||||
(define (make-flor/c _)
|
||||
(case-> (-> array?)
|
||||
(-> (and/c inexact? real?) array?)))
|
||||
|
||||
(define a:floq128d (vector-maker))
|
||||
(define a:floq64d (vector-maker))
|
||||
(define a:floq32d (vector-maker))
|
||||
;; Returns a contract for a decimal flonum rational prototype function
|
||||
;; given the number of bits (NOT USED).
|
||||
(define (make-floq/c _)
|
||||
(case-> (-> array?)
|
||||
(-> (and/c exact? rational?) array?)))
|
||||
|
||||
(define a:bool (vector-maker))
|
||||
;; Returns a contract for a binary fixnum prototype function given
|
||||
;; the number of bits and whether the elements are signed.
|
||||
(define (make-fix/c n signed?)
|
||||
(case->
|
||||
(-> array?)
|
||||
(-> (and/c exact?
|
||||
(if signed?
|
||||
(let ((x (arithmetic-shift 1 (sub1 n))))
|
||||
(integer-in (- x) (sub1 x)))
|
||||
(integer-in 0 (sub1 (arithmetic-shift 1 n)))))
|
||||
array?)))
|
||||
|
||||
(provide array? s:equal? array-rank array-dimensions
|
||||
make-array make-shared-array
|
||||
list->array array->list array->vector
|
||||
array-in-bounds?
|
||||
|
||||
a:fixz8b a:fixz16b a:fixz32b a:fixz64b
|
||||
a:fixn8b a:fixn16b a:fixn32b a:fixn64b
|
||||
|
||||
a:floc16b a:floc32b a:floc64b a:floc128b
|
||||
a:flor16b a:flor32b a:flor64b a:flor128b
|
||||
|
||||
a:floq32d a:floq64d a:floq128d
|
||||
|
||||
a:bool)
|
||||
|
||||
(provide/contract
|
||||
|
||||
(array? (-> any/c boolean?))
|
||||
(s:equal? (-> any/c any/c boolean?))
|
||||
(array-rank (-> any/c natural-number/c))
|
||||
(array-dimensions (-> array? (listof natural-number/c)))
|
||||
|
||||
(make-array
|
||||
(->r ((proto array?)) dimensions (listof natural-number/c)
|
||||
(lambda (result)
|
||||
(let ((rank (length dimensions)))
|
||||
(cond ((and (string? proto) (= 1 rank))
|
||||
(string? result))
|
||||
((and (vector? proto) (= 1 rank))
|
||||
(vector? result))
|
||||
(else
|
||||
(equal? (array-store-type proto)
|
||||
(array-store-type result))))))))
|
||||
|
||||
(make-shared-array
|
||||
(->r ((array array?)
|
||||
(mapper (->* () (listof natural-number/c)
|
||||
((listof natural-number/c)))))
|
||||
indices (listof natural-number/c)
|
||||
array?))
|
||||
|
||||
(list->array
|
||||
(->r ((rank natural-number/c) (proto array?) (list list?)) array?))
|
||||
|
||||
(array->list
|
||||
(->r ((array array?))
|
||||
(lambda (result)
|
||||
(or (zero? (array-rank array))
|
||||
(list? result)))))
|
||||
|
||||
(array->vector
|
||||
(->r ((array array?)) vector?))
|
||||
|
||||
(array-in-bounds?
|
||||
(->r ((array array?)) indices (listof any/c) boolean?))
|
||||
|
||||
(array-set!
|
||||
(->r ((a array?) (_ any/c)) indices
|
||||
(lambda _ (apply array-in-bounds? a indices)) any))
|
||||
(->r ((array array?) (_ any/c)) indices
|
||||
(lambda _ (apply array-in-bounds? array indices))
|
||||
any))
|
||||
|
||||
(array-ref
|
||||
(->r ((a array?)) indices
|
||||
(lambda _ (apply array-in-bounds? a indices)) any))
|
||||
(->r ((array array?)) indices
|
||||
(lambda _ (apply array-in-bounds? array indices))
|
||||
any))
|
||||
|
||||
(vector->array
|
||||
(->r ((v vector?) (p array?)) dimensions
|
||||
(lambda _ (eqv? (vector-length v) (apply * dimensions))) any)))
|
||||
(->r ((vector vector?) (proto array?)) dimensions
|
||||
(lambda _ (eqv? (vector-length vector) (apply * dimensions)))
|
||||
any))
|
||||
|
||||
;; Binary flonum complex
|
||||
(a:floc128b (make-floc/c 128))
|
||||
(a:floc64b (make-floc/c 64))
|
||||
(a:floc32b (make-floc/c 32))
|
||||
(a:floc16b (make-floc/c 16))
|
||||
|
||||
) ; end of module |63|
|
||||
;; Binary flonum real
|
||||
(a:flor128b (make-flor/c 128))
|
||||
(a:flor64b (make-flor/c 64))
|
||||
(a:flor32b (make-flor/c 32))
|
||||
(a:flor16b (make-flor/c 16))
|
||||
|
||||
;; Decimal flonum rational
|
||||
(a:floq128d (make-floq/c 128))
|
||||
(a:floq64d (make-floq/c 64))
|
||||
(a:floq32d (make-floq/c 32))
|
||||
|
||||
;; Binary fixnum
|
||||
(a:fixz64b (make-fix/c 64 #t))
|
||||
(a:fixz32b (make-fix/c 32 #t))
|
||||
(a:fixz16b (make-fix/c 16 #t))
|
||||
(a:fixz8b (make-fix/c 8 #t))
|
||||
(a:fixn64b (make-fix/c 64 #f))
|
||||
(a:fixn32b (make-fix/c 32 #f))
|
||||
(a:fixn16b (make-fix/c 16 #f))
|
||||
(a:fixn8b (make-fix/c 8 #f))
|
||||
|
||||
;; Boolean
|
||||
(a:bool
|
||||
(case-> (-> array?)
|
||||
(-> boolean? array?))))
|
||||
|
||||
) ; end of module |63|
|
||||
|
|
Loading…
Reference in New Issue
Block a user