This chapter defines the lattice data type and how it is used in the IRIS Explorer environment. It describes the forms that lattices can take in one, two, and three dimensions and gives examples of how to create them.
The API (Application Programming Interface) routines are listed and examples of user function code for writing modules that manipulate lattices are included.
The IRIS Explorer lattice data type, cxLattice, contains all the information IRIS Explorer requires for creating arrays. An array is a regular, structured matrix of points, which can be 1-D or multidimensional. Because it is extremely versatile, you can use the cxLattice data structure to represent a wide variety of array data. Thus, some modules may accept a cxLattice with any number of dimensions, containing any number of data values, of any type. Other modules may, for example, accept only 1-D lattices in byte format. In general, the form of the array data you plan to feed into a module will determine how narrowly you define the lattice specifications on the input port in the Module Builder.
The IRIS Explorer lattice data structure has two parts. One holds data values and the other holds node coordinates. A node is a point in a lattice defined by a unique coordinate or set of coordinates in Cartesian space, usually indicating the position of the data value (or values). The data and coordinate arrays are optional, however. You can create a lattice with an empty data structure, and node coordinates only, or one with data values and no coordinate values.
The two array structures in cxLattice are cxData and cxCoord. The data and coordinate arrays are defined in separate variables because:
The
cxLattice
data type is one of the root data types, which means it can be placed on
module ports and will pass data into and out of modules. It has three main
parts, or subsidiary data structures:
This is the type definition for
cxLattice:
The type definitions for
cxData
and
cxCoord
are given below.
Figure
3-2
shows a schematic representation of
cxLattice.
The dimension variables in the cxLattice data type are:
The nDim variable indicates the number of dimensions of the
lattice. The dims array specifies the number of nodes in each dimension
- that is, the number of data values in each dimension.
From
Figure
3-2, it can be seen that
nDim
and
dims
are stored with both
cxData
and
cxCoord; the dimensions of these arrays are set by the values of
nDim
and
dims. Thus, these values
must
be consistent throughout the
cxLattice
structure; otherwise, you may get some bizarre results. For example, if you
define
nDim
as 3 and
dims
as [10,6,6] in
cxData, you must also define them as 3 and [10,6,6] in
cxCoord.
Data values go into the
cxData
type, which contains the value or values stored at each node of the lattice.
Its elements include:
This is the data type definition for cxData:
The Cartesian coordinate values that define the position of the lattice
nodes go into the cxCoord
data type. These values map the lattice data to Cartesian space. Its elements
include:
This is the data type definition for cxCoord:
Figure 3-3 shows the relationship of some
lattice variables. This example depicts a 2-D lattice with seven nodes in each
dimension and three data variables per node. Thus, nDim = 2,
dims[0] = 7 (x direction),
dims[1] = 7 (y direction), and
nDataVar = 3.
The lattice and coordinate data values are stored separately and in
different formats. Figure
3-4
shows how data from arrays in C and Fortran formats is stored in computer
memory, and illustrates the difference between row-major (C) and column-major
format (Fortran). The formats used by each data and coordinate lattice type
in cxLattice format are described below.
Lattice data is located at the coordinate nodes. In a 1-D array, or
vector, each node in the array has two neighbors (except the end points,
which each have only one), as shown in Figure
3-5. In two dimensions, each internal node has four neighbors. A node
internal to a 3-D array has six neighbors. An internal node in an
n-D array has 2*n
neighbors. This regular structure is the
computational
space of the lattice. This topology is completely determined by the value of
nDim
and the
dims
vector, and is to be distinguished from the
physical
space of the lattice, which is determined by its coordinates part.
Lattice data is stored in the Fortran convention, using a column-major
layout, in which the I direction of the array varies the fastest (see
Figure
3-6). For all lattice types, the I direction corresponds to the X
direction. Similarly, J corresponds to Y, and K to Z.
If a lattice has several data values at each node (that is, if
nDataVar > 1), then the data is stored in interleaved
format. In a color image, for example, the interleaving of RGB data looks
like this:
**To locate a particular node within an array, you use array
indexing. For example, the node located at (i,j,k) is:
You can compute the total number of data values in a lattice by calling
the API function
cxDimsProd. Since this number is the
product of the number of nodes in the lattice and
nDataVar, the number of data values at each node, you
can use this result to calculate the number of nodes in the lattice. See the
IRIS Explorer Reference
Pages pages for details on the API routines.
The primitive data type is defined in terms of C types in the lattice data
type. If you are programming in Fortran, choose the C primitive that is
equivalent to the Fortran variable that your subroutine expects.
Table
3-1
lists the equivalences between the two.
Coordinates are always stored in single-precision floating point (float)
format. The lattice data type allows for three types of coordinate mapping to
physical space: uniform, perimeter, and curvilinear. The interleaving of the
coordinate storage varies from type to type. Each type is described in detail
below.
A lattice with uniform coordinates has a uniform cell size throughout (see
Figure
3-7). Most generated data is in this format.
The data structure for a uniform lattice is:
The coordinate values are stored in row-major format, in the C
convention:
IRIS Explorer uses a bounding box to set the size and aspect ratio of
uniform lattice coordinates. Bounding boxes are dimensioned as a constant and
a scalar in the cxCoord data type. That is,
dims
is [2,
nDim]. IRIS Explorer saves only the bounding box
coordinates for a uniform lattice. It can construct the complete lattice
coordinate set from these values.
For example, this is how
PrintLat
prints out the coordinate structure for the uniform lattice shown in
Figure
3-7. It shows the values of
nDim
(in this case 2),
dims,
coordType, and the bounding box coordinates. Comparing
this output with the variables of Figure 3-7, it can be seen that
xmin
= 0.0,
ymin
= 0.0,
xmax
=
dims[0]-1.0 and
ymax
=
dims[1]-1.0. In this example, the spacing between
nodes in the
x
and
y
directions are both equal to 1.0. This can be altered by changing the
coordinates of the bounding box (see
Changing the Aspect Ratio below).
Figure
3-8
shows an example of a 3-D uniform lattice.
A 2-D image is an example of a uniform lattice; all the pixels in the
image have the same size and aspect ratio. You can change the aspect ratio of
a lattice by manipulating the bounding box coordinates.
For example, the lattice in
Figure
3-7
has nine nodes in the
x
direction and five nodes in the
y
direction. The default mapping provides a 1:1 aspect ratio. Since the
bounding box for this lattice is [0.0, 8.0] by [0.0, 4.0], the lattice is
mapped into a 9 by 5 grid to be displayed. However, if the bounding box
coordinates were [-1.0, 1.0] by [-1.0, 1.0], the lattice would occupy a 2 by
2 space when mapped to the screen, with a pixel aspect ratio of 2:1. Uniform
lattices can have this non-uniform aspect.
A perimeter lattice has a list of coordinate values sufficient to specify
an irregularly spaced rectangular structure.
The data structure for a perimeter lattice is:
Here,
*perimCoord
is an array of length
sumCoord
containing an ordered list of all the coordinates for each dimension. You can
compute sumCoord
by calling the API subroutine
cxDimsSum. See the
IRIS Explorer Reference
Pages for details on the
API subroutines.
Figure
3-9
shows the data set for a 2-D perimeter lattice. The
x
and
y
perimeter vectors contain coordinate values that specify the layout of the
lattice. It contains eight nodes in the
x
dimension and six nodes in the
y
dimension.
Coordinates for perimeter lattices are stored in row-major format in the C
convention (see Figure
3-10).
Figure
3-11
shows an example of a 3-D perimeter lattice. The
dims
values are the same for each of the perimeter vectors, because there are the
same number of nodes in each dimension.
Curvilinear lattices are used to store datasets where the data values at a
node need to be associated explicitly with the Cartesian coordinates of the
node. Examples of these include a collection of atoms in 3D space, points on
the surface of a sphere and computational fluid dynamics data calculated in a
body-fitted coordinate system.
The data structure for the coordinates part of a curvilinear lattice is:
You can use cxDimsProd
to compute the total number of coordinate values as the product of the
number of nodes in the lattice (i.e. the
dims
vector) and
nCoordVar.
Coordinate values for curvilinear lattices are stored interlaced at the node
level in the Fortran convention, with the I dimension varying the fastest.
This is the same storage method used to store lattice data (see
Figure
3-6) and is the reverse of the method used for storing uniform and
perimeter coordinates.
The number of computational dimensions for the lattice is defined by the
variable
nDim (see
Figure
3-5). For uniform and perimeter lattices, this number is also equal to
the number of physical dimensions for the lattice, but for curvilinear
lattices, the number of physical dimensions is defined by the variable
nCoordVar, the number of coordinate variables for each
node. In principle, this can have any value, although since each node in an
nDim-lattice usually requires at least this number of
coordinates to locate it in physical space, useful lattices will have
nDim
<= nCoordVar. Some examples of curvilinear lattices with this
property are shown in
Figure
3-13.
This figure shows the wide variety of datasets that can be stored in a
curvilinear lattice; from collections of points (nDim
= 1) in 1, 2 or 3-D space (nCoordVar
= 1, 2 or 3) through areas (nDim
= 2) in 2 or 3-D space (nCoordVar
= 2 or 3) to volumes (nDim
= 3) in 3-D space (nCoordVar
= 3). In addition it should be noted that, because of its greater
generality, a curvilinear lattice can always store datasets that are stored
in a perimeter or uniform lattice (and a perimeter lattice can always store
datasets from a uniform lattice, for the same reason). However, this would
be an inefficient use of storage space, since much of the coordinate
information would be redundant under these circumstances, and it is always
best to use the simplest type of lattice to store a given set of data.
When you build a module, you specify the range of lattice types the module
can accept on its input port or produce on its output port. You can define in
general terms the lattice constraints that encompass a large range of values for
a given element, or you can be very specific. The range you choose will depend
on the kind of data you want the module to handle.
The Lattice Constraints window in Figure 3-14 shows the settings for a more narrowly
defined lattice, such as a colormap (see Lattice Examples below). The port will accept a 1-D
lattice with four data variables. The primitive data type must be a float, and
the lattice coordinate type must be uniform. The number of coordinate dimensions
is not limited.
See Defining Lattice Constraint Fields in
Chapter 2 for more information on using this window.
These examples show how to create some simple, commonly used lattices.
They include code for a colormap and a 2-D image.
A colormap is a 1-D lattice with four variables per node (RGBA). Nodes are
spaced uniformly. The data is usually in floating point format. The elements
are:
See Code Examples in Chapter 3 for an
example of a user function for a module that accepts a colormap.
An image is a 2-D lattice with one variable (greyscale), three variables
(RGB), or four variables (RGBA) per node. The data is usually in byte format
and the coordinate spacing between nodes is usually uniform. IRIS Explorer
image-processing modules accept images of any size. The elements are:
See
Code Examples in Chapter 3
for examples of user functions for modules that work with both 2-D and 3-D
lattices.
To prepare your data for input into an IRIS Explorer lattice data type,
follow these points:
The easiest way to import your data into an IRIS Explorer map as a lattice is
to make use of the `plain' ASCII format. Files written in this format can be
immediately read by the ReadLat module. The ReadLat help page contains details
of the plain ASCII lattice format. Alternatively, see the file
$EXPLORERHOME/data/lattice/README.PlainFormat. Example data files in
the plain format may be found in the same directory.
The
cxLattice
data type, though defined in the IRIS Explorer typing language, can be
considered as a C structure. Fortran users need to set pointers to the data
type structures when they use them. The type declaration resides in the
header file
$EXPLORERHOME/include/cx/cxLattice.h.
This is the
cxLattice
data type declaration:
The Fortran type enumerations reside in the file
$EXPLORERHOME/include/cx/cxLattice.inc.
The three coordinate mappings are specified as follows:
Note: All Fortran data type access routines use zero-based
indexing, as in the C language (except where otherwise stated).
You can use the API (Application Programming Interface) routines to
manipulate data types in IRIS Explorer. The lattice subroutines are listed
below and described in detail in the
IRIS Explorer Reference
Pages. They let you:
Some routines check the validity of the data on the inputs before the
module is fired.
Table
3-2
lists the subroutines and briefly describes the purpose of each one.
This section presents three examples of source code using the lattice data
structure. Each one is written in C and in Fortran. The source code files and
modules for all the examples reside in $EXPLORERHOME/src/MWGcode.
This example shows how to create a a simple colormap module. It inverts
the colors of the input colormap. You may test it by connecting these
modules:
GenerateColorMap
to this module and
PrintLat; this module to another copy of
PrintLat. Compare the output from the two
PrintLat
modules. The code resides in
$EXPLORERHOME/src/MWGcode/Lattice/C/ColorMap.c
and in
$EXPLORERHOME/src/MWGcode/Lattice/Fortran/ColorMap.f.
This example shows how to work with a 2-D image, and negates all elements
of the data in the input image. Test it by connecting
ReadImg
to this module and
DisplayImg; this module to
DisplayImg
(DisplayImg
accepts more than one image, and you can display them in the same window; see
the
DisplayImg(1EXP)
man page for more details). Read in the image file
$EXPLORERHOME/data/image/flowers2.rgb
and compare the two images. The code resides in
$EXPLORERHOME/src/MWGcode/Lattice/C/Image2D.c
and in
$EXPLORERHOME/src/MWGcode/Lattice/Fortran/Image2D.f.
This example illustrates how to create a curvilinear lattice and rotate
the coordinates. Test it by connecting
GenLat
to this module and
PrintLat; this module to another copy of
PrintLat. Compare the output from both PrintLat modules. The code
resides in
$EXPLORERHOME/src/MWGcode/Lattice/C/Curvi3D.c
and in
$EXPLORERHOME/src/MWGcode/Lattice/Fortran/Curvi3D.f.
Figure 3-1 Data Flow Between Input and Output Lattices
The Lattice Data Type
shared root typedef struct {
long *nDim "Num Dimensions";
long* *dims[nDim] "Dimensions Array";
cxData(nDim,dims) *data "Data Structure";
cxCoord cDim, dims) *coord "Coord Structure";
} cxLattice;
Figure 3-2 Schematic Structure of the Lattice Data Type
The Dimension Variables
The
cxData
Structure
shared typedef struct { /* IRIS Explorer Lattice's Data array */
long nDim;
long dims[nDim];
long nDataVar "Num Data Variables";
cxPrimType primType "Primitive Data Type";
switch (primType) {
case cx_prim_byte:
char values[nDataVar, dims] "Data Array";
case cx_prim_short:
short values[nDataVar, dims] "Data Array";
case cx_prim_long:
long values[nDataVar, dims] "Data Array";
case cx_prim_float:
float values[nDataVar, dims] "Data Array";
case cx_prim_double:
double values[nDataVar, dims] "Data Array";
} d;
} cxData(nDim, dims);
typedef enum {
cx_prim_byte,
cx_prim_short,
cx_prim_long,
cx_prim_float,
cx_prim_double
} cxPrimType;
The
cxCoord
Structure
shared typedef struct { /* IRIS Explorer Lattice's Coordinate array */
long nDim;
long dims[nDim];
cxCoordType coordType "Coord Type";
switch (coordType) {
case cx_coord_uniform:
float bBox[2, nDim] "Coordinates Array";
case cx_coord_perimeter:
long sumCoord "Perim Coord Array Length";
float perimCoord[sumCoord] "Coordinates Array";
case cx_coord_curvilinear:
long nCoordVar "Num Coord Dimensions";
float values[nCoordVar, dims] "Coordinates Array";
} c;
} cxCoord(nDim, dims);
How Variables Interact
Figure 3-3 Lattice Variables
Manipulating Lattices
Figure 3-4 Storing Arrays in C and Fortran
Storing Data Values
Figure 3-5 Array Neighbors
Figure 3-6 Storing Data Values
R(node 1)
G(node 1)
B(node 1)
R(node 2)
G(node 2)
B(node 2)
R(node 3)
G(node 3)
B(node 3)...
Array[k][j][i] in C
Array(i,j,k) in Fortran
Defining Primitive Values
C Data Types
Fortran Equivalents
byte (signed char)
character*1
short
integer*2
long
integer (integer*4)
float
real (real*4)
double
double precision (real*8)
Storing Coordinate Values
Uniform Lattices
Figure 3-7 A 2-D Uniform Lattice Structure
struct {
float *bBox; /* An array of length [2, ndim]*/
} cx_coord_uniform;
coord
nDim 2
dims 9 5 /* Number of nodes in the x and y dimensions /*
coordType cx_coord_uniform
bBox
0.000000e+00 8.0000000e+00 /* The values of xmin and xmax /*
0.000000e+00 4.0000000e+00 /* The values of ymin and ymax /*
Figure 3-8 A 3-D Uniform Lattice Structure
Changing the Aspect Ratio
Perimeter Lattices
struct {
long sumCoord; /* Total number of nodes in all dims */
float *perimCoord; /* Ordered list of all coordinates */
} cx_coord_perimeter;
Figure 3-9 Data Set for a 2-D Perimeter Lattice
Figure 3-10 Storing Perimeter Coordinates
Figure 3-11 Example of a 3-D Perimeter Lattice
Curvilinear Lattices
struct {
long nCoordVar; /* Number of physical dimensions */
float *values; /* Array containing node coordinates */
} cx_coord_curvilinear;
Figure 3-12 Storing Curvilinear Coordinates
Figure 3-13 Curvilinear Lattices with Various Values for nDim
and nCoordVar
Limiting Lattice Values
Figure 3-14 Defining Lattice Constraints
Lattice Examples
A Colormap Example
A 2-D Image Example
Preparing Your Data for Lattices
The Data Type Declaration
#include <cx/Typedefs.h>
typedef enum {
cx_coord_uniform,
cx_coord_perimeter,
cx_coord_curvilinear
} cxCoordType;
typedef struct cxCoord {
long nDim;
long *dims;
cxCoordType coordType;
union {
struct {
float *bBox;
} cx_coord_uniform;
struct {
long sumCoord;
float *perimCoord;
} cx_coord_perimeter;
struct {
long nCoordVar;
float *values;
} cx_coord_curvilinear;
} c;
} cxCoord;
typedef struct cxData {
long nDim;
long *dims;
long nDataVar;
cxPrimType primType;
union {
struct {
unsigned char *values;
} cx_prim_byte;
struct {
short *values;
} cx_prim_short;
struct {
long *values;
} cx_prim_long;
struct {
float *values;
} cx_prim_float;
struct {
double *values;
} cx_prim_double;
} d;
} cxData;
typedef struct cxLattice {
long nDim;
long *dims;
cxData *data;
cxCoord *coord;
} cxLattice;
integer cx_coord_uniform
integer cx_coord_perimeter
integer cx_coord_curvilinear
parameter (cx_coord_uniform = 0 )
parameter (cx_coord_perimeter = 1 )
parameter (cx_coord_curvilinear = 2 )
The Lattice API Routines
Subroutine
Purpose
cxLatNew
Creates a lattice with data and coordinates
cxLatDataNew
Creates a lattice with data and no coordinates
cxLatCoordNew
Creates a lattice with coordinates and no data
cxLatRootNew
Creates a lattice with no data and no coordinates
cxDataNew
Creates new data structure
cxCoordNew
Creates new coordinate data structure
cxCoordDefaultNew
Creates default index coordinates
cxDataPrimSize
Returns the size of the primitive data type
cxDataPrimType
Returns the primitive data type
cxCoordType
Returns the lattice coordinate type
cxDimsProd
Returns the total number of data points in a lattice
cxDimsSum
Computes the sum of a dimensions vector (for perimeter lattices
only)
cxLatPtrSet
Sets lattice data and coordinate pointers
cxLatPtrGet
Gets pointers to lattice data and coordinates
cxLatDup
Duplicates a lattice with data or coordinates
cxLatRootDup
Duplicates a lattice without data or coordinates
cxDataDup
Duplicates data values
cxCoordDup
Duplicates coordinates
cxLatDescGet
Gets descriptive information about a lattice
cxDataValsGet
Returns pointer to data values
cxDataValsSet
Sets pointer to data values
cxCoordValsGet
Returns pointer to coordinate value
cxCoordValsSet
Sets pointer to coordinate values
cxCoordNVarGet
Gets number of coordinate variables
cxCoordNVarSet
Sets number of coordinate values
Code Examples
1-D Lattice
C Version:
#include <stdio.h>
#include <cx/DataAccess.h>
#include <cx/cxLattice.h>
#include <cx/cxLattice.api.h>
/*
This user function takes a colormap input (1D lattice with 4 floats
per sample) and inverts the red, green, and blue components of each
lookup value.
*/
void cchange(
cxLattice *cin, /* input colormap lattice */
cxLattice **cout) /* output colormap lattice */
{
int i; /* loop variable */
int n; /* number of colormap entries */
float *a,*b; /* pointers to colormap data */
cxErrorCode err;
/* create the new lattice */
*cout = cxLatDataNew(
1, /* number of dimensions */
cxLatticeDimensionsArrayGet(cin,&err),
4, /* number of data values */
cx_prim_float); /* data type */
/* use the same coordinate space as the input lattice */
cxLatPtrSet(*cout,NULL,NULL,
cxLatticeCoordStructureGet(cin,&err),NULL);
/* get the number of samples */
n = (int)*cxLatticeDimensionsArrayGet(cin,&err);
/* get the data pointers */
cxLatPtrGet(cin,NULL,(void **)&a,NULL,NULL);
cxLatPtrGet(*cout,NULL,(void **)&b,NULL,NULL);
/* invert the colors of the colormap entries */
for ( i = 0; i < n; i++ )
{
b[0] = 1.0 - a[0]; /* red */
b[1] = 1.0 - a[1]; /* green */
b[2] = 1.0 - a[2]; /* blue */
b[3] = a[3]; /* alpha */
a += 4; b += 4;
}
}
Fortran Version:
C This user function takes a colormap input
C (1D lattice with 4 real values per sample)
C The red, green, and blue of each lookup value are inverted
C
SUBROUTINE CHANGE(CIN,COUT)
C
INCLUDE '/usr/explorer/include/cx/Typedefs.inc'
INCLUDE '/usr/explorer/include/cx/DataAccess.inc'
C .. Scalar Arguments ..
#if defined(IS_64BIT)
INTEGER*8 CIN, COUT, P0, COORD
INTEGER*8 N(1)
#else
INTEGER CIN, COUT, P0, COORD
INTEGER N(1)
#endif
C .. Local Scalars ..
INTEGER I, IER, NN
C .. Local Arrays ..
REAL A(1), B(1)
C .. External Functions ..
EXTERNAL CXLATDATANEW, CXLATDESCGET, CXLATPTRGET,
* CXLATPTRSET
C .. Pointers to Lattice Structures ..
POINTER (PA,A)
POINTER (PB,B)
POINTER (PN,N)
C .. Executable Statements ..
C
C Get the number of samples
C
P0 = 0
IER = CXLATDESCGET(CIN,P0,PN,P0,P0,P0,P0,P0,P0)
NN = N(1)
C
C Create the new lattice
C
COUT = CXLATDATANEW(1,N,4,CX_PRIM_FLOAT)
C
C Use the same coordinate space as the input lattice
C
P0 = 0
IER = CXLATPTRGET(CIN,P0,P0,COORD,P0)
P0 = 0
#ifdef WIN32
IER = CXLATPTRSET(COUT,P0,P0,COORD,P0)
#else
IER = CXLATPTRSET(COUT,P0,%VAL(0),COORD,%VAL(0))
#endif
C
C Get the data pointers
C Note that we could have had the data pointers passed into
C the user function as arguments, which may be easier
C
P0 = 0
IER = CXLATPTRGET(CIN,P0,PA,P0,P0)
P0 = 0
IER = CXLATPTRGET(COUT,P0,PB,P0,P0)
C
C Invert the red, green, and blue lookup values
C
DO 20 I = 1, NN
B(4*I-3) = 1.0 - A(4*I-3)
B(4*I-2) = 1.0 - A(4*I-2)
B(4*I-1) = 1.0 - A(4*I-1)
B(4*I) = A(4*I)
20 CONTINUE
C
RETURN
END
2-D Lattice
C Version:
#include <stdio.h>
#include <cx/DataAccess.h>
#include <cx/cxLattice.h>
#include <cx/cxLattice.api.h>
/*
This user function takes an input 2D image and negates all the
elements of the data array. It works for any primitive data type.
*/
void cimage(cxLattice *in,cxLattice **out)
{
int i,j,k; /* loop variables */
void *a,*b; /* data pointers */
cxErrorCode err;
/* create the new lattice */
*out = cxLatDataNew(
2, /* number of dimensions */
in->dims, /* dimensions array */
in->data->nDataVar, /* number of data variables */
in->data->primType); /* data type */
/* use the same coordinate space as the input lattice */
cxLatPtrSet(*out,NULL,NULL,cxLatticeCoordStructureGet(in,&err),NULL);
/* extract the data pointers */
cxLatPtrGet(in,NULL,&a,NULL,NULL);
cxLatPtrGet(*out,NULL,&b,NULL,NULL);
/* loop over the data elements */
for ( i = 0; i < in->dims[1]; i++ )
for ( j = 0; j < in->dims[0]; j++ )
for ( k = 0; k < in->data->nDataVar; k++ )
{
/* switch on the data type */
/*
This should be outside the loops for
efficiency. It is shown inside here
for greater clarity.
*/
switch ( in->data->primType )
{
#define CASE(CXTYPE,TYPE) \
case CXTYPE: \
/* This is where the actual computation takes place */\
*(TYPE *)b = -*(TYPE *)a; \
a = (TYPE *)a + 1; b = (TYPE *)b + 1; \
break;
CASE(cx_prim_byte,unsigned char)
CASE(cx_prim_short,short)
CASE(cx_prim_long,long)
CASE(cx_prim_float,float)
CASE(cx_prim_double,double)
default:
break;
#undef CASE
}
}
}
Fortran Version:
C This user function takes an image input
C (2D lattice of any data type)
C and takes the negative of every data element.
C
SUBROUTINE IMAGE(IN,OUT)
C
INCLUDE '/usr/explorer/include/cx/Typedefs.inc'
INCLUDE '/usr/explorer/include/cx/DataAccess.inc'
C
C .. Scalar Arguments ..
#if defined(IS_64BIT)
INTEGER*8 IN, OUT, P0, NDVAR,COORD
INTEGER*8 DIMS(2)
#else
INTEGER IN, OUT, P0, NDVAR,COORD
INTEGER DIMS(2)
#endif
C .. Local Scalars ..
INTEGER I, IER, J, K, M, N, P, PTYPE
C .. Local Arrays ..
CHARACTER B0(1), B1(1)
DOUBLE PRECISION D0(1), D1(1)
REAL F0(1), F1(1)
#if defined(__alpha)
INTEGER*8 L0(1), L1(1)
#else
INTEGER L0(1), L1(1)
#endif
INTEGER *2 S0(1), S1(1)
C .. External Functions ..
EXTERNAL CXLATDATANEW, CXLATDESCGET, CXLATPTRGET,
* CXLATPTRSET
C .. Pointers to Lattice Structures ..
#ifdef WIN32
POINTER (PDIMS,DIMS)
POINTER (PB0,B0)
POINTER (PB1,B1)
POINTER (PS0,S0)
POINTER (PS1,S1)
POINTER (PL0,L0)
POINTER (PL1,L1)
POINTER (PF0,F0)
POINTER (PF1,F1)
POINTER (PD0,D0)
POINTER (PD1,D1)
#else
POINTER (PDIMS,DIMS)
POINTER (PB0,B0),(PB1,B1)
POINTER (PS0,S0),(PS1,S1)
POINTER (PL0,L0),(PL1,L1)
POINTER (PF0,F0),(PF1,F1)
POINTER (PD0,D0),(PD1,D1)
#endif
C .. Executable Statements ..
C
C Extract information from the input lattice
C
P0 = 0
IER = CXLATDESCGET(IN,P0,PDIMS,P0,NDVAR,PTYPE,P0,P0,P0)
C
C Compiler bug requires this hack
C
N = DIMS(2)
M = DIMS(1)
C
C Create the new lattice
C
OUT = CXLATDATANEW(2,DIMS,NDVAR,PTYPE)
C
C Use the same coordinate space as the input lattice
C
P0 = 0
IER = CXLATPTRGET(IN,P0,P0,COORD,P0)
P0 = 0
#ifdef WIN32
IER = CXLATPTRSET(OUT,P0,P0,COORD,P0)
#else
IER = CXLATPTRSET(OUT,P0,%VAL(0),COORD,%VAL(0))
#endif
C
C Extract data pointers based on primitive type
C
IF (PTYPE.EQ.CX_PRIM_BYTE) THEN
P0 = 0
IER = CXLATPTRGET(IN,P0,PB0,P0,P0)
P0 = 0
IER = CXLATPTRGET(OUT,P0,PB1,P0,P0)
ELSE IF (PTYPE.EQ.CX_PRIM_SHORT) THEN
P0 = 0
IER = CXLATPTRGET(IN,P0,PS0,P0,P0)
P0 = 0
IER = CXLATPTRGET(OUT,P0,PS1,P0,P0)
ELSE IF (PTYPE.EQ.CX_PRIM_LONG) THEN
P0 = 0
IER = CXLATPTRGET(IN,P0,PL0,P0,P0)
P0 = 0
IER = CXLATPTRGET(OUT,P0,PL1,P0,P0)
ELSE IF (PTYPE.EQ.CX_PRIM_FLOAT) THEN
P0 = 0
IER = CXLATPTRGET(IN,P0,PF0,P0,P0)
P0 = 0
IER = CXLATPTRGET(OUT,P0,PF1,P0,P0)
ELSE IF (PTYPE.EQ.CX_PRIM_DOUBLE) THEN
P0 = 0
IER = CXLATPTRGET(IN,P0,PD0,P0,P0)
P0 = 0
IER = CXLATPTRGET(OUT,P0,PD1,P0,P0)
END IF
C
C Loop over all the data items
C
P = 1
DO 60 I = 1, N
DO 40 J = 1, M
DO 20 K = 1, NDVAR
C
C Do the computation. The data type switching should be
C outside the loop for efficiency. It is shown inside
C here for greater clarity.
C
IF (PTYPE.EQ.CX_PRIM_BYTE) THEN
B1(P) = CHAR(-ICHAR(B0(P)))
ELSE IF (PTYPE.EQ.CX_PRIM_SHORT) THEN
S1(P) = -S0(P)
ELSE IF (PTYPE.EQ.CX_PRIM_LONG) THEN
L1(P) = -L0(P)
ELSE IF (PTYPE.EQ.CX_PRIM_FLOAT) THEN
F1(P) = -F0(P)
ELSE IF (PTYPE.EQ.CX_PRIM_DOUBLE) THEN
D1(P) = -D0(P)
END IF
C
C Increment the data item
C
P = P + 1
20 CONTINUE
40 CONTINUE
60 CONTINUE
C
RETURN
END
A 3-D Curvilinear Lattice
C Version:
#include <stdio.h>
#include <math.h>
#include <cx/DataAccess.h>
#include <cx/DataExtract.h>
#include <cx/cxLattice.h>
#include <cx/cxLattice.api.h>
void cwind(float rot,cxLattice *in,cxLattice **out)
{
int i,j,k; /* loop variables */
int index[3]; /* index vector for coordinate lookup */
float *c; /* pointer to output lattice coordinates */
float coord[3]; /* input coordinate vector */
float cosa,sina; /* utility variables */
/* create the new lattice */
*out = cxLatCoordNew(
3, /* number of dimensions */
in->dims, /* dimensions array */
3, /* coordinate dimensions */
cx_coord_curvilinear); /* type of coordinates */
/* use the same data from the input lattice */
cxLatPtrSet(*out,in->data,NULL,NULL,NULL);
/* get the coordinate data pointer */
cxLatPtrGet(*out,NULL,NULL,NULL,(void **)&c);
/* loop over the elements */
for ( i = 0; i < in->dims[2]; i++ )
{
index[2] = i; /* set z index */
for ( j = 0; j < in->dims[1]; j++ )
{
index[1] = j; /* set y index */
for ( k = 0; k < in->dims[0]; k++ )
{
index[0] = k; /* set x index */
/* get the original coordinates */
cxLatCoordExtract(in,index,coord);
/* wind the coordinates around the z-axis */
cosa = cos(rot*coord[2]);
sina = sin(rot*coord[2]);
c[0] = coord[0]*cosa + coord[1]*sina;
c[1] = coord[0]*sina - coord[1]*cosa;
c[2] = coord[2];
/* increment pointer */
c += 3;
}
}
}
}
Fortran Version:
SUBROUTINE FWIND(ROT,IN,OUT)
C
INCLUDE '/usr/explorer/include/cx/cxLattice.inc'
INCLUDE '/usr/explorer/include/cx/DataAccess.inc'
INCLUDE '/usr/explorer/include/cx/Typedefs.inc'
C
C .. Scalar Arguments ..
REAL ROT
#if defined(IS_64BIT)
INTEGER*8 IN, OUT, P0
INTEGER*8 DIMS(3)
#else
INTEGER IN, OUT, P0
INTEGER DIMS(3)
#endif
C .. Local Scalars ..
REAL COSA, SINA
INTEGER D, I, IER, J, K, M, NX, NY, NZ
INTEGER INDEX(3)
C .. Local Arrays ..
REAL C(1), COORD(3)
C .. External Subroutines ..
EXTERNAL CXLATCOORDEXTRACT
C .. External Functions ..
EXTERNAL CXLATCOORDNEW, CXLATDESCGET, CXLATPTRGET,
* CXLATPTRSET
C .. Intrinsic Functions ..
INTRINSIC COS, SIN
C .. Pointers to Lattice Structures ..
POINTER (PDIMS,DIMS)
POINTER (PC,C)
C .. Executable Statements ..
C
C Get the dimensions vector
C
P0 = 0
IER = CXLATDESCGET(IN,P0,PDIMS,P0,P0,P0,P0,P0,P0)
NX = DIMS(1)
NY = DIMS(2)
NZ = DIMS(3)
C
C Create the new lattice
C
OUT = CXLATCOORDNEW(3,DIMS,3,CX_COORD_CURVILINEAR)
C
C Use the same data as the input lattice
C
P0 = 0
IER = CXLATPTRGET(IN,D,P0,P0,P0)
P0 = 0
#ifdef WIN32
IER = CXLATPTRSET(OUT,D,P0,P0,P0)
#else
IER = CXLATPTRSET(OUT,D,%VAL(0),P0,%VAL(0))
#endif
C
C Get the output data pointer
C
P0 = 0
IER = CXLATPTRGET(OUT,P0,P0,P0,PC)
C
C Loop over the coordinates
C
M = 1
C
C Set z index (0 based for api routine)
C
DO 60 I = 1, NZ
INDEX(3) = I - 1
C
C set y index
C
DO 40 J = 1, NY
INDEX(2) = J - 1
C
C Set x index
C
DO 20 K = 1, NX
INDEX(1) = K - 1
C
C Get the original coordinates
C
CALL CXLATCOORDEXTRACT(IN,INDEX,COORD)
C
C Wind the coordinates around the z-axis
C
COSA = COS(ROT*COORD(3))
SINA = SIN(ROT*COORD(3))
C
C(M) = COORD(1)*COSA + COORD(2)*SINA
C(M+1) = COORD(1)*SINA - COORD(2)*COSA
C(M+2) = COORD(3)
C
C Increment index
C
M = M + 3
20 CONTINUE
40 CONTINUE
60 CONTINUE
C
RETURN
END
Last modified: Mar 03 09:22 1999
[ Documentation Home ]