Built-in Functions

Table of Contents

  1. Elemental Functions
  2. Reduction and Scan Functions
  3. Metadata Functions
  4. Functions which change shape or order
  5. Linear-algebra Functions
  6. Correlation
  7. Geometry
  8. Grid Functions
  9. Functions related to Special Data-types
  10. Morphological Functions

Elemental Functions

The result of an elemental function has the same shape as its argument(s). Each element of the result is defined by applying the function to the corresponding element of the argument.

The following table is very similar to Table 5.3 in Ousterhout's 1994 classic Tcl and the Tk Toolkit:

Function Result
abs(x) Absolute value of x
acos(x) Arc cosine of x, in the range 0 to π
asin(x) Arc sine of x, in the range -π/2 to π/2
atan(x) Arc tangent of x, in the range -π/2 to π/2
atan(y,x) Arc tangent of y/x, in the range -π to π
atan2(y,x) Alias for atan
ceil(x) Smallest integer not less than x
cos(x) Cosine of x (x in radians)
cosh(x) Hyperbolic cosine of x
exp(x) ex, where e is base of natural logarithms
floor(x) Largest integer not greater than x
fmod(x,y) x%y
hypot(x,y) √(x2+y2)
isnan(x) 1 if x is NaN, 0 otherwise
log(x) logex (natural logarithm of x)
log(x,y) logyx
log10(x) log10x
nint(x) Nearest integer to x
pow(x,y) xy
random(x) f32 or f64 random number r such that 0r < x
round(x) Alias for nint
sign(x) Sign of x,   i.e. (x>0)-(x<0)
sin(x) Sine of x (x in radians)
sinh(x) Hyperbolic sine of x
sqrt(x) x
tan(x) Tangent of x (x in radians)
tanh(x) Hyperbolic tangent of x

The following data-type conversion functions are also elemental:
c8(x)
f32(x)
f64(x)
i8(x)
i16(x)
i32(x)
u8(x)
u16(x)
u32(x)
Here are some examples of their use:

% [nap "f32(97 .. 102)"] all; # convert from i32 to f32
::NAP::43-43  f32  MissingValue: NaN  References: 0  Unit: (NULL)
Dimension 0   Size: 6      Name: (NULL)    Coordinate-variable: (NULL)
Value:
97 98 99 100 101 102
% [nap "u8('abcdef')"]; # Display ASCII codes for 'abcdef'
97 98 99 100 101 102
% [nap "c8(97 .. 102)"]; # Reverse this process
abcdef

Reduction and Scan Functions

A reduction or insert function is one which has the effect of inserting a binary operator between the cells of its argument. If the argument is a vector then its elements are the cells and the result is a scalar. If the argument is a matrix then its rows are the cells and the result is a vector containing the sum of each column. Such functions are termed reductions because the result has a rank which is one less than the argument.

A classic example is the ∑ summation operation, which corresponds to the NAP function sum. This can be used as follows to produce a scalar (rank 0) result by summing a vector (rank 1):

% [nap "sum({0.5 2 -1 8})"]
9.5
This function sum can be applied to a matrix (rank 2) to produce a vector (rank 1). If the second argument is omitted then we get the sum of each column. If it is 1 we get the sum of each row. This is shown by:
% nap "mat = {
{2 5 0}
{6 7 1}
}"
::NAP::49-49
% [nap "sum mat"]
8 12 1
% [nap "sum(mat,1)"]
7 14

The NAP reduction and scan functions are listed in the following table:

Function Type Result
count(x[,r]) reduction Number of non-missing elements in rank-r sub-arrays of x
max(x[,r]) reduction Maximum of rank-r sub-arrays of x
min(x[,r]) reduction Minimum of rank-r sub-arrays of x
prod(x[,r]) reduction Product of rank-r sub-arrays of x
psum(x) scan Multi-directional partial-sums of x (see below)
psum1(x[,r]) scan Uni-directional partial-sums of rank-r sub-arrays of x (see below)
sum(x[,r]) reduction Sum of rank-r sub-arrays of x

The optional second argument of reduction functions is called the verb-rank (as in J). It specifies the rank of the sub-arrays (cells) to which the process is applied. In the above example the verb-rank was 1, so the matrix was split into vectors (corresponding to each row) before doing the summation. This final summation process is always done by summing along the first (most significant) dimension.

It is possible to specify a verb-rank of 0. This is useful with count() because each (rank 0) element is processed separately. If it is missing the result is 0, otherwise it is 1. So this gives us an elemental function for testing whether values are missing. Note that the rank does not change in this case! E.g.

% [nap "count({4 _ 2 -9}, 0)"]
1 0 1 1

Partial-sum Functions psum(x) and psum1(x[,r])

The result of psum(x) or psum1(x[,r]) has the same shape as x.

If x is a vector then these two functions give the same result. Let r be this result. Each element of r is defined by
I
r I = x i
i=0

For example:

% nap "x = {2 7 1 3 8 2 5 0 2 5}"
::NAP::14-14
% [nap "psum(x)"] value
2 9 10 13 21 23 28 28 30 35
% [nap "psum1(x)"] value
2 9 10 13 21 23 28 28 30 35

Missing values are treated as zeros. E.g.

% [nap "psum{5 -9 _ 6 4}"]
5 -4 -4 2 6

The following example shows how partial sums can be used to calculate a 3-point moving-average in an efficient manner:

% nap "ps = 0 // psum(x)"
::NAP::25-25
% $ps value
0 2 9 10 13 21 23 28 28 30 35
% [nap "(ps(3 .. 10) - ps(0 .. 7)) / 3.0"] value
3.33333 3.66667 4 4.33333 5 2.33333 2.33333 2.33333

Missing values can be handled as follows:

% nap "x = f64{2 7 1 _ 3 8 2 5 _ 0 2 5}"
::NAP::187-187
% nap "ps = 0 // psum(x)"
::NAP::192-192
% $ps value
0 2 9 10 10 13 21 23 28 28 28 30 35
% nap "psc = 0 // psum(isPresent x)"; # psum of counts
::NAP::203-203
% $psc value
0 1 2 3 3 4 5 6 7 7 8 9 10
% nap "i = 0 .. 9"
::NAP::209-209
% [nap "(ps(i+3) - ps(i)) / (psc(i+3) - psc(i))"] value
3.33333 4 2 5.5 4.33333 5 3.5 2.5 1 2.33333

The library function moving_average generalises this moving-average technique to any rank.

If the rank of x exceeds 1 then psum(x) and psum1(x[,r]) give different results. Function psum1 sums in a single direction defined by the verb-rank in the same manner as the reduction functions. If x is a matrix and r is the result psum(x), then each element of r is defined by
I J
r IJ = x ij
i=0 j=0

The following example uses the matrix mat defined above:

% $mat
2 5 0
6 7 1
% [nap "psum1(mat)"]
 2  5  0
 8 12  1
% [nap "psum1(mat, 1)"]
2 7 7
6 7 1
% [nap "psum(mat)"]
 2  7  7
 8 20 21

Other similar scan functions can be defined for partial products and so on. However NAP currently has only psum and psum1.

Metadata Functions

Metadata functions return information (other than data values) from a NAO. The same information can be obtained using an OOC, but these functions are more convenient within expressions.

Function Result
coordinate_variable(x[,d]) Coordinate variable of dimension d (default 0)
label(x) Descriptive title
missing_value(x) Value indicating null or undefined data
nels(x) Number of elements = prod(shape)
rank(x) Number of dimensions = nels(shape)
shape(x) Vector of dimension sizes

Functions which change shape or order

Function Result
sort(x[,r]) Sort rank-r sub-arrays of x into ascending order over most significant dimension
reshape(x) Spread the elements of x into a vector with shape nels(x)
reshape(x,s) Reshape the elements of x into an array with shape s
transpose(x) Reverse the order of dimensions of x
transpose(x,p) Permute the dimensions of x to the order specified by p

Here are some examples of the use of these functions:

% [nap "sort {6.3 0.5 9 -2.1 0}"]
-2.1 0 0.5 6.3 9
% [nap "sort({{3 0 2}{1 9 1}})"]; # sort each column
1 0 1
3 9 2
% [nap "sort({{3 0 2}{1 9 1}}, 1)"]; # sort each row
0 2 3
1 1 9
% [nap "reshape {{1 3 7}{0 9 2}}"] all
::NAP::217-217  i32  MissingValue: -2147483648  References: 0  Unit: (NULL)
Dimension 0   Size: 6      Name: (NULL)    Coordinate-variable: (NULL)
Value:
1 3 7 0 9 2
% [nap "reshape({6.3 0.5 9 -2.1 0}, {2 4})"] all
::NAP::224-224  f64  MissingValue: NaN  References: 0  Unit: (NULL)
Dimension 0   Size: 2      Name: (NULL)    Coordinate-variable: (NULL)
Dimension 1   Size: 4      Name: (NULL)    Coordinate-variable: (NULL)
Value:
 6.3  0.5  9.0 -2.1
 0.0  6.3  0.5  9.0
% [nap "transpose {{1 3 7}{0 9 2}}"] all
::NAP::228-228  i32  MissingValue: -2147483648  References: 0  Unit: (NULL)
Dimension 0   Size: 3      Name: (NULL)    Coordinate-variable: (NULL)
Dimension 1   Size: 2      Name: (NULL)    Coordinate-variable: (NULL)
Value:
1 0
3 9
7 2

Linear-algebra Functions

The function solve_linear(A[,B]) solves a system of linear equations defined by matrix A and right-hand-sides B. B can be either a vector or a matrix (representing multiple right-hand sides). If B is omitted then the result is the matrix inverse.

If the system is over-determined (more equations than unknowns) then the result is the solution of the linear least-squares problem. This solution minimizes the sum of the squares of the differences between the left and right-hand sides.

The following system of linear equations is solved by the following example:
  3x − 4y = 20
−5x + 8y = −36

% nap "A = {
{3 -4}
{-5 8}
}"
::NAP::14-14
% nap "B = {20 -36}"
::NAP::17-17
% nap "x = solve_linear(A, B)"
::NAP::20-20
% $x a
::NAP::20-20  f64  MissingValue: NaN  References: 1  Unit: (NULL)
Dimension 0   Size: 2      Name: (NULL)    Coordinate-variable: (NULL)
Value:
4 -2

We can check the result using matrix multiplication:

% [nap "A . x"]
20 -36

Correlation

The functions correlation and moving_correlation both calculate Pearson product-moment correlations. Function correlation calculates correlations between variables defined by the dimensions of its (one or two) arguments. Function moving_correlation calculates pattern (spacial) correlations between a (vector or matrix) window variable and variables defined by moving a window of the same shape around a larger array of the same rank.

Both functions handle missing values by omitting cases where one or both values are missing. The result consists of two layers. Layer 0 contains the correlation values themselves. Layer 1 contains the corresponding number of (non-missing) cases (sample size n) used to calculate these values.

Both functions produce an f64 result if any of the data is f64, but otherwise the result is f32.

Function correlation(x[, y])

If y is not specified then it defaults to x.

The 1st (most significant) dimensions of x and y must have the same size, since this corresponds to the number of cases. (For time-series this dimension is time.) The remaining dimensions (if any) of x and y are essentially merged into column dimensions, but do appear in the result.

For example, let x be a 80×3 matrix and y a 80×5 matrix. The command

nap "r = correlation(x, y)"
produces a 2×3×5 array r. r0ij is the correlation between column i of x and column j of y. r1ij is the number of cases (n) used to calculate r0ij.

A simple example is:

% [nap "correlation({1 3 _ 6 6}, {6 6 4 2 3})"]
-0.924138 4
Element 2 (base 0) of x is missing, so element 2 from y is not used and the sample size is 4 (as shown in the second element of the result). The correlation between {1 3 6 6} and {6 6 2 3} is calculated to be -0.924138.

The following example is from Table 15.2 (page 274) of Schaum's Outline of Theory and Problems of Statistics, M.R. Spiegel, 1961:

% [nap "correlation{
	{64 57 8}
	{71 59 10}
	{53 49 6}
	{67 62 11}
	{55 51 8}
	{58 50 7}
	{77 55 10}
	{57 48 9}
	{56 52 10}
	{51 42 6}
	{76 61 12}
	{68 57 9}
}"] -f %6.4f
 1.0000  0.8196  0.7698
 0.8196  1.0000  0.7984
 0.7698  0.7984  1.0000

12.0000 12.0000 12.0000
12.0000 12.0000 12.0000
12.0000 12.0000 12.0000
Layer 0 of the result is the correlation matrix.
The correlation between columns 0 and 1 is 0.8196.
The correlation between columns 0 and 2 is 0.7698.
The correlation between columns 1 and 2 is 0.7984.
There is no missing data, so all values in layer 1 are 12.

Function moving_correlation(x, y, [lag0[, lag1]])

The ranks of x and y must be the same. (The current version supports ranks 1 and 2 only.)

If x and y have the same shape then the result contains a single correlation, calculated by treating the elements of each array as two lists of values.

If x and y have different shapes then the smaller of x and y is a window (chip) array which is moved around in the other array, producing a correlation for each position.
lag0 is vector of row lags (default: all possible)
lag1 is vector of column lags (default: all possible)

Geometry

Testing whether points are in polygon

Function inPolygon(x, y, p) tests whether the points defined by x and y are inside the polygon defined by p. The result is

The algorithm is an extension of Wm. Randolph Franklin's PNPOLY. PNPOLY classifies points into only two categories, inside and outside. Points exactly on an edge can be classified either way. The modified algorithm in inPolygon does detect edge points.

The ranks of x and y can differ provided their trailing dimensions match. The shape of the result is that of the one of higher rank. If an element of x or y is missing then the corresponding element of the result is missing.

The argument p is an n×m matrix defining the n vertices (x,y) of the polygon. There must be at least one vertex. The number of columns (m) must be at least 2. Column 0 contains x. Column 1 contains y. Any other columns are ignored.

The following example tests whether the points (1,2), (2,2), (3,2), (4,2), (5,2), (6,2) are in the triangle with vertices (0,0), (5,0), (5,5):

% [nap "inPolygon(1 .. 6, 2, {{0 0}{5 0}{5 5}})"]
-1 0 1 1 0 -1

Triangulation

Triangulation is the process of joining scattered (x, y) points (called sites) to form triangles. One important use of triangulation is interpolation of (x, y, z) data. Function scattered2grid. interpolates by defining a plane for each triangle produced by triangulation.

The Delaunay triangulation is the optimal triangulation in various senses. For example, it maximises the minimum angle. Delaunay triangulation is closely related to Voronoi Diagrams which consist of polygons around each site. The points within each polygon are those which are closer to this site than to any other site. A good survey of Delaunay triangulation and Voronoi diagrams is given by

Franz Aurenhammer, Voronoi diagrams -- a survey of a fundamental geometric data structure , ACM Computing Surveys, Volume 23 , Issue 3 (September 1991), pp345-405, 1991

Function triangulate gives the triangles defined by Delaunay triangulation. Function triangulate_edges gives the edges defined by the same Delaunay triangulation. The code of both functions is based on a program written by Geoff Leach, Department of Computer Science, RMIT, Melbourne, Australia. This program implements a very efficient Delaunay triangulation algorithm that is O(n log n) time and O(n) space. This worst-case optimal divide-and-conquer algorithm is described in

Guibas, L. and Stolfi, J., Primitives for the manipulation of general subdivisions and the computation of Voronoi diagrams , Proceedings of the fifteenth annual ACM symposium on theory of computing, pp221-234, 1983.

Function Result
triangulate(sites) t×3 matrix of site indices defining t triangles
triangulate_edges(sites) e×2 matrix of site indices defining e edges

The argument sites is an n×m matrix defining the n points (x,y). The number of columns (m) must be at least 2. Column 0 contains x. Column 1 contains y. Any other columns are ignored. The row number is called the site index and ranges from 0 to n-1.

The following example triangulates the sites (0,0), (2,1), (0,1) and (1,2). These have site indices 0, 1, 2 and 3 respectively. Function triangulate gives the site indices of the vertices of each of two triangles. Function triangulate_edges gives the site indices of the vertices of each of the five edges of these same two triangles.

% [nap "triangulate({{0 0}{2 1}{0 1}{1 2}})"]
0 1 2
1 2 3
% [nap "triangulate_edges({{0 0}{2 1}{0 1}{1 2}})"]
0 2
0 1
1 3
1 2
2 3

Grid Functions

There are currently just two closely related grid functions, invert_grid and invert_grid_no_trim. These can be applied to

There is only a minor difference between these two functions. Function invert_grid suppresses edges (rows and columns in 2D case) containing nothing except missing values. Function invert_grid_no_trim does no such trimming.

In the 1D case we have a piecewise-linear mapping from x to y, and we want a piecewise-linear mapping from y to x. The functions are called by
invert_grid(y,ycv)
or
invert_grid_no_trim(y,ycv)
where y is the known mapping (and has a coordinate variable corresponding to x)
and ycv is the desired new y coordinate variable.

The following example starts with a mapping from x to y defined by the two lines joining the three points (0, 0), (2, 1) and (5, 4). The difference between invert_grid and invert_grid_no_trim is shown by attempting to extrapolate to y = −1 with both these functions. Both produce the inverse mapping from y to x defined by the four lines joining the five points (0, 0), (2, 1), (3, 2), (4, 3) and (5, 4). Function invert_grid_no_trim generates the requested point for y = −1 (with x missing) whereas invert_grid suppresses this point.

% nap "y = {0 1 4}"
::NAP::56-56
% $y set coo "{0 2 5}"
% [nap "coordinate_variable(y) /// y"]
0 2 5
0 1 4
% [nap "ycv = -1 .. 4"] value
-1 0 1 2 3 4
% nap "x = invert_grid(y,ycv)"
::NAP::75-75
% $x all
::NAP::75-75  f32  MissingValue: NaN  References: 1  Unit: (NULL)
Link: ::NAP::76-76
Dimension 0   Size: 5      Name: (NULL)    Coordinate-variable: ::NAP::72-72
Value:
0 2 3 4 5
% [nap "coordinate_variable(x) /// x"]
0 1 2 3 4
0 2 3 4 5
% nap "xnt = invert_grid_no_trim(y,ycv)"
::NAP::86-86
% $xnt all
::NAP::86-86  f32  MissingValue: NaN  References: 1  Unit: (NULL)
Link: ::NAP::87-87
Dimension 0   Size: 6      Name: (NULL)    Coordinate-variable: ::NAP::83-83
Value:
_ 0 2 3 4 5
% [nap "coordinate_variable(xnt) /// xnt"]
-1  0  1  2  3  4
 _  0  2  3  4  5

In the 2D case, the functions are called by
invert_grid(y,ycv,x,xcv),
or
invert_grid_no_trim(y,ycv,x,xcv),
where matrix y defines a mapping from ij space to y.
matrix x defines a mapping from ij space to x.
The result is a 3D array whose

  • Dimension 0 has the specified coordinate-variable ycv
  • Dimension 1 has the specified coordinate-variable xcv.
  • dimension 2 is of size 2, corresponding to the i and j mappings We can think of the result as two matrices defining mappings from xy space to i and j respectively.

    The following 2D example shows how a satellite image can be mapped to latitude/longitude space (i.e. a Cylindrical Equidistant map projection). Note that the terms line and pixel refer to the row and column of a raw satellite image respectively. We are interested in an input region bounded by line 40, line 50, pixel 1 and pixel 21. Assume we know the latitude and longitude on a 3×3 grid corresponding to lines 40, 50, 60 and pixels 1, 11, 21. The following defines and displays an inverse grid for latitudes 40°S, 30°S, 25°S and longitudes 150°E, 160°E, 170°E, 180°E:

    nap "line = {40 50 60}"
    nap "pixel = {1 11 21}"
    nap "lat_grid = {{-40 -50 _}{-30 -40 -50}{-20 -30 -40}}"
    $lat_grid set coo line pixel
    nap "lon_grid = {{200 180 _}{180 160 140}{160 140 120}}"
    $lon_grid set coo line pixel
    nap "lat_cv = {-40 -30 -25}"
    $lat_cv set unit degrees_north
    nap "lon_cv = 150 .. 180 ... 10"
    $lon_cv set unit degrees_east
    nap "ig = invert_grid(lat_grid, lat_cv, lon_grid, lon_cv)"
    $ig all
    
    This displays the following inverse grid:
    ::NAP::46-46  f32  MissingValue: NaN  References: 1  Unit: (NULL)
    Link: ::NAP::47-47
    Dimension 0   Size: 3      Name: (NULL)    Coordinate-variable: ::NAP::36-36
    Dimension 1   Size: 4      Name: (NULL)    Coordinate-variable: ::NAP::39-39
    Dimension 2   Size: 2      Name: (NULL)    Coordinate-variable: (NULL)
    Value:
    52.5 13.5
    50.0 11.0
    47.5  8.5
    45.0  6.0
    
    57.5  8.5
    55.0  6.0
    52.5  3.5
    50.0  1.0
    
    60.0  6.0
    57.5  3.5
    55.0  1.0
       _    _
    
    The following displays the coordinate variables of this inverse grid ig:
    % [$ig coo 0] all
    ::NAP::36-36  f32  MissingValue: NaN  References: 1  Unit: degrees_north
    Dimension 0   Size: 3      Name: (NULL)    Coordinate-variable: (NULL)
    Value:
    -40 -30 -25
    % [$ig coo 1] all
    ::NAP::39-39  f32  MissingValue: NaN  References: 1  Unit: degrees_east
    Dimension 0   Size: 4      Name: (NULL)    Coordinate-variable: (NULL)
    Value:
    150 160 170 180
    
    The first row of ig is
    52.5 13.5
    
    Let us use these values as indirect indices of the original latitude and longitude grids:
    % [nap "lat_grid(@52.5, @13.5)"]
    -40
    % [nap "lon_grid(@52.5, @13.5)"]
    150
    
    Note that these results correspond to the initial values of the coordinate variables of ig.

    Now let us define a small extract from a raw satellite image:

    nap "raw = {
    {99 91 91 90}
    {95 95 92 91}
    {90 89 88 88}
    }"
    nap "line = 50 .. 52"
    nap "pixel = 1 .. 4"
    $raw set coo line pixel
    

    The latitudes and longitudes at these points are given by

    % [nap "lat_grid(@line, @pixel)"]
    -30 -31 -32 -33
    -29 -30 -31 -32
    -28 -29 -30 -31
    % [nap "lon_grid(@line, @pixel)"]
    180 178 176 174
    178 176 174 172
    176 174 172 170
    

    We can map this image to a Cylindrical Equidistant projection as follows:

    % nap "latitude = f32(-29 .. -33)"
    ::NAP::135-135
    % nap "longitude = f32(170 .. 180)"
    ::NAP::142-142
    % nap "cyl_eq = raw(@ig(@latitude, @longitude, ))"
    ::NAP::166-166
    % $cyl_eq all -f %.1f -col 11
    ::NAP::166-166  f32  MissingValue: NaN  References: 1  Unit: (NULL)
    Dimension 0   Size: 5      Name: (NULL)    Coordinate-variable: ::NAP::152-152
    Dimension 1   Size: 11     Name: (NULL)    Coordinate-variable: ::NAP::153-153
    Value:
    91.0    _    _    _    _    _    _    _    _    _    _
    89.2 88.7 88.0 89.4 91.0 92.9 95.0 94.5 95.0 96.5 99.0
    88.0 88.8 89.8 90.8 92.0 92.3 92.2 91.8 91.0 92.1 92.2
    91.0 91.1 91.0 91.0 91.0 91.0 91.0 90.3 89.8 89.3 89.0
    95.0 94.7 93.8 92.2 90.0 89.7 89.2 88.7 88.0 89.4 91.0
    % [$cyl_eq coo 0] all
    ::NAP::152-152  f32  MissingValue: NaN  References: 1  Unit: degrees_north
    Dimension 0   Size: 5      Name: (NULL)    Coordinate-variable: (NULL)
    Value:
    -29 -30 -31 -32 -33
    % [$cyl_eq coo 1] all -col 11
    ::NAP::153-153  f32  MissingValue: NaN  References: 1  Unit: degrees_east
    Dimension 0   Size: 11     Name: (NULL)    Coordinate-variable: (NULL)
    Value:
    170 171 172 173 174 175 176 177 178 179 180
    

    Functions related to Special Data-types

    Function Result
    open_box(x) NAO pointed to by boxed NAO x
    pad(x) Normal NAO corresponding to ragged NAO x
    prune(x) Ragged NAO corresponding to normal NAO x

    The following example illustrates the use of the function open_box, which allows one to extract NAOs from a structure created with the operator ",".

    % nap "pointers = {4 5} , 'hello' , 9"
    ::NAP::9776-9776
    % $pointers
    9772 9773 9775
    % [nap "open_box(pointers(0))"] all
    ::NAP::9772-9772  i32  MissingValue: -2147483648  References: 1  Unit: (NULL)
    Dimension 0   Size: 2      Name: (NULL)    Coordinate-variable: (NULL)
    Value:
    4 5
    % [nap "open_box(pointers(1))"] all
    ::NAP::9773-9773  c8  MissingValue: (NULL)  References: 1  Unit: (NULL)
    Dimension 0   Size: 5      Name: (NULL)    Coordinate-variable: (NULL)
    Value:
    hello
    % [nap "open_box(pointers(2))"] all
    ::NAP::9775-9775  i32  MissingValue: -2147483648  References: 1  Unit: (NULL)
    Value:
    9
    

    The following example illustrates the use of functions prune and its inverse pad. Function prune creates a ragged array. This suppresses missing values at the start and end of the least significant dimension (column in this matrix case). In this matrix case it creates a separate NAO for each row and stores an index (slot number) to these in the result.

    % nap "data = {{0 1.5 2 -1}{_ 1 4 1n}{4#_}{2#_ 9 -9}}"
    ::NAP::9736-9736
    % $data
     0.0  1.5  2.0 -1.0
       _  1.0  4.0    _
       _    _    _    _
       _    _  9.0 -9.0
    % nap "compressed_data = prune(data)"
    ::NAP::9738-9738
    % $compressed_data all
    ::NAP::9738-9738  ragged  MissingValue: 0  References: 1  Unit: (NULL)
    Dimension 0   Size: 4      Name: (NULL)    Coordinate-variable: (NULL)
    Dimension 1   Size: 4      Name: (NULL)    Coordinate-variable: (NULL)
    Value:
    
    0   start-index: 0   ::NAP::9740-9740
    1   start-index: 1   ::NAP::9741-9741
    2   start-index: 4   ::NAP::9742-9742
    3   start-index: 2   ::NAP::9743-9743
    % ::NAP::9743-9743
    9 -9
    % [nap "pad(compressed_data)"] all
    ::NAP::9745-9745  f64  MissingValue: NaN  References: 0  Unit: (NULL)
    Dimension 0   Size: 4      Name: (NULL)    Coordinate-variable: (NULL)
    Dimension 1   Size: 4      Name: (NULL)    Coordinate-variable: (NULL)
    Value:
     0.0  1.5  2.0 -1.0
       _  1.0  4.0    _
       _    _    _    _
       _    _  9.0 -9.0
    

    Morphological Functions

    The basic concepts are explained in the MATLAB documentation on Morphological Operations.

    Function Result
    dilate(x,se[,seo]) Binary dilation of x; se = structure-element; seo = origin of structure-element
    erode(x,se[,seo]) Binary erosion of x; se = structure-element; seo = origin of structure-element
    moving_range(x,s) Range (max-min) of moving shape-s window around matrix x

    Morphological Binary Dilation and Erosion

    x is an n by m non-negative matrix that is being dilated or eroded.
    se is the morphological structure element, an a by b matrix, where a<n and b<m.
    seo is the origin of the structure element indexed from 0 at the top left corner.

    Moving Range

    Move a window over the matrix x and find the maximum difference between values in the moving window. The result is placed in the element nearest the centre of the moving window.

    Author: Harvey Davies       © 2002, CSIRO Australia.       Legal Notice and Disclaimer
    CVS Version Details: $Id: function.html,v 1.12 2005/03/08 23:16:15 dav480 Exp $