Arrays

Home • Gallery • Tutorials • Download • Purchase • Site Map
 

Arrays

The Fractal Science Kit programming language supports 1-dimensional and 2-dimensional arrays. The elements of an array can be complex numbers or objects. A 1-dimensional array is said to have rank 1 and a 2-dimensional array has rank 2. Arrays of rank greater than 2 are not supported. All arrays must be declared before they are used. The most efficient place to declare an array is in the global section.

A 1-dimensional array is declared using the statement:

[const] <Type> <ArrayName>[<Size>]

The type of the array is given by <Type>, and <ArrayName> must be a valid identifier. The <Type> is required and can be Complex or an existing Object name. The number of items in the array is given by <Size> and the items are indexed using a 0-based index; i.e., the index ranges from 0 to <Size>-1. If <Size> is omitted, the array is declared but no storage is allocated.

Like variable declarations, the optional keyword const is used to declare a constant array. Declaring an array as const can be done only in the global section and states that the array will not be changed outside the global section. This allows the compiler to optimize statements that reference the array in other sections.

Example:

Complex card[52]

This declares a Complex array called card[] containing 52 items. Array items are referenced using an index value which ranges from 0 to 1 less than the number of items in the array; 0 to 51 in the above example.

Example:

card[0] = 1
card[51] = 0

This assigns a value to the first and last items of the array.

A 2-dimensional array is declared using the statement:

[const] <Type> <ArrayName>[<NumberOfRows>, <NumberOfColumns>]

The <Type> and <ArrayName> are identical to 1-dimensional arrays above. The <NumberOfRows> and <NumberOfColumns> give the number of rows and columns of the array. The total number of elements in the array is <NumberOfRows>*<NumberOfColumns>. Array items stored in row major order and are indexed using 0-based indices for the row and column.

Example:

Complex matrix[10,20]

This declares a 2-dimensional array with 10 rows and 20 columns. The 1st index ranges from 0 to 9 and the 2nd from 0 to 19. The number of items in the array is 200.

Arrays with rank greater than 2 are not supported.

Like variables, arrays can be initialized when declared. There are 2 ways to initialize an array. The 1st is to assign a list of comma (,) separated values to the array.

Example:

Complex center[] = 1, 1i, -1, -1i

This creates an array of 4 items with the given values. If the array size is omitted as in the above example, it is set based on the number of initializers. The type of each of the expressions given in the list of initializers must match the type of the array.

Example:

Circle c[] = CircleC( 1, 1), CircleC( 1i, 1), \
             CircleC(-1, 1), CircleC(-1i, 1)

The array items can be reassigned using the same technique, but you do not include the type of the array and the array size must not be included.

Example:

center[] = 1+1i, -1+1i, -1-1i, 1-1i

This example assigns values to the 1st 4 items of the array in a single statement. For 1-dimensional arrays, statements like that given above, will check if there is sufficient space to hold the set of items and, if not, the runtime subsystem will allocate the required space automatically. For 2-dimensional arrays, insufficient space results in a runtime error.

The 2nd way to initialize an array is to set the array equal to another array.

Example:

Complex point[] = center[]

This creates an array called point[] with the same values found in the array center[]. If the array size is omitted as in the above example, it is set based on the size of the other array. In most cases the source and destination array will have the same type and rank but this is not required.

Example:

Complex data[3, 6]
...
Affine s[] = data[,]

The above assignment will initialize s[] with 3 Affine objects created from the values in the Complex array data[,]. Since an Affine object has 6 fields, and each row of the array data[,] has 6 values, s[i] is created from the values in the i-th row of the array data[,]; i.e., data[i,0], data[i,1], ..., data[i,5]. While this type of usage should be avoided for the sake of code clarity, it can be useful in selected circumstances. For example, when accessing data loaded into a data table via the DataFile Statement, it can be used to place the data into an array of objects for convenient access.

Array assignment is supported for existing arrays as well, but you do not include the type of the array and the array size must not be included.

Example:

point[] = center[]

This copies the items in array center[] into array point[]. For 1-dimensional arrays, statements like that given above, will check if there is sufficient space to hold the set of items and, if not, the runtime subsystem will allocate the required space automatically. For 2-dimensional arrays, insufficient space results in a runtime error.

Initialization of 2-dimensional arrays is identical to 1-dimensional arrays except that the array dimensions must be given, you must provide the data in row-major order, and the space allocated for the array must be sufficient to hold the given data.

Example:

Complex t[2,3] = 1, 1, 1, 2, 2, 2

This initializes all the values of the 1st row to 1 and the values of the 2nd row to 2.

Arrays can be resized using the same syntax used to create them. The array rank cannot be changed, however.

Example:

Complex array[100]
...
Complex array[20]

The last statement releases any storage previously held for the array and allocates storage for 20 Complex elements. All the elements are initialized to 0. The previous contents of the array are lost. If the new size is identical to the current size, the statement has no effect; i.e., no space is allocated or freed and the array contents remain unchanged.

There are 4 special functions that are useful when using arrays:

  • Array.Dim1 returns the size of an array's 1st dimension.
  • Array.Dim2 returns the size of an array's 2nd dimension.
  • Array.Copy copies items from one array to another.
  • Array.Clear sets all the items to 0.

Example:

n = Array.Dim1(vector[])

This example sets n equal to the size of the array vector[]; i.e., n is set to the number of items in the 1-dimensional array vector[].

Example:

rows = Array.Dim1(table[,])
cols = Array.Dim2(table[,])

This example sets rows equal to the size of the 1st dimension of the array table[,] and cols equal to the size of the 2nd dimension.

Example:

Array.Copy(src[], srcIndex, dst[], dstIndex, count)

This example copies the count items in the array src[], starting at srcIndex, into the array dst[], starting at dstIndex. In most cases the source and destination array will have the same type and rank but this is not required. If the source or destination arrays are 2-dimensional arrays, the index is a relative offset into the array.

Example:

Complex data1[6,4]
Complex data2[6,4]
Mobius m[12]
...
Array.Copy(data1[,], 0, m[], 0, 24)
Array.Copy(data2[,], 0, m[], 6, 24)

This example fills m[] with 12 Mobius objects using the data given in the 2 arrays data1[,] and data2[,]. Since the source arrays are of type Complex, the count argument is the number of Complex elements to copy (24), and these are mapped onto 6 Mobius objects, each with 4 fields. While this type of usage should be avoided for the sake of code clarity, it can be useful in selected circumstances.

Example:

Array.Clear(a[])

This sets all the elements of a[] to 0. If a[] is an array of objects, it sets all fields in all objects to 0.

When you pass a 1-dimensional array as an argument to a function or method, you must include the [] at the end of the array name. For 2-dimensional arrays you would include [,] at the end of the array name. This is illustrated in the above examples.

Be forewarned that the runtime system does not check for array index errors and if these occur, a generic message is displayed indicating the an index was outside the bounds of an array. While this message does inform you that a program failed and why (an array index was less than 0 or too big), it does not tell you which program failed, or in which section it failed, or what array access caused the failure, or what the invalid index was. All of these could be determined if I was willing to validate all array access statements before executing them or to include localized error handling around the array access code. However, either of these solutions would increase execution time and in the depths of the fractal iteration, even small increases in execution time add up. Given that these situations do not come up all that often (never in a bug free program!), I opted to avoid the extra cost (however small) and handle these errors in the global error handler. I have not found this too inconvenient thus far.

 

Copyright © 2004-2019 Ross Hilbert
All rights reserved