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.

- 3.1.0 Bug fix for SRFI 63 prototype names & more SRFI 58 support.
- 3.001 Bug fix for SRFI 63 prototype names.
- 3.0 Bug fix for dimensions of 0 - these should result in an empty array - and not be treated as a synonym of dimension 1. Added 'array-dimensions-object' & 'array-shape-object'.
- 2.117 Added SRFI 17 support.
- 2.116 Added 'array-prototype'.
- 2.115 'array' can now return an empty array with dimensions. Added 'array-length'.
- 2.114 Bug fix for 'array-for-each' - allowed empty array.
- 2.113 Added 'array-count'. Bug fix for 'array-join'.
- 2.112 Removed array-lib-sub/hof/ec dependence on array-lib. Bug fix for equal? procedure.
- 2.111 Bug fix for array-copy.
- 2.110 Bug fix for array->list for 1 element primitive array, array-join incorrect prototype, rank-0 array. Documentation update.
- 2.109 Added dimensions & shape object procedures.
- 2.108 Direct use of some backend procedures.
- 2.107 Minor internal storage definition changes.
- 2.1.6 Minor documentation update & superflous code removal.
- 2.1.5 Added 'array-align' & 'array-reshape/shared'.
- 2.1.4 Changed BOUNDS to INTERVAL in documentation. Bugfix for 'make-shared-array'.
- 2.1.3 Added array-unfold. Bugfix for subarray w/ (H L) select.
- 2.1.2 Bugfix for array record printing - wasn't. Renamed array-project -> array-reshape. Added array:unsafe. Documentation update.
- 2.1.1 More internal shared code.
- 2.1 Deprecated array RANK parameter. Added make-array-dimensions/rank, *array-ref, *array-set!, array:thread-safe. Added user supplied storage definition. Removed byte-vector support since deprecated.
- 2.0.4 More inline coding (replaces map calls)
- 2.0.3 Bug fix for array-copy deep-copy
- 2.0.2 Signals specific conditions
- 2.01 New misc-extn & testbase
- 2.0 Changed #A<rank><value> read syntax to #<rank>A<value>; requires Chicken 2.513
- 1.9 Reduce source expansion by array ec syntax
- 1.8 Needs misc-extn > 2.0
- 1.7 Bug fix for ec
- 1.6 Removal of common code, partial support for csi describe
- 1.5 Exports
- 1.4 Replaced #<rank>A print syntax with #A read/print syntax, bug fix for returning underlying storage object
- 1.3 Optimized array construction
- 1.2 Bug fix for unbound-variable array:store
- 1.1 Record optimization
- 1.0 Indexing optimization
- 0.9 more SLIB procedures
- 0.8 SLIB procedures
- 0.7 Added procedures
- 0.6 Added procedures
- 0.5 Added procedures
- 0.4 Added procedures
- 0.3 Bug fix for empty arrays
- 0.2 Bug fix for rank 0 arrays
- 0.1 Initial release

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.