[plt-scheme] More PLT Scheme as an Alternative to Matlab

From: Doug Williams (m.douglas.williams at gmail.com)
Date: Thu Aug 13 22:30:00 EDT 2009

This is a continuation of the' DrScheme as alternative to Matlab' thread and
back on track to the original question.

Some time ago I began thinking about a project I was calling Schemelab,
which is exactly what the original question in the thread was addressing -
PLT Scheme as an alternative to Matlab (or Python/NumPy/SciPy).

Matlab (and NumPy/SciPy in Python) is primarily a numeric processing for
data analysis. At its heart is an efficient multidimensional array
representation that facilitates this numeric processing. On top of this is
the cool graphics and specialized numeric processing libraries.

I think the first thing we need to do is to define such a multidimensional
array representation for PLT Scheme. I have put up some prototype code on
GitHub (http://github.com/DrDoug/numeric/tree/master) with the very
beginnings of such a representation. Currently, it just shows creating
arrays (make-array and arange), referenceing elements (array-ref), and some
basic (but interesting) operations (reshape and transpose).

Arrays have a shape, which is specified as a list of exact nonnegative
integers. For example: (make-array '(3 4)) makes a two-dimensional array
with 3 rows and 4 columns and (make-array '(3 4 5)) makes a
three-dimensional array that is a 3 x 4 x 5 array. Arrays have a type. The
types are object, u8, u16, u32, u64, s8, s16, s32, s64, f32, f64, c64, and
c128. Implementationally, this specified the underlying vector type that
stores the actual data for the array, where object is a standard Scheme
vector and the others are unsigned integer, signed integer, floating-point,
and complex representations based on SRFI 4 vectors. This lets the user
specify the fundamental numerical representation. The default is object.
Finally, arrays have an order, which may be 'row or 'column. This specifies
whether the array is stored in row-major or column-major format. The default
is row-major.

For example: (make-array '(3 4)) creates a 3 x 4 row-major array whose
elements can hold any Scheme object; (make-array '(3 4 5) #:type f32)
creates a 3 x 4 x 5 row-major array whose elements are single-precision
floats; and (make-array '(3 4) #:type s32 #:order 'column) creates a 3 x 4
column-major array whose elements are 32-bit signed integers.

A fill value can also be specified when creating an array. If not fill is
specified, the underlying data vector is initialized using whatever method
the primitive make vector functions use. So, (make-vector '(3 4) #:type f32
#:fill 0.0) creates a 3 x 4 row-major array while single-precision flot
elements are initialized to 0.0.

The function arange creates a one-dimensional array of a specified size that
is initialized with the natural numbers 0 ... size-1. The type can also be
specified. For example, (arange 12 #:type f32) creates a 12 element
one-dimensional array (i.e., a vector) whose elements are single-precision
floats 0.0, 1.0, 2.0, ..., 11.0. Note that array order doesn't matter for
one-dimensional arrays (although it will be set to row-major).

Array elements are referenced using array-ref. For example, (array-ref a '(1
2)) returns a[1, 2]. For the prototype code, the reference must be fully
specified and will return the referenced element. In the future, array-ref
will also allow slicing operations such as (array-ref a '(* 3)) would return
the 4th column (with index 3) of a as a one-dimensional array. I'll get
those in the prototype soon.

The function reshape changes the shape of an array. The size of the new
shape must be size of the original shape. Note that the original array is
not changed nor is it copied, a new array reference is created that shares
data with the original. For example, (reshape (arange 12) '(3 4)) creates a
3 x 4 row-major array whose elements are ((0 1 2 3) (4 5 6 7) (8 9 10 11)).

The function transpose transposes an array (obviously). Note that the
original array is not changed nor is it copied. This makes use of the fact
that the column-major representatio of a row-major array is its transpose
and vice versa. For example, (transpose (reshape (arange 12) '(3 4)))
creates a 4 x 3  column-major array whose elements are ((0 4 8) (1 5 9) (2 6
10) (3 7 11)), which is the transpose of ((0 1 2 3) (4 5 6 7) (8 9 10 11)).

Anyway, if you're interested, please download the code from GitHub and run
array-test.ss to see some of the above capabilities. The output describes
the array structure for various examples.

Please let me know if you have trouble getting the code using the above
link. I'm new to GitHub and may have done something wrong.

For the PLT implementors. I'm using SRFI 4 as the underlying representation
for storing the arrays. They store the data in the formats we want, but
don't seem to be processed efficiently. Although efficiency isn't a real
concern at this stage, it will be for some people at some point. Any idea of
what we can do better is more than welcome.

Thanks,
Doug
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20090813/5b022403/attachment.html>

Posted on the users mailing list.