Provides a SRFI 63 workalike
The array-lib purports to be a Chicken workalike for SRFI 47, SRFI 63, SRFI 58, and the SLIB array, subarray & arraymap modules.
The signatures of all SRFI 63 procedures are supported by this API, only with extended interpretations.
However, unlike SRFI 63, the equal? procedure is not automatically rebound! An extension, array-lib-equal, is available that provides a rebound procedure.
The SRFI 58 "sharp A" forms are supported.
Both SRFI 47 and SRFI 63 array prototype procedures are supplied, including complex prototypes (see below).
Array constructors will return the underlying storage object, rather than an array object, when the constructed array is 0-origin & rank = 1, per SRFI 63.
The array-lib operations are in general thread-safe. See array:thread-safe
and array:storage-definition
below for exceptions.
Dimensions are an ordered sequence of the magnitude of each dimension. Dimensions maybe represented as a list, or a dimensions
object. For example, '(1 2)
are dimensions of a rank 2 array, with dimension one having magnitude 1 and dimension two having magnitude 2.
A Shape is an ordered sequence of Interval, [lower upper), for each dimension. A shape maybe a list of interval list or a shape
object. For example, (0 1) (0 2)
is a shape of a rank 2 array, with the bounds of dimension one [0 0] and dimension two [0 1].
The accepted list form of dimensions or shape for procedures taking these as tail arguments is as an 'exploded' list. Each element as an individual argument. For example, (make-array '(1 2) '(-8 -5))
, not (make-array '((1 2) (-8 -5)))
.
All magnitudes of indices, dimensions, bounds, ranks, intervals are fixnums. Not much of a restiction from SRFI 63, just a clarification.
The dimensions '(2 1 3)
are equivalent to the shape '(0 2 0 1 0 3)
.
An inner or outer dimension of 0
will result in an empty array. Per the SRFI 63 implementation.
A SRFI 10 printer and reader is supplied.
An array specific read/print syntax is supplied: #<rank>A<elements>
, where <rank> is the array dimensionality and <elements> are a rank-nested list consisting of all the elements, in row-major order.
The SRFI 10 print-form preserves the underlying storage model and shape information, unlike the #nA form, which only preserves the rank and element values. So, reading the #nA form may not reconstruct the original array.
Use (current-array-print-form ...)
to select the desired form.
A limit is placed on the number of array elements printed, which may be overridden. See (current-array-print-count ...)
.
Gets or sets whether array indices are bounds-checked.
Default is #t
.
Gets or sets whether array elements are immediately type-checked before setting. When #f
the underlying storage type performs any validation.
Default is #f
.
Gets or sets the number of array elements to print. A COUNT of #f
will set the count 0, and #t
will set the count to a very big number. When COUNT is a number it must a zero or positive fixnum.
Gets or sets the format for printing an array, either 'SRFI 10
, 'A
, or #f
which turns off array element printing.
Gets or sets the thread safety status. When #f
cached values of the bounds & element check parameters are used.
Default value is #f
.
Gets or sets the unsafe array element access status. When #t
the array-ref
and array-set!
procedures are replaced by *array-ref
and *array-set!
procedures, respectively.
Default value is #f
.
Returns a dimensions object. Without DIMENSION returns a rank 0 dimensions object.
RANK & COUNT must be >= 0.
Interpreted as the dimensions: ((- RANK 0) (- RANK 1) ... (/ COUNT (factorial RANK))). So rank 1 is (COUNT), 2 is (2 COUNT/2), 3 is (3 2 COUNT/3x2), and so on.
Dubious.
A set of dimensions, as produced by make-array-dimensions?
Are the dimensions the same?
Returns a new shape from the dimensions.
Returns the dimensions information as a list.
Returns the dimension count #f when not dimensions.
Are the indices valid for this dimensions?
Returns a shape object suitable for use with the array construction procedures. Without parameters returns a rank 0 shape object.
A shape is composed of a series of intervals, one for each dimension. An interval argument is either 2 paired arguments, START END, or a list of (START END), INTERVAL. An index is within the bounds for a dimension if START <= index < END.
The interval is on the integers. The START must be strictly less than the END. So [-5 -2) is valid but [-2 -5) is invalid. To indicate an empty dimension start = end is accepted.
A shape, as produced by make-array-shape?
Are the shapes the same?
Returns the shape information as a list.
Returns the dimension count or #f when not shape.
Returns the length of each dimension of the shape as a list.
Are the indices valid for this shape?
Returns whether the object is an array object, or accepted as an array. Builtin objects are vector, string, and SRFI 4 vectors.
Returns whether the object is only an array object.
Are the two arrays equal in dimensionality and elements?
Signals an error when either of the arguments is not an array.
Returns #t
for an empty array, #f
for anything else.
Are the indices valid for the array?
Signals an error when not an array.
Do the arrays have the same shape?
Do the arrays have the same dimensions?
Does the array have the specified shape?
Does the array have the specified dimensions?
Some array error?
Out of range error?
Invalid type error?
Returns the start, or lower bound, of ARRAY along dimension RANK, or #f
when not array.
Returns the end, one beyond the upper bound, of ARRAY along dimension RANK, or #f
when not an array.
Returns the number of elements of ARRAY along dimension RANK, or #f
when not an array.
Returns the actual number of elements (the storage length) of ARRAY, or 0
when not an array.
Returns the number of dimensions for ARRAY, or 0
when not an array, an empty array, or a rank 0 array.
Returns the list of dimensions for ARRAY, or #f
when not an array. The elements are the actual length of each dimension, so a dimension of 3, [0 3), is 3 and [1 3) is 2.
Returns a dimensions object for ARRAY, or #f
when not an array.
Returns the bounds list for ARRAY, or #f
when not an array. A list of pairs, one for each dimension. Each pair is the interval [low high].
Returns the shape list for ARRAY, or #f
when not an array. The list can be used as (apply make-array-shape LIST)
.
To access the compiled shape information of an array use (array-bounds ...)
.
Returns a shape object for ARRAY, or #f
when not an array.
Returns the underlying prototype object for ARRAY , or #f
when not an array.
This is not the original prototype object, it will not have an initial value.
Returns the underlying storage object for ARRAY , or #f
when not an array.
Be vewy, vewy, careful.
A PROTOTYPE is any object such that (array? PROTOTYPE) => #t
. The PROTOTYPE provides a storage definition, and an initial value - the origin element. When the PROTOTYPE is empty the initial value is unspecified.
When the PROTOTYPE is missing, '#()
is assumed.
An empty array cannot be used with any setter or getter. However, property queries will work, and they can be used as a PROTOTYPE.
Returns a fresh array of storage type PROTOTYPE with dimensionality SHAPE/DIMENSIONS and optional ELEMENT ....
When PROTOTYPE is not supplied vector
is assumed. When ELEMENT ... are not supplied an empty array is returned.
Creates and returns an array of type prototype with supplied dimensionality, and filled with elements from prototype.
(make-array [<prototype>])
will construct a rank 0 array.
(make-array [<prototype>] 0)
will construct an empty array.
Returns a copy of the array.
When PROTOTYPE is missing a deep copy is returned of the ARRAY.
When the PROTOTYPE and ARRAY are the same, (eq? PROTOTYPE ARRAY)
, a fresh array is returned with the same shape, using ARRAY as the prototype.
When the PROTOTYPE is #t
a fresh array is returned, with prototype ARRAY and the elements of the ARRAY.
Otherwise a fresh array is returned from the specified prototype and elements of the ARRAY.
The prototype and source array element types must be assignment compatible. Even so, precision maybe lost.
Returns a new array mapped from ARRAY. Can be used to create shared subarrays.
The MAPPER is a function that translates coordinates in the new array into coordinates in the ARRAY. A mapper must be linear, and its' range must stay within the bounds of the array, but it can be otherwise arbitrary.
Returns a shared-array mapped from ARRAY with new lower bounds, but same rank & dimensions.
LOWER-BOUND may be #f
, for same lower-bound as the ARRAY, or an integer, for a new lower-bound. When missing 0
is assumed. Thus, (array-align ARRAY)
returns a shared-array with all lower-bounds of 0.
The list must be a rank-nested list consisting of all the elements, in row-major order, of the array to be created.
Returns an array of rank, or shape, or dimensions and type prototype consisting of all the elements, in row-major order, of the list. When the rank is 0, list is the lone array element; not necessarily a list.
The vector must be of length equal to the product of the dimensions, or shape element sizes.
Returns an array of type prototype consisting of all the elements, in row-major order, of the vector. In the case of a rank 0 array, the vector has a single element.
Returns the array elements as a rank-nested list. For rank 0 arrays returns just the element. Will generate an error when not an array.
Returns the array elements as a new unpacked vector. Will generate an error when not an array.
SRFI 17 is supported.
Returns the array element at indices.
Generates an error when not an array or out-of-range condition.
Sets the array element at indices to the object.
Generates an error when not an array, out-of-range condition, or the object is unsuitable as an array element.
Returns the array element at indices.
Be vewy, vewy, careful.
Sets the array element at indices to the object.
Be vewy, vewy, careful.
Prints COUNT elements of the ARRAY on the specified PORT.
Returns a subarray sharing elements with ARRAY. For an array of rank N, there must be at least N SELECT arguments. For 0 <= I < N, SELECT[I] is either an integer, a list of two integers within the range for the Ith index, or #f
.
When SELECT[I] is a list of two integers, then the Ith index is restricted to that subrange in the returned array. When the subrange is reversed, the lower bound is greater than the upper bound, the subarray is reflected.
The lower bounds for the subarray are the same as the original array. For example, the orginal array has bounds [0 2] and select (1 2), then the subarray has bounds [0 1]. Or, the orginal array has bounds [-2 0] and select (-1 0), then the subarray has bounds [-2 -1].
When SELECT[I] is #f
, then the full range of the Ith index is accessible in the returned array. An elided argument is equivalent to #f
.
When SELECT[I] is an integer, then the rank of the returned array is less than ARRAY, and only elements whose Ith index equals SELECT[I] are shared.
Returns a subarray sharing elements with ARRAY except for slices removed from either side of each dimension. Each of the TRIM arguments is an exact integer indicating how much to trim. A positive TRIM trims the data from the lower end and reduces the upper bound of the result; a negative TRIM trims from the upper end and increases the lower bound.
Returns the array row, as an unpacked vector, at indices. Will generate an error when not an array or out-of-range condition. The number of indices must be one less than the rank.
Sets the array row at indices to the object. Will generate an error when not an array, out-of-range condition, or the object is unsuitable as an array row. The number of indices must be one less than the rank.
The row object may be an one dimensional array, a list, or an atomic value. The row object length must match the target array row length. When an atomic value this operation is row fill.
Return a list of fresh subarrays, split along the specified outer rank, in ascending order by outer index.
Return a list of shared subarrays, split along the specified outer rank, in ascending order by outer index.
Construct a fresh array with specified prototype, outer dimensions, and optional inner dimensions, from the specified inner array(s).
The outer dimension maybe a number (indicating the single, outer, dimension), a list of dimensions, a shape, or #f
(indicating the count of the inner arrays is the outer dimension).
If specified the inner dimension maybe a list of dimensions, or a shape. If missing the first inner array shape is used as the inner shape for the result array.
The result array shape is the concatenation of the outer and inner shapes. The rank of the result array must be greater than the rank the inner array(s).
All joined arrays must be of the same dimensionality.
Returns a fresh array with the top-level dimension reversed.
Returns a zero argument procedure which returns an indices list (a full index) for the specified bounds upon each invocation, or #f
when the indices are exhausted.
An indices list is suitable for use with (apply array-ref/array-set! ... indices)
.
Invokes the procedure with each set of indices for the specified bounds. The procedure arity is equal to the number of bounds. Each argument is a list of the indices, with rank length (length of the bounds).
When an array is specified the bounds of the array are used.
An indices list is suitable for use with (apply array-ref/array-set! ... indices)
.
All arrays should be of the same dimensions. The operation will terminate when any of the set of indices is exhausted.
Applys the PROCEDURE to each list of indexes of the ARRAY and replaces the existing element with the result of the procedure application.
Returns an array of lists of indexes for the ARRAY.
Apply the procedure to each element of the array(s). The procedure arity is equal to the number of the array(s).
All arrays must be of the same dimensionality.
Apply the procedure to each element of SOURCE-ARRAY .... The procedure arity is equal to the number of the source array(s).
Returns the DESTINATION-ARRAY with the mapped elements. An in-place map.
All arrays must be of the same dimensionality.
Apply the procedure to each element of the array(s). The procedure arity is equal to the number of the array(s).
Returns a fresh array from the PROTOTYPE and the shape of the first ARRAY with the mapped elements.
All arrays must be of the same dimensionality.
Apply the fold procedure to each element of the array(s). The procedure arity is 1 + the number of array(s). The first argument is the current accumulated value, or the initial seed. The rest of the arguments are the array elements.
Returns the accumulated value.
All arrays must be of the same dimensionality.
Returns a new array from the PROTOTYPE, the dimensionality RANK/SHAPE/DIMENSIONS, and elements from the result values of interated invocations of PROCEDURE.
The number of seeds must equal the number of elements in the inner-most row of the new array.
PROCEDURE has a signature ((ROW-NO fixnum) (SEED-1 object) ... (SEED-N object) -> (values (ELEMENT-1 object) ... (ELEMENT-N object)))
. The values of the previous invocation are the arguments of the next.
Conform an N dimensional source ARRAY to a fresh M dimensional target array.
The PROCEDURE takes 2 arguments, the target row vector and the source row vector. The target vector length is M and the source vector is length N. The procedure is not required to use the supplied target vector. However, it must return some vector of length M.
Returns the new array.
Conform an N dimensional source ARRAY to a shared M dimensional target array. Returns the shared-array.
A DIMENSION maybe #f
to indicate a dimension as large as necessary to fill the array. An INTERVAL maybe (LOWER-BOUND #f)
to indicate an interval as large as necessary to fill the array. The dimensions of the shared array may be arbitrary but must lay within the source array.
Bug - Re-shaping a shared-array does not yield a correct result.
Copy the elements of the source array to the corresponding elements of the destination array. The source and destination arrays must have the same dimensions, but not necessarily the same shape.
The source and destination element types must be assignment compatible. Even so, precision maybe lost.
Returns an array with specified PROTOTYPE, and SHAPE/DIMENSIONS. Each element of the fresh array is produced by evaluating the EXPRESSION for every state generated by the set of QUALIFIER.
Should more states be generated than elements of the array they are ignored.
Generate each element of each ARRAY, binding the element to VARIABLE. Should the indices be wanted there must be as many INDEX-VARIABLE items as the rank of greatest dimensioned array.
SRFI 63
Returns an inexact 128 bit flonum complex uniform-array prototype.
Returns an inexact 64 bit flonum complex uniform-array prototype.
Returns an inexact 32 bit flonum complex uniform-array prototype.
Returns an inexact 16 bit flonum complex uniform-array prototype.
Returns an inexact 128 bit flonum real uniform-array prototype.
Returns an inexact 64 bit flonum real uniform-array prototype.
Returns an inexact 32 bit flonum real uniform-array prototype.
Returns an inexact 16 bit flonum real uniform-array prototype.
Returns an exact 128 bit decimal flonum rational uniform-array prototype.
Returns an exact 64 bit decimal flonum rational uniform-array prototype.
Returns an exact 32 bit decimal flonum rational uniform-array prototype.
Returns an exact binary fixnum uniform-array prototype with at least 64 bits of precision.
Returns an exact binary fixnum uniform-array prototype with at least 32 bits of precision.
Returns an exact binary fixnum uniform-array prototype with at least 16 bits of precision.
Returns an exact binary fixnum uniform-array prototype with at least 8 bits of precision.
Returns an exact non-negative binary fixnum uniform-array prototype with at least 64 bits of precision.
Returns an exact non-negative binary fixnum uniform-array prototype with at least 32 bits of precision.
Returns an exact non-negative binary fixnum uniform-array prototype with at least 16 bits of precision.
Returns an exact non-negative binary fixnum uniform-array prototype with at least 8 bits of precision.
Returns a boolean uniform-array prototype.
SRFI 47
Returns an inexact 64 bit flonum complex uniform-array prototype.
Returns an inexact 32 bit flonum complex uniform-array prototype.
Returns an inexact 64 bit flonum real uniform-array prototype.
Returns an inexact 32 bit flonum real uniform-array prototype.
Returns an exact binary fixnum uniform-array prototype with at least 64 bits of precision.
Returns an exact binary fixnum uniform-array prototype with at least 32 bits of precision.
Returns an exact binary fixnum uniform-array prototype with at least 16 bits of precision.
Returns an exact binary fixnum uniform-array prototype with at least 8 bits of precision.
Returns an exact non-negative binary fixnum uniform-array prototype with at least 64 bits of precision.
Returns an exact non-negative binary fixnum uniform-array prototype with at least 32 bits of precision.
Returns an exact non-negative binary fixnum uniform-array prototype with at least 16 bits of precision.
Returns an exact non-negative binary fixnum uniform-array prototype with at least 8 bits of precision.
Returns a boolean uniform-array prototype.
Creates or updates a non-builtin array storage class. Not Thread Safe.
SYMBOL | Symbolic name of the type. |
ELEMENT-PREDICATE | Single argument procedure to test if an object is valid as an element of the type. |
MAKE-TYPE | Single argument procedure to make an instance of the type with length. |
TYPE-PREDICATE | Single argument procedure to test if an object is a type instance. |
ELEMENT-REF | Two argument procedure to get an element of a type instance. |
ELEMENT-SET | Three argument procedure to set an element of a type instance. |
INSTANCE-LENGTH | Single argument procedure to return the length of the type instance. |
TO-LIST | Single argument procedure |
FROM-LIST | Single argument procedure |
PROTOTYPE | When supplied a type instance. Otherwise the MAKE-TYPE procedure is used to construct an empty instance. |
Returns an association list of the symbolic names & prototypes of the current storage definitions. Thread Safe.
SRFI 25 indexing is 2.4 times faster! However, 'array-lib' has faster indexing than the reference SRFI 63 implementation.
Array aggregate operations are implemented in an element by element fashion.
The SRFI 42 general dispatcher (: ...)
does not recognize arrays.
The 128-bit & 64-bit prototypes are currently implemented as unpacked vectors.
Full SRFI 58 implementation except for the '#<dimensions>...' form.
Doesn't print full SRFI 58 form.
(use array-lib) (current-array-print-form 'A) (array-dimensions (make-array 3 5)) ; => (3 5) (define fred (make-array '#(#f) 8 8)) (define freds-diagonal (make-shared-array fred (lambda (i) (list i i)) 8)) (array-set! freds-diagonal 'foo 3) (array-ref fred 3 3) ; => foo (define freds-center (make-shared-array fred (lambda (i j) (list (+ 3 i) (+ 3 j))) 2 2)) (array-ref freds-center 0 0) ; => foo (list->array 2 '#() '((1 2) (3 4))) ; => #2A((1 2) (3 4)) (list->array 0 '#() 3) ;Note vector returned, per SRFI 63 ; => #(3) (array->list (array '(2 3) 'ho 'ho 'ho 'ho 'oh 'oh)) ; => ((ho ho ho) (ho oh oh)) (array->list (array 0 'ho)) ; => ho (vector->array (vector 1 2 3 4) '#() 2 2) ; => #2A((1 2) (3 4)) (vector->array '#(3) '#()) ; => #(3) (array->vector (array (make-array-shape 0 2 0 2) 1 2 3 4)) ; => #(1 2 3 4) (array->vector (array 0 'ho)) ; => #(ho) ;; Assuming sparse-vectors works as advertised (use sparse-vectors) (define sparse-vector-empty-element-tag (gensym)) (define (sparse-vector-element? obj) (not (eq? sparse-vector-empty-element-tag obj)) ) (define (list->sparse-vector lst) (let ([sv (make-sparse-vector sparse-vector-empty-element-tag)]) (do ([i 0 (add1 i)] [elms lst (cdr elms)]) [(null? elms) sv] (and-let* ([elm (car elms)]) (sparse-vector-set! sv i elm))) ) ) (define (sparse-vector-length sv) ; This is expensive (length (sparse-vector->list sv)) ) (define (a:sv #!optional value) (let ([sv (make-sparse-vector sparse-vector-empty-element-tag)]) (when (sparse-vector-element? value) (sparse-vector-set! sv 0 value) ) sv ) ) (array:storage-definition 'sparse-vector sparse-vector-element? (lambda (len) (make-sparse-vector sparse-vector-empty-element-tag)) sparse-vector? (lambda (sv idx) (let ([obj (sparse-vector-ref sv idx)]) (if (sparse-vector-element? obj) obj (error 'sparse-vector-ref "no such element" idx sv)))) sparse-vector-set! sparse-vector-length sparse-vector->list list->sparse-vector ; Don't supply initial value, otherwise NOT SPARSE! (a:sv)) (define sva1 (make-array (a:sv) 2 2)) (array-strict? sva1) ; => #t (array->list sva1) ; => () (array->vector sva1) ; => #() (array-empty? sva1) ; => #t (array-ref sva1 1 1) ; => Error: (sparse-vector-ref) no such element: 3 #() (array-set! sva1 'skidoo 1 1) (array-ref sva1 1 1) ; => skidoo (array-empty? sva1) ; => #f (array->list sva1) ; =? ((#f #f) (#f skidoo)) (array->vector sva1) ; => #(#f #f #f skidoo) ;; ;; See "array-lib-test.scm" in the testbase tests repository for more examples. ;;
Thanks to Ivan Shmakov and Terrence Brannon for exploring the corners and uncovering bugs.
Copyright (c) 2006, 2007 Kon Lovett. All rights reserved. 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 ASIS, 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. Copyright (C) 2001, 2003, 2005 Aubrey Jaffer Permission to copy this software, to modify it, to redistribute it, to distribute modified versions, and to use it for any purpose is granted, subject to the following restrictions and understandings. 1. Any copy made of this software must include this copyright notice in full. 2. I have made no warranty or representation that the operation of this software will be error-free, and I am under no obligation to provide any services, by way of maintenance, update, or otherwise. 3. In conjunction with products arising from the use of this material, there shall be no use of my name in any advertising, promotional, or sales literature without prior written consent in each case.