Home · Pages · Index · Overviews

Array Class Reference

N-dimensional arrays over scalar data. More...

 #include <array.h>

Visible Fields

kind : Array_Kind
type : Value_Type
scale : int
ndims : int
dims : Dimn_Type *
tlen : int
text : string
data : void *
size : Size_Type
Interpreation of the array: one of the 4 Array_Kinds below
The type of the array's values, one of the 10 Value_Types
Number of bits in non-float values
Number of dimensions of the array
dims[i] is the length of dimension i
Length of the string text
An arbitrary string label
A block of sizeof(type)*size bytes holding the array's elements
Total number of elements in the array (= ∏ i dims[i])

Structures

  Array_Bundle : Array

  Range_Bundle : struct
maxval : Value
minval : Value
max observed value
min observed value

  Extent_Bundle : struct
min : Vector *
max : Vector *
Minimum value encountered in each dimension
Maximum value encountered in each dimension

Enumerated Scalars

  Array_Kind : { PLAIN_KIND, RGB_KIND, RGBA_KIND, COMPLEX_KIND }
  Color_Index : { RED_INDEX, GREEN_INDEX, BLUE_INDEX, ALPHA_INDEX }
  Complex_Index : { REAL_INDEX, IMAG_INDEX }
 
 
 

Descriptive Types

  Matrix : Array
  Vector : Array
  Coordinate : Vector
A 2-dimensional array
A 1-dimensional array
A Dimn_Type vector
 
  Pixel_Array : Array
  Pixel_Matrix : Matrix
  Pixel_Vector : Vector
  Pixel_APart : APart
A uint8 or uint16 array
A uint8 or uint16 matrix
A uint8 or uint16 vector
A uint8 or uint16 array or slice
 
  Integer_Array : Array
  Integer_Matrix : Matrix
  Integer_Vector : Vector
An int32 array
An int32 matrix
An int32 vector
 
  Float_Array : Array
  Float_Matrix : Matrix
  Float_Vector : Vector
A float32 array
A float32 matrix
A float32 vector
 
  Double_Array : Array
  Double_Matrix : Matrix
  Double_Vector : Vector
A float64 array
A float64 matrix
A float64 vector
 
  Numeric_Array : Array
  Numeric_Matrix : Matrix
  Numeric_Vector : Vector
A float32 or float64 array
A float32 or float64 matrix
A float32 or float64 vector
 
  Complex_Array : Array
  Complex_Matrix : Matrix
  Complex_Vector : Vector
A float32 or float64 PLAIN or COMPLEX array
A float32 or float64 PLAIN or COMPLEX matrix
A float32 or float64 PLAIN or COMPLEX vector

Routines

Creation and Basic Manipulation

uint8 AUINT8 (Array *a)
uint16 AUINT16 (Array *a)
uint32 AUINT32 (Array *a)
uint64 AUINT64 (Array *a)
int8 AINT8 (Array *a)
int16 AINT16 (Array *a)
int32 AINT32 (Array *a)
int64 AINT64 (Array *a)
float32 AFLOAT32 (Array *a)
float64 AFLOAT64 (Array *a)

Dimn_Type ADIMN (Array *a)
Indx_Type AINDX (Array *a)
Size_Type ASIZE (Array *a)
Offs_Type AOFFS (Array *a)

Array * Make_ArrayG (Array_Kind kind, Value_Type type, int ndims, Dimn_Type *dims)
Array * Make_Array_With_ShapeG (Array_Kind kind, Value_Type type, Coordinate *shape F)
Array * Make_Array_From_ArraysG (Array_Kind kind, int n, Array **arrays)
Array * Make_Array_Of_DataG (Array_Kind kind, Value_Type type,
                                         int ndims, Dimn_Type *dims, void *data)

void Set_Array_Text (Array *a M, string text)
void Append_To_Array_Text (Array *a M, string text)

Value Get_Array_Value (Array *a, Coordinate *coord F)
void Set_Array_Value (Array *a M, Coordinate *coord F, Value v)

Array_Bundle * Get_Array_Plane (Array_Bundle *a RM, Dimn_Type plane)

void Print_Array (AForm *a, FILE *output, int indent, string format)
void Print_Inuse_List (FILE *output, int indent)

Coordinates

Coordinate * CoordG (string list)
void Print_Coord (FILE *f, Coordinate *coord F)

Coordinate * Coord1G (Dimn_Type d1)
Coordinate * Coord2G (Dimn_Type d2, Dimn_Type d1)
Coordinate * Coord3G (Dimn_Type d3, Dimn_Type d2, Dimn_Type d1)
Coordinate * Coord4G (Dimn_Type d4, Dimn_Type d3, Dimn_Type d2, Dimn_Type d1)

Coordinate * AppendCoord (Dimn_Type d, Coordinate *coord RM)
Coordinate * PrependCoord (Coordinate *coord RM, Dimn_Type d)

Coordinate * Idx2CoordAG (Array *a, Indx_Type idx)
Indx_Type Coord2IdxA (Array *a, Coordinate *coord F)

void Set_Coord_Basis (Coordinate *coord F, Array_Kind kind)
void Use_Array_Basis (Array *a)
Coordinate * Get_Coord_BasisG (Array_Kind *kind O)

Coordinate * Idx2CoordG (Indx_Type idx)
Indx_Type Coord2Idx (Coordinate *coord F)

Coordinate * Idx2CoreAG (Array *a, Indx_Type idx)
Coordinate * Idx2CoreG (Indx_Type idx)

Coordinate * Floor_CoordG (Double_Vector *point)
Coordinate * Ceiling_CoordG (Double_Vector *point)
Coordinate * Nearest_CoordG (Double_Vector *point)

Conversion, Element-Wise Ops, Padding, Clipping, and Down-Sampling

Array * Convert_ArrayG (Array *a, Array_Kind kind, Value_Type type, int scale, int|double factor)
Array * Convert_Array_Inplace (Array *a RM, Array_Kind kind, Value_Type type,
                                          int scale, int|double factor)

boolean Image_Check (Array *a)
Array * Convert_ImageG (Array *a, Array_Kind kind, Value_Type type, int scale)
Array * Convert_Image_Inplace (Array *a RM, Array_Kind kind, Value_Type type, int scale)

Range_Bundle * Array_Range (Range_Bundle *range RO, AForm *a)

APart * Scale_Array (APart *a RM, double factor, double offset)
APart * Scale_Array_To_Range (APart *a RM, Value min, Value max)

APart * Array_Op_Scalar (APart *a RM, Operator op, Value_Type type, Value v)
APart * Complex_Op_Scalar (APart *a RM, Operator op, Value_Type type, Value v, Value w)

APart * Array_Op_Array (APart *a RM, Operator op, AForm *b)
APart * Complex_Op_Array (APart *a RM, Operator op, AForm *b)
APart * Complex_Op_Complex (APart *a RM, Operator op, AForm *b)

APart * Array_Fct_Val (APart *a RM, Value (*fct)(void * valp))
APart * Array_Fct_Idx (APart *a RM, Value (*fct)(Coordinate *coord))

APart * Threshold_Array (APart *a RM, Value cutoff)

Array * Array_MultiplyG (Array *a, Array *b)

Array * Apply_MapG (Array *image, Array *map)

Array * Down_SampleG (AForm *source, Coordinate *box F)
Array * Clip_ArrayG (AForm *source, Coordinate *beg F, Coordinate *end F)
Array * Pad_ArrayG (AForm *source, Coordinate *anchor F, Coordinate *shape F)

Array * Down_Sample_Inplace (Array *source RM, Coordinate *box F)
Array * Clip_Array_Inplace (Array *source RM, Coordinate *beg F, Coordinate *end F)
Array * Pad_Array_Inplace (Array *source RM, Coordinate *anchor F, Coordinate *shape F)

Detailed Description

An array is the central object of the Mylib library and is used throughout. This page describes primarily those routines and matters that pertain to arrays in and of themselves. All the fields of an Array object's structure are visible to the user in order to facilitate access. One may freely change the values of the elements in an array without concern for unanticipated side-effects. However, we recommend that you do not make any changes to the dimensions, type, kind, or any other facet of an array that changes its size unless you have familiarized yourself with the object conventions and how Mylib's object manager works by reading the document Object.Management.

Anatomy of an Array

An array can have any number of dimensions ndims and the size of each dimension is given by dims[i] for i from 0 to ndims-1 where 0 is the innermost (and fastest moving) dimension.

The elements of an array of are all of a given type that is one of the ten scalar Value_Types that cover unsigned integers, signed integers, and floating point values of all standard sizes. Moreover, for the signed and unsigned integer types, the scale-field specifies the number of bits used to encode the value. Typically this is just the number of bits in the underlying element type (e.g. 32 if INT32_TYPE, or UINT32_TYPE), but it may be a smaller number if desirable. This is motivated by the frequent occurence in microscopy data, of 12-bit or 10-bit D/A converters in a microscope's CCD camera. One might, for example, recieve an array with elements of type UINT16_TYPE and a scale of 12. This makes almost no difference to any routine in the package which will happily treat the values as uint16, except when the array is read or written to a TIFF file (e.g. Read_Image, Read_Images, etc.), or when one converts an array from one type and scale to another (e.g. Convert_Array, Convert_Image, etc.)

The data field is a void pointer to the elements of the array stored as a linear vector. To obtain a pointer to the appropriate type use one of the routines AUINT8, AUINT16, ... AFLOAT64 below (these are actually simple macros). The elements are layed out with dims[0] being the fastest moving dimension, i.e., for an n-dimensional array the index of A[xn-1,...,x1,x0] is

(... (xn-1*dims[n-2] + xn-2)*dims[n-3] + ...)*dims[0] + x0

using Horner's rule. While it could be computed from dims and ndims, Mylib keeps the size of an array as a field (NB: this is not the size in bytes, but the number of elements in the array).

There are four kinds of arrays: plain, rgb, rgba, and complex that are indicated by the values of the enum Array_Kind. Every kind of array is basically an n-dimensional array over the ten scalar types, but in the case of all but PLAIN_KIND arrays, there is a restriction on one of the dimensions. Specifically, if an array is of RGB_KIND or RGBA_KIND then the outermost dimension must be 3 and 4, respectively, one (n-1)-dimensional sub-array of red, green, blue, and alpha values. If an array is of COMPLEX_KIND then the innermost dimension is 2, where the first element in this dimension is the real part, and the second the imaginary part of a complex number. As an example, consider a 3 x 5 x 2 array, A. It can be interpreted as either a 3 x 5 x 2 plain array, a 5 x 2 array of rgb colors, or a 3 x 5 array of complex numbers, depending on its kind. That is, (A[0,y,x],A[1,y,x],A[2,y,x]) can represent an rgb-triple or color, or A[x,y,0] + i A[x,y,1] can represents a complex number. The choice to have color be the outer rather than the inner dimension is unconventional, but it gives one the ability to work independently on a red, green, blue, or alpha sub-array easily, with no real downside to setting or computing on color-tuples in terms of code or efficiency on today's machines with 4-or-more-way interleaved caches.

The shape of an array is the ndims element vector of its dimensions dims. For example, for the array A in our example above, it's shape is the vector (3,5,2). The core shape of an array is its shape less the special dimension attributed to its kind. For example, A has core shape (3,5) if it is of COMPLEX_KIND, (5,2) if it is of RGB_KIND, and (3,5,2) if it is of PLAIN_KIND. Care must be taken that some routines work with core shapes (e.g. all the drawing routines) while most work directly with an array's shape.

While rgb and rgba arrays are typically of type UINT8_TYPE or UINT16_TYPE, and complex array are typically FLOAT32_TYPE or FLOAT64_TYPE, we do not so restrict them nor do our tiff reader/writer routines. For the alpha channel the convention is that alpha is between 0. and 1. for floating point types, and for integer types, no transparency or 100% opacity, is denoted by the largest possible positive value encodable with the number of bits given by the type and scale, e.g. 1024 = 2^10-1 when type = UINT8_TYPE and scale = 10, and 32677 = 2^15-1 when type = INT16_TYPE and scale = 16.

Finally, every array has an associated text tag, text, whose length is tlen. The text tag is generally the empty string for ordinary arrays, but one can label arrays with arbitrarily long strings if they find it useful. In particular, the Print_Inuse_List routine will list the text tag of each array so one can identify them in the usage analysis report when trying to debug an object memory leak. Furthermore the text tag is read/written from and to the JF_TAGGER tag of a TIFF file by Mylib, so it can be used as a means to encode arbirary amounts of meta-data about an array or image.

Creating and Accessing Arrays

There are currently four ways to generate a new array from scratch: Make_Array, Make_Array_With_Shape, Make_Array_Of_Data and Make_Array_From_Arrays. The first two routines take parameters that specify the kind, type, and core shape of the array desired. Make_Array recieves the shape as an ndim,dims pair and Make_Array_With_Shape recieves it in the form of an integer Coordinate. Make_Array_Of_Data takes a linear data array supplied by the caller and wraps an array object around it, taking ownership of the data vector. Make_Array_From_Arrays takes an array of pointers to say n arrays all of the same shape α, generates an array of shape (n,&alpha), and fills it in with the values of the n arrays. For example, one can construct an RGB_KIND array from three planes as follows:

 Array **planes[3];

 planes[0] = a_red_array;
 planes[1] = a_green_array;
 planes[2] = a_blue_array;
 color = Make_Array_From_Arrays(RGB_KIND,3,planes);

One can set the text tag of an array with Set_Array_Text and append to it with Append_To_Array_Text. There are also simple routines to get and set a given element of an array: Get_Array_Value and Set_Array_Value. These are provided mostly as an example for users in order to make sure they understand how elements are indexed and accessed. Any serious computation over an array is expected to be done directly with indices into an array's data or with the aid of the array traversal mechanisms provided by the Slice and Frame classes.

One can select sub-slices of an array by peeling away the outer dimension with Get_Array_Plane. The idea is to be efficient and not create a new array object, but rather a "fake" array that is valid as long as the underlying real array object is not modified. This "fake" array is an Array_Bundle that is just the outer struct of an array object whose dims, data, and text pointers are into a real array's structure. Get_Array_Plane takes a valid Array_Bundle and modifies it so that upon return the bundle models the requested sub-array. The tricky part is that the bundle must initially be set up by assigning it to the outer-struct of a real array object. For example, the code below, takes the color array from the example above, and peals off each color sub-array:

 Array_Bundle red, green, blue;

 red = green = blue = *color;
 Get_Array_Plane(&red,0);
 Get_Array_Plane(&green,1);
 Get_Array_Plane(&blue,2);

If a real independent, and proper object is need for a sub-array then call Copy_Array on the fetched plane, e.g. Copy_array(&red). Moreover, more than one layer of outer dimensions can be peeled away:

 Array_Bundle bundle;
 Get_Array_Plane(Get_Array_Plane(&(bundle=*color),1),3);

gets the 3rd z-plane of the green pixels when color is a 3D RGB_KIND array.

One can produce an ASCII print out of an array, slice, or frame with Print_Array. The caller can specify the indentation, the output stream to be written to, and the format in which to print the numbers. Obviously this capability is not designed for very large arrays, but more for small examples to help one develope a code using Mylib. Moreover, arrays are typically so frequently used in a code that there is the possibility of failing to free or kill one, creating a memory leak. To facilitate the developers efforts we provide the routine Print_Inuse_List that gives a report of all the currently active arrays, slices, and frames at the current moment. A typical output follows:

   Arrays:
      1 : 3 int32 = 12
      1 : 3 int32 = 12
      3 : 3 x 4 x 5 int32 = 240
   Slices:
      1 : (0,0,0) - (2,3,4) int32
   Frames:
      1 : 8 x 8 x 8 int32 = 12.3Kb

Generalization and Specializations of Arrays: AForms, Matrices, ...

There are a large number of type definitions in the header of this page -- e.g. Matrix, Vector, etc. -- that are effectively all equivalent to Array. The intent is to document the kind, type, and/or dimensionality of the array that is being operated upon. For example, if one sees a routine declaration where the argument is a Complex_Matrix, then one knows that the argument should be a FLOAT32_TYPE or FLOAT64_TYPE, 2D array of either PLAIN_KIND or COMPLEX_KIND. In general, if a routine takes an argument that can only be a subset of all the possible array types, kinds, and dimensionalities, then the routine actually checks that the argument meets those constraints before proceeding, and conversely if it returns such a typed retult, then one can be sure that it satisfies the constraints of the type name.

In the direction of generalization, note that the key attributes of an array-like object is that it is an n-dimensional lattice of values of some Value_Type that may be interpreted specially based on its Array_Kind. In addition to Arrays, Mylib also supports Slices that are any hyper-rectangular sub-region of an underlying array, and Frames that are hyper-rectangular shape windows that can be moved over an underlying array (but need not lie within its lattice). Any routine that takes an Array as a read-only argument could equally well take a Slice or a Frame as the argument. The union of the three classes is termed an array form and an AForm class is introduced to model this generalization of the three base classes. Note carefully that many of the "array" routines on this page have been generalized to take AForms as arguments. Similarly, note that any routine that takes an Array as an argument for which only it's elements will be modified (and not it's shape, type, etc.), could equally well take a Slice as an argument (but not a Frame as a frame may not lie with the boundary of its underlying array), in which case only the elements of the underlying array delimited by the slice's hyper-rectangle are modified. The union of the Array and the Slice classes is termed an array part and an APart type is introduced to model this genalization. Again, note that many of the "array" routines on this page have been generalized to take AParts as arguments.

Coordinates

Many if not most Mylib routines address an element of an array with an index directly into the linear vector pointed at by the data field. But conceptually an address into an n-dimensional array, is an integer coordinate (x0,x1...xn) into the n-dimensional lattice -- [0,dims[0]-1] x [0,dims[1]-1] x ... x [0,dims[n]-1] -- of the array. In the subsection on the anatomy of an array above we showed how to map such a coordinate to an index into the data vector, that is, we specified the mapping Mylib uses to assign lattice positions to linear positions in data's linear vector.

It is clearly conceptually easier for a human being to think in terms of coordinates than in terms of indices. So Mylib supports the idea of a Coordinate which is itself an array that is 1-dimensional and of type Dimn_Type (a signed 32-bit integer). There are routines that create coordinates with specific values and lengths (Coord, Coord1, Coord2, Coord3, Coord4), routines that convert coordinates to indices and vice versa (Idx2CoordA, Idx2CoreA, Coord2IdxA), routines that add dimensions to a coordinate (AppendCoord, PrependCoord), and routines to round real-valued n-dimensional points to the nearest coordinate (Floor_Coord, Ceiling_Coord, Nearest_Coord). Coordinates are also used to specify the shape of an array (see AForm_Shape for an example) and to model offsets relative to a point in an array's n-dimensional lattice (see Make_Frame for an example). Coordinates are generally short-lived objects and so the convention is that most routines that recieve coordinates as input parameters, free or subsume them before returning.

The routines Idx2CoordA and Coord2IdxA convert between coordinates and array indices. Note carefully that the conversions require a parameter specifying the array in question as the shape of the array must be known in order to perform the conversion. As an alternative to always supplying the array as an argument, we maintain a global current basis which can be set with Set_Coord_Basis or Use_Array_Basis and retrieved with Get_Coord_Basis. The conversions of Idx2Coord and Coord2Idx (note the 'A' is missing from the names) take place with respect to the current basis. Clearly the use of the current basis is not re-entrant, but the routines for setting it are thread-safe. For code that must be re-entrant, you must use Idx2CoordA and Coord2IdxA.

For arrays whose kind is not PLAIN_KIND, one often needs to describe coordinates as if the special dimension (i.e. the outermost for RGB_KIND and RGBA_KIND, and the innermost for COMPLEX_KIND) were not present. This is particularly true of drawing routines (see the Draw module) where a "brush" of kind PLAIN_, RGB_, RGBA_, or COMPLEX_KIND is being applied to an array of the given kind. We consider such a truncated coordinate a core coordinate in direct analogy to the idea of the core shape of an array. Many routines in the library will accept either a core coordinate or a complete coordinate. In those instances, it is generally the case that: when a core coordinate is being used as a point, the special dimension is assumed to be 0, and when being used as a shape or basis, it gets filled in with the width of the special dimension. Idx2CoreA and Idx2Core convert an array index into a core coordinate (where any offset in the special dimension is ignored), and Coord2IdxA and Coord2Idx will accept core coordinates and assume the coorindate for the special dimension is 0. Note, that Idx2Core requires that the current basis also records the kind of the basis as well.

Basic Array Routines

Converting an array from one type, kind, and/or scale to another is frequently required. Convert_Array performs such a conversion generating a new array for the result, whereas Convert_Array_Inplace does so in the existing memory blocks of the array in question, increasing the size of said blocks if necessary. Similarly, Convert_Image and Convert_Image_Inplace convert arrays that are presumed to model an image where the routine Image_Check will ascertain if a given array is an image. An array is considered an image if all values are between 0 and 2scale-1−1 for a signed integer array, are all between 0 and 2scale−1 for an unsigned integer array, and between 0. and 1., inclusive, for a floating point array.

There are quite a few routines for performing basic element-by-element functions on an array. Array_Range computes the range of values in an array, and Scale_Array and Scale_Array_To_Range offer two ways to scale and offset the values in an array. Array_Op_Scalar combines every element of an array with a particular scalar value via any of the ten supported Operators and Array_Op_Array does an element-wise combination between two arrays. There are also Complex_Op_Scalar, Complex_Op_Array, and Complex_Op_Complex that require the first argument be a COMPLEX_KIND array and for these routines the combining is done via complex arithmetic when it makes sense. Array_Fct_Val replaces each element of an array with a new value that is any caller-defined function of its current value, while Array_Fct_Idx replaces each element with a caller-defined function of its coordinate in the array's lattice. Threshold_Array binarizes an array against a background/foreground threshold value.

Array multiplication and index-table mapping are two operations that can be generalized to arrays of any dimension provided the innermost dimension of the first array equals the outermost dimension of the second for multiplication, and the range of values in the first array equals the innermost dimension of the second for mapping. The routines Array_Multiply and Apply_Map realize these generalized versions of the operations. For fast matrix multiplication for linear algebra, one should use Matrix_Multiply in the Linear Algebra module. On the other hand if you read a color-mapped image in the Image I/O module then one should use Apply_Map to perform the color mapping if desired.

Finally, there are routines to clip, pad, and downsample an array. They come in a generator version that makes a new array holding the result (Clip_Array, Pad_Array, and Down_Sample), and in-place versions that perform the operation in the memory of the subject array, expanding said if necessary (Clip_Array_Inplace, Pad_Array_Inplace, and Down_Sample_Inplace). One should particularly note that how an array gets padded is a function of the current boundary effect.


Visible Fields Documentation

kind: Array_Kind

Indicates whether an array can be interpreted as an rgb, rgba, or complex array, as opposed to just an ordinary or plain array. If an RGB_KIND array, then the outermost dimension is 3 and (A[0,α],A[1,α],A[2,α]) is an rgb color triple for each index sequence α. If an RGBA_KIND array, then the outermost dimension is 4 and (A[0,α],A[1,α],A[2,α],A[3,α]) is an rgba color for each α. If an COMPLEX_KIND array, then the innermost dimension is 2 and A[α,0] + [i] A[α,1] is a complex number for each α.

type: Value_Type

Specifies the type of the elements of an array which can be one of the ten number types supported in C.

scale: int

If the array has integer elements, then this field specifies the number of bits used to encode the values. It cannot be more than the number of bits in the type. A typical example where this field comes into play would be 12-bit microscopy data, for which type would be UINT16_TYPE and scale would be 12. This field only has an effect when converting an array (e.g. Convert_Array) or when reading or writing the array to a TIFF file (where only the number of bits per value is read or written).

ndims: int

The number of dimensions of the array.

dims: Dimn_Type *

dims[i] gives the size of the ith dimension of the array for i from 0 to ndims-1.

tlen: int

The length of the text tag text.

text: string

An arbirary text tag for the array. Typically empty, but you can use it to label an array so you can identify it in a space usage report produced by Print_Inuse_List, or you can place, say xml-encoded meta-data describing the image acquisition parameters of the microscope that produced the data. This tag is read and written to and from the JF_TAGGER tag of a TIFF file for this purpose.

data: void *

A void pointer to the elements of the array stored as a linear vector. To obtain a pointer to the appropriate type use one of the routines AUINT8, AUINT16, ... AFLOAT64 below (these are actually simple macros). The elements are layed out with dims[0] being the fastest moving dimension, i.e., for an n-dimensional array the index of A[xn-1,...,x1,x0] is

(... (xn-1*dims[n-2] + xn-2)*dims[n-3] + ...)*dims[0] + x0

using Horner's rule.

size: Size_Type

The total number of elements in the array.


Structure Documentation

Array_Bundle : Array

Used to serve as a short term construct that can be passed as an array to any routine that does not modify that array argument. It is just the outer struct of an array object: the dims vector, data vector, and text tag all point to another array's memory (so do not modify that array until the Array_Bundle is no longer in use). This is not often used save for efficiency or simplicity. For example, for a 3D array A one can get the ith z-plane as an Array_Bundle using Get_Array_Plane as follows:

   Array_Bundle plane;
   Range_Bundle range;
    ...
   plane = *A;
   Get_Array_Bundle(&plane,i);
   Array_Range(&range,&plane);

Range_Bundle : struct
maxval: Value
minval: Value

Used by Array_Range so that it can record the minimum and maximum value seen in the AForm in question.

Extent_Bundle : struct
min: Vector *
max: Vector *

This bundle is passed to routines like Region_Extent and SWC_Tree_Extent so that they can be filled in with the minimum and maximum vectors, min and max, respectively, of the smallest bounding box that encloses all the elements of the object in question. The type of the arrays for min and max depends on the routine, e.g. Region_Extent fills in Coordinates and SWC_Tree_Extent fills in Double_Vectors.


Enumerated Scalars Documentation

Array_Kind: { PLAIN_KIND, RGB_KIND, RGBA_KIND, COMPLEX_KIND }

The four supported kinds of an array.

Color_Index: { RED_INDEX, GREEN_INDEX, BLUE_INDEX, ALPHA_INDEX }

The indices into the red, green, blue, and alpha sub-arrays of a color array. Primarily defined for those that wish to write more descriptive code as one can equally well use 0, 1, 2, and 3 as the indices.

Complex_Index: { REAL_INDEX, IMAG_INDEX }

The indices for the real and imaginary parts of the innermost dimension of a complex array. Primarily defined for those that wish to write more descriptive code as one can equally well use 0 and 1 for this purpose.


Routine Documentation

uint8 AUINT8 (Array *a)
uint16 AUINT16 (Array *a)
uint32 AUINT32 (Array *a)
uint64 AUINT64 (Array *a)
int8 AINT8 (Array *a)
int16 AINT16 (Array *a)
int32 AINT32 (Array *a)
int64 AINT64 (Array *a)
float32 AFLOAT32 (Array *a)
float64 AFLOAT64 (Array *a)

Each function returns a pointer to the data of array a that is of the type implied by its name. These functions are implemented as macros.

Dimn_Type ADIMN (Array *a)
Indx_Type AINDX (Array *a)
Size_Type ASIZE (Array *a)
Offs_Type AOFFS (Array *a)

Each function returns a pointer to the data of array a that is of the type implied by its name. For example, if a is a Coordinate then while one could access its elements with AINT32(a), it is better to do so with ADIMN(a), as the latter will remain correct even if the type of Dimn_Type were to change. These functions are implemented as macros.

Array * Make_ArrayG (Array_Kind kind, Value_Type type, int ndims, Dimn_Type *dims)

Creates an array of the given kind, type, and core shape, that is, if kind is other than PLAIN_KIND, then the shape specified by ndims and dims does not include the extra dimension for the kind which is automatically added.

Array * Make_Array_With_ShapeG (Array_Kind kind, Value_Type type, Coordinate *shape F)

Creates an array where the Coordinate shape gives the dimensionality and size of each dimension of the core shape of the matrix. See Coord for one way to easily make a shape (e.g. you could write Make_Array_With_Shape(RGB_KIND,UINT8_TYPE,Coord("4,2,3")). The shape coordinate is freed before returning.

Array * Make_Array_From_ArraysG (Array_Kind kind, int n, Array **arrays)

The parameter arrays is expected to be contain n pointers to arrays that all have the same type, kind, and shape α. Creates an array with shape (n,α) that is the concatenation of the n arrays. The n array objects are unaffected by the construction as their elements are copied to the new array. NB: If kind is COMPLEX_KIND then the arrays pointed at must all be of COMPLEX_KIND, otherwise all the array must be of PLAIN_KIND. Moreover, if kind is RGB_KIND then n must be 3 and if kind is RGBA_KIND then n must be 4.

Array * Make_Array_Of_DataG (Array_Kind kind, Value_Type type,
                                         int ndims, Dimn_Type *dims, void *data)

Creates an array whose data vector is the one supplied as the last argument data. The argument conventions are otherwise exactly as for Make_Array. The data vector must be of size at least size*sizeof(type) bytes and the memory management of this vector is taken over by the array class.

void Set_Array_Text (Array *a M, string text)

Set the text tag of array a to text.

void Append_To_Array_Text (Array *a M, string text)

Append text to the text tag of array a.

Value Get_Array_Value (Array *a, Coordinate *coord F)

Get the value of the element at coordinate coord in array a. The coordinate coord is freed upon return and the value is passed back in a Value structure.

void Set_Array_Value (Array *a M, Coordinate *coord F, Value v)

Set the value of the element at coordinate coord in array a to v. The coordinate coord is freed upon return and the value v is passed to the routine in a Value structure.

Array_Bundle * Get_Array_Plane (Array_Bundle *a RM, Dimn_Type plane)

Select the planeth (n-1)-dimension sub-array of the, say n-dimensional, Array_Bundle a, which is basically just the outer struct of an array object, where the dims, data, and text fields point to the memory of some real array object. A bundle is initialized by assigning it the value of a proper array's struct. Get_Array_Plane returns a pointer to a after modifying its fields (in the bundle only) so that it now models the selected sub-array. For example, the code below, takes the color array from the example above, and peals off each color sub-array:

 Array_Bundle red, green, blue;

 red = green = blue = *color;
 Get_Array_Plane(&red,0);
 Get_Array_Plane(&green,1);
 Get_Array_Plane(&blue,2);

If a real independent, and proper object is need for a sub-array then call Copy_Array on the fetched plane, e.g. Copy_Array(&red). Moreover, more than one layer of outer dimensions can be peeled away:

 Array_Bundle bundle;
 Get_Array_Plane(Get_Array_Plane(&(bundle=*color),1),3);

gets the 3rd z-plane of the green pixels when color is a 3D RGB_KIND array.

void Print_Array (AForm *a, FILE *output, int indent, string format)

Print an array or slice or frame in a tabular form on the open FILE output. The display depends on the kind of the array and is indented by indent spaces from the left margin. The format string must be appropriate for the type of data in the array, e.g. "%10lld" for an INT64_TYPE array, or "%6.4f" for a FLOAT32_TYPE array.

void Print_Inuse_List (FILE *output, int indent)

Prints out a report of the current set of arrays, slices, and frames currently in use by the program to the specified output, indented by the amount specified by indent.

Coordinate * CoordG (string list)

The routine expects the string list to be a comma-separated list of integer constants. The routine generates a coordinate corresponding to the list, e.g. Coord("3,4,2") produces a 3-element coordinate.

void Print_Coord (FILE *f, Coordinate *coord F)

Print the coordinate coord as an comma-separated list of integers to the file f.

Coordinate * Coord1G (Dimn_Type d1)
Coordinate * Coord2G (Dimn_Type d2, Dimn_Type d1)
Coordinate * Coord3G (Dimn_Type d3, Dimn_Type d2, Dimn_Type d1)
Coordinate * Coord4G (Dimn_Type d4, Dimn_Type d3, Dimn_Type d2, Dimn_Type d1)

Generate a k-element coordinate (d1,d2,d3,...) according to the name of the routine and the number of its arguments.

Coordinate * AppendCoord (Dimn_Type d, Coordinate *coord RM)

Add integer d as the outermost dimension of coordinate coord and return a pointer to the modified coordinate.

Coordinate * PrependCoord (Coordinate *coord RM, Dimn_Type d)

Add integer d as the innermost dimension of coordinate coord and return a pointer to the modified coordinate.

Coordinate * Idx2CoordAG (Array *a, Indx_Type idx)

Generates the coordinate in array a's lattice corresponding to index idx into its data vector.

Indx_Type Coord2IdxA (Array *a, Coordinate *coord F)

Returns the index corresponding to the position of coordinate coord within the lattice of array a.

void Set_Coord_Basis (Coordinate *coord F, Array_Kind kind)

Sets the current basis for Mylib to the given shape and kind. Specifying the kind is important as it affects the operation of Idx2Core which must know if any of the dimensions of shape are special.

void Use_Array_Basis (Array *a)

Sets the current basis for Mylib to that of the array a.

Coordinate * Get_Coord_BasisG (Array_Kind *kind O)

Generates a coordinate that models the shape of the current basis, and returns in the value pointed at by kind the kind of the current basis.

Coordinate * Idx2CoordG (Indx_Type idx)

Returns the coordinate in the current basis corresponding to index idx.

Indx_Type Coord2Idx (Coordinate *coord F)

Returns the index corresponding to the position of coordinate coord within the lattice of the current basis.

Coordinate * Idx2CoreAG (Array *a, Indx_Type idx)

Generates the core coordinate in array a's lattice corresponding to index idx into its data vector.

Coordinate * Idx2CoreG (Indx_Type idx)

Generates the core coordinate in the lattice of the current basis corresponding to index idx.

Coordinate * Floor_CoordG (Double_Vector *point)

Generate the coordinate produced by taking the floor of every element of point.

Coordinate * Ceiling_CoordG (Double_Vector *point)

Generate the coordinate produced by taking the ceiling of every element of point.

Coordinate * Nearest_CoordG (Double_Vector *point)

Generate the coordinate produced by taking rounding every element of point to the nearest integer.

Array * Convert_ArrayG (Array *a, Array_Kind kind, Value_Type type, int scale, int|double factor)

Converts the array a to one of the specified kind, type, and scale in a newly generated array, say t, and returns a pointer to it. The result is as if the assignement t[i] = Mapping(a[i])*β were made for each core element (i.e. RGB-triple, complex number, ...) where i ranges over the core shape of a, Mapping converts between different kinds of elements, and β is a scaling factor. If the types of a and t are different then the the right hand side is computed in a's type space and then the type conversion takes place during the assignment as per C's type rules.

If the kind remains unchanged, the Mapping is the identity fucntion. Otherwise the table below gives the function implied by each source/target kind pair. The free variable i is assumed to range over all possible core coordinates of a (and t).

ConversionMapping
PLAIN to RGB t[0,i] = t[1,i] = t[2,i] = a[i]
PLAIN to RGBA t[0,i] = t[1,i] = t[2,i] = a[i], t[3,i] = &alpha(t)
RGB to RGBA t[c,i] = a[c,i] for c ∈ {0,1,2}, t[3,i] = &alpha(t)
RGBA to RGB t[c,i] = a[c,i]*a[3,i] / α(a) for c ∈ {0,1,2}
RGB to PLAIN t[i] = .30*a[0,i] + .59*a[1,i] + .11*a[2,i]
RGBA to PLAIN t[i] = (.30*a[0,i] + .59*a[1,i] + .11*a[2,i])*a[3,i] / α(a)
PLAIN to COMPLEX t[i,0] = a[i], t[i,1] = 0
COMPLEX to PLAIN t[i] = (a[i,0]2 + a[i,1]2).5
KIND X to KIND Y KIND X to PLAIN to KIND Y

The last row of the table is intended to capture any conversion not specified in the previous rows of the table. For example, a COMPLEX_KIND to RGB_KIND transformation is conceptually the result of first converting the COMPLEX_KIND to a PLAIN_KIND and then converting the PLAIN_KIND to an RGB_KIND. The quantity &alpha(x) is (a) 2 x->scale−1 if the type of x is one of the unsigned integer types, (b) 2 x->scale-1−1 if the type of x is one of the signed integer types, and (c) 1 if the type of x is one of the floating point types. Intuitively it is the fully opaque value for the alpha component of an RGBA_KIND array of the same type as x.

Conceptually after being mapped as per the table above, each value is then scaled by a factor β except for an alpha component if it has been newly introduced. The value of β is determined by the parameter factor as follows. If the type of a or the type of t is a floating point type, then the parameter factor is interpreted as a double value and it is β. Otherwise, factor is interpreted as an int argument and the value of β is effectively 2-factor. We say "effectively" because the multiplication by β is actually accomplished with a left or right bit shift. The scale of t is simply set to the scale parameter; one must set factor appropriately if an actually scale change in the value resulting from the kind Mapping is required.

Array * Convert_Array_Inplace (Array *a RM, Array_Kind kind, Value_Type type,
                                          int scale, int|double factor)

Convert a in the same way as Convert_Array above, but do so in-place, that is, a is overwritten with the converted result and a pointer to a is returned.

boolean Image_Check (Array *a)

Check whether or not an array is an image. An array is considered an image if all its values are between 0 and 2 scale-1−1 for a signed integer array, are all between 0 and 2 scale−1 for an unsigned integer array, and between 0. and 1., inclusive, for a floating point array.

Array * Convert_ImageG (Array *a, Array_Kind kind, Value_Type type, int scale)

Converts an image into one of the given kind, type, and scale in a newly generated array that is returned as the result. Unlike Convert_Array, values are scaled so that the relative intensity of a pixel element is preserved. For example, if a has type UINT16_TYPE and scale 12, then (a) if type is UINT8_TYPE and scale is 8, then values of a will be right-shifted 4 bits, (a) if type is FLOAT32_TYPE, then values of a will be divided by the floating point value 2 scale−1, and (c) if type is INT32_TYPE and scale is 24, then the values of a will be left-shifted 11 bits.

Array * Convert_Image_Inplace (Array *a RM, Array_Kind kind, Value_Type type, int scale)

Convert image a in the same way as Convert_Image above, but do so in-place, that is, a is overwritten with the converted result and a pointer to a is returned.

Range_Bundle * Array_Range (Range_Bundle *range RO, AForm *a)

Returns the smallest and largest value in array in the maxval and minval fields of the Range_Bundle.

APart * Scale_Array (APart *a RM, double factor, double offset)

Each element of a is first ofset by offset and then scaled by factor, i.e. a[i] = factor * (a[i] + offset) for all i in basis of a.

APart * Scale_Array_To_Range (APart *a RM, Value min, Value max)

Scales every element of a so that the largest (after scaling) equals max and the smallest equals min. Returns a for convenience.

APart * Array_Op_Scalar (APart *a RM, Operator op, Value_Type type, Value v)

Combines each element in a with the value v of type type according to the selected Operator op. The table below lists the operational effect. Not carefully that if a and v are not of the same type, then results are coreced for the operation and assignment according to the rules of the C-language. v must be a positive integer if either of the two shift operators is requested.

OperatorEffect
SET_OP a[i] = v
ADD_OP a[i] = a[i] + v
SUB_OP a[i] = a[i] - v
MUL_OP a[i] = a[i] * v
DIV_OP a[i] = a[i] / v
POW_OP a[i] = a[i] ^ v
LSH_OP a[i] = a[i] << v
RSH_OP a[i] = a[i] >> v
MIN_OP a[i] = min(a[i],v)
MAX_OP a[i] = max(a[i],v)

APart * Complex_Op_Scalar (APart *a RM, Operator op, Value_Type type, Value v, Value w)

Assumes a is of COMPLEX_KIND and combines each complex element of a with the complex number v+iw. All arithmetic is done in the field of complex numbers. However, for the shift and min/max operators, the operations are performed on the real and imaginary parts separately, e.g. for LSH_OP, a[i].real <<= v and a[i].imag <<= w. v and w must be positive integers if either of the two shift operators is requested.

APart * Array_Op_Array (APart *a RM, Operator op, AForm *b)

Combine, element-wise, the elements of the arrays a and b with Operator op, leaving the result in the element of a. a and b do not have to be the same size, type, or kind. If b is larger than a, then the first a->size elements of b are combined with the elements of a. If b is smaller than a, then the elements of b are used in a circular fashion until every element of a has been operated upon. This is reflected in the table below by the use of the expression b[i%|B|] where |B| is, b->size, the size of b.

OperatorEffect
SET_OP a[i] = b[i%|B|]
ADD_OP a[i] = a[i] + b[i%|B|]
SUB_OP a[i] = a[i] - b[i%|B|]
MUL_OP a[i] = a[i] * b[i%|B|]
DIV_OP a[i] = a[i] / b[i%|B|]
POW_OP a[i] = a[i] ^ b[i%|B|]
LSH_OP a[i] = a[i] << b[i%|B|]
RSH_OP a[i] = a[i] >> b[i%|B|]
MIN_OP a[i] = min(a[i],b[i%|B|])
MAX_OP a[i] = max(a[i],b[i%|B|])

APart * Complex_Op_Array (APart *a RM, Operator op, AForm *b)

The effect is similar to Array_Op_Array above except that a must be of COMPLEX_KIND and each non-complex element of b is combined with each complex element of a and complex arithmetic is used for all but the shift and min/max operators. To be a bit more precise, if p is the index corresponding to a core coordinate c of a, then the complex number a[c,0] + i a[c,1] is combined with b[p%|B|] according to op. For, the shift and min/max operators, the b-value is applied to both parts of the a-value, e.g. x+iy << e is (x<<e) + i (y<<e).

APart * Complex_Op_Complex (APart *a RM, Operator op, AForm *b)

The effect is similar to Array_Op_Array above except that a and b must both be of COMPLEX_KIND and complex arithmetic is used to combine elements except for the shift and min/max operators which take place on the real and imaginary parts separately, e.g. x+iy << c+id is (x<<c) + i (y<<d).

APart * Array_Fct_Val (APart *a RM, Value (*fct)(void * valp))

For each element of a, the routine calls the handler fct with a void pointer to the element and replaces the element with whatever Value fct returns.

APart * Array_Fct_Idx (APart *a RM, Value (*fct)(Coordinate *coord))

For each element of a, the routine calls the handler fct with the Coordinate of the element and replaces the element with whatever Value fct returns.

APart * Threshold_Array (APart *a RM, Value cutoff)

Binarizes the image with respect to threshold cutoff. That is, every element whose value is less than or equal to cutoff is set to 0, and every element other element is set to 1.

Array * Array_MultiplyG (Array *a, Array *b)

Multiply arrays a and b where they must both be of the same type and the innermost dimension of a must be of the same length as the outermost dimension of b. If either a or b is of COMPLEX_KIND then complex arithmetic is performed and a COMPLEX_KIND array is returned. The kind of the arrays is otherwise ignored and a PLAIN_KIND array returned.

The routine handles all type situations and complex multiplication and is therefore not as efficient as the carefully-crafted Matrix_Multiply routine in the Linear Algebra module for multiplying Double_Matrixes together.

Array * Apply_MapG (Array *image, Array *map)

A general routine for mapping array data, but specifically inspired by image "color maps". The array image must be of PLAIN_KIND and unsigned integer type. The array map must have dimension at least 1 and its inner dimension must be equal to m = 2 image->scale, i.e. the range of values in image. Suppose the shape of map is (α,m). Each value v in image is replaced with the *array* map[β,v]β of shape α. Thus the resulting array is of shape α.shape(image) and has the type and scale of map. A new array is created to hold the result and a pointer to it is returned.

Array * Down_SampleG (AForm *source, Coordinate *box F)

Downsample array source where the downsampling in each dimension is given by box. For example, Coord("2,3,4"), would downsample a 3 dimensional array by 4 pixels in dimension 0, 3 pixels in dimension 1, and 2 pixels in dimension 2. If the array is RGB_KIND, RGBA_KIND, or COMPLEX_KIND then the downsample vector need only specify the downsampling in the core shape, in which case the downsampling in the special dimesnion is assumed to be 1 (i.e. no downsampling). A pixel in the result is the average of the pixels it replaces. A new array is generated for the result and a pointer to it returned.

Array * Clip_ArrayG (AForm *source, Coordinate *beg F, Coordinate *end F)

Select the subset of source in the rectangle whose opposing corners are at the coordinates beg and end. For example, if beg = (2,4,3) and end = (6,7,8) then the sub-array source[2..6][4..7][3..8] will be returned. If the array is RGB_KIND, RGBA_KIND, or COMPLEX_KIND, then one is free to use core coordinates as well, in which case the entire range of the special dimension is assumed.

Array * Pad_ArrayG (AForm *source, Coordinate *anchor F, Coordinate *shape F)

Place the array source in a padded array of shape shape where its origin (index 0 pixel) is placed at coordinate anchor in the padded array. shape must be not smaller than the shape of source in every dimension. The padded array is padded according to the current boundary effect. (NB: Padding with zero's is the most efficient, the other padding effects take an extra pass over the boundary pixels.) If the array is RGB_KIND, RGBA_KIND, or COMPLEX_KIND, then shape and anchor can be a core shape and core coordinate, in which case the special dimension is not padded and the origins of the special dimension are aligned.

Array * Down_Sample_Inplace (Array *source RM, Coordinate *box F)

Same effect as Down_Sample except that it only applies to Arrays and modifies source to hold the downsampled result and returns a pointer to source. Be sure to pack the array Pack_Array) if you want to free up the space no longer required by the downsampled array.

Array * Clip_Array_Inplace (Array *source RM, Coordinate *beg F, Coordinate *end F)

Same effect as Clip_Array except that it only applies to Arrays and modifies source to hold the clipped result and returns a pointer to source.

Array * Pad_Array_Inplace (Array *source RM, Coordinate *anchor F, Coordinate *shape F)

Same effect as Pad_Array except that it only applies to Arrays and modifies source to hold the padded result and returns a pointer to source.