SPL Series and Arrays

 

Unlike C/C++, series are a primary data type in SPL. A series may be processed much like a scalar value. For example:

 

a = {1, 2, 3, 4};

b = a+1;

c = b^2;

 

b == {2, 3, 4, 5}

c == {4, 9, 16, 25}

 

The arithmetic operations above are automatically performed on each element of the series. Unlike C/C++, SPL series begin at index 1. The square brackets, [ ], reference individual elements in the standard way:

 

a = {4, 3, 2, 1};

 

a[2] returns: 3

 

a[2] = 0

 

Series a now contains the elements {4, 0, 2, 1}.

 

SPL arrays are organized in row-column format so that

 

data[3, 4]

 

refers to the element in the third row of the fourth column of the array. Like series, array indices start at index 1. SPL also recognizes C/C++ style array addressing:

 

data[3][4]

 

Indices themselves may be series. For example:

 

a = {10, 20, 30, 40};

 

b = a[{3, 2, 1}];

 

The series b contains the values {30, 20, 10}.

 

The { } may be used to create arrays in a variety of ways. For example:

 

a = {1, 2, 3};

 

produces a 3 element series.

 

a = {0, a, 0};

 

yields the series {0, 1, 2, 3, 0}

 

b = {{1, 2}, {3, 4}, {5, 6}};

 

creates the 3x2 array:

 

{{1, 2},

 {3, 4}, 

 {5, 6}} 

 

c = {"a ", "string"};

 

creates the series {97, 32, 115, 116, 114, 105, 110, 103}

 

Empty braces, {}, create a variable with zero length.

 

a = {};

 

If the variable was previously defined, the old value is cleared.

 

The built in ravel function creates multi-column arrays. Ravel(a, n) divides the series a into an array of columns of length n.

 

a = {1, 2, 3, 4, 5, 6, 7, 8, 9}; 

b = ravel(a, 3); 

 

b == {{1, 4, 7}, 

      {2, 5, 8}, 

      {3, 6, 9}} 

 

To create a 10x10 array of normally distributed random noise:

 

 ravel(gnorm(100, 1), 10);

 

Ravel also appends multiple series in column-wise order. For example:

 

a = {1, 2, 3}; 

b = {4, 5, 6}; 

c = ravel(a, b, a); 

 

c == {{1, 4, 1}, 

      {2, 5, 2}, 

      {3, 6, 3}} 

 

The built in unravel function converts an array into a single column series.

 

d = unravel(c);

 

d == {1, 2, 3, 4, 5, 6, 1, 2, 3}

 

The .. operator acts as a numeric range specification to create a linearly increasing or decreasing series. The range specifier accepts the following form:

 

start..increment..end

 

If the increment is not specified, it is defaulted to 1. For example,

 

1..5 

 

returns the series {1, 2, 3, 4, 5}

 

1..0.8..5 

 

returns {1, 1.8, 2.6, 3.4, 4.2, 5}

 

5..1 

 

returns {}, the empty series.

 

5..-1..1 

 

returns {5, 4, 3, 2, 1}

 

t = -2..0.01..2; 

f = 3; 

s = sin(2*pi*f*t); 

 

creates as series that contains 401 values of a 3 Hertz sinewave evenly sampled over the range 2 <= t <= 2

 

Since .. creates a series and series may address arrays, .. may also access a block of array elements. For example

 

a = {2, 4, 6, 8, 10, 12}; 

b = a[2..6]; 

c = a[2..2..6]; 

d = a[..]; 

f = a[6..-1..2]; 

 

a == {2, 4, 6, 8, 10, 12} 

b == {4, 6, 8, 10, 12} 

c == {4, 8, 12} 

d == {2, 4, 6, 8, 10, 12} 

f == {12, 10, 8, 6, 4} 

 

u = ravel(1..16, 4); 

v = u[1..3, 2..4]; 

w = u[.., 1..3]; 

x = u[1..3, ..]; 

y = u[..]; 

 

u == {{1, 5,  9, 13}, 

      {2, 6, 10, 14}, 

      {3, 7, 11, 15}, 

      {4, 8, 12, 16}} 

 

v == {{5,  9, 13}, 

      {6, 10, 14}, 

      {7, 11, 15}} 

 

w == {{1, 5, 9}, 

      {2, 6, 10}, 

      {3, 7, 11}, 

      {4, 8, 12}} 

 

x == {{1, 5,  9, 13}, 

      {2, 6, 10, 14}, 

      {3, 7, 11, 15}} 

 

y == {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14} 

 

As indicated by examples, the .. operator without any range specifiers implies all rows or columns. For tabular data, the .. operator by itself implies all the values of the table unraveled into a single column.

 

Array assignments are also valid. For example, from above:

u[1..3, 1] = -1; 

 

u == {{-1, 5,  9, 13}, 

      {-1, 6, 10, 14}, 

      {-1, 7, 11, 15}, 

      { 4, 8, 12, 16}} 

Assigning an array using the .. operator preserves the shape of the array.

a = ravel(1..9, 3); 

 

a == {{1, 4, 7} 

      {2, 5, 8} 

      {3, 6, 9}} 

 

a[..] = 2..2..18; 

 

a == {{2,  8, 14} 

      {4, 10, 16} 

      {6, 12, 18}} 

SPL arrays also support "unraveled" or linear addressing. For example,

a = ravel(100..200, 10); 

 

creates a 10x10 array of elements ranging from 100 to 200.

 

Now, a[11] == a[1,2] == 110 since both a[11] and a[1,2] refer to the 11th element of array a.

 

Assigning elements of an array to the empty series, {}, removes them. For example:

 

a = ravel(1..9, 3)

a[.., 2] = {}

 

Removes the 2nd column and returns the array:

 

{{1, 7},

 {2, 8}, 

 {3, 9}} 

 

The END function returns the last index or last row or column index of an array. For example:

 

a1 = ravel(1..12, 4);

b1 = a[end];

b2 = a[1, end];

b3 = a[end, 1];

b4 = a[end, end];

b5 = a[end-1, end-1];

 

a1 == {{1, 5,  9},

       {2, 6, 10}, 

       {3, 7, 11}, 

       {4, 8, 12}} 

 

b1 == a1[12]   == 12

b2 == a1[1, 3] ==  9

b3 == a1[4, 1] ==  4

b4 == a1[4, 3] == 12

b5 == a1[3, 2] ==  7

 

END can only be used inside an array reference expression, i.e. an array name followed by [ ].