Type and Structure of Expressions
Every entity in PV-WAVE has an associated type and structure. The nine atomic data types, in decreasing order of complexity are:
DCOMPLEX—Complex double-precision floating point
COMPLEX—Complex single-precision floating point
DOUBLE—Double-precision floating point
FLOAT—Floating point
LONG—32 or 64-bit integer on 32 and 64-bit systems, respectively
INT32—32-bit integer
INT—16-bit integer
BYTE—8-bit integer
STRING—String
The structure of expressions may be scalars or arrays. The type and structure of an expression depend upon the type and structure of its operands.
note | Unlike many other languages, the type and structure of expressions in PV-WAVE cannot be determined until the expression is evaluated. Because of this, care must be taken when writing programs. For example, a variable may be a scalar byte variable at one point in a program, while at a later point it may be set to a complex array. |
PV-WAVE attempts to evaluate expressions containing operands of different types in the most accurate manner possible. The result of an operation becomes the same type as the operand with the greatest precedence or potential precision. For example, when adding a byte variable to a floating point variable, the byte variable is first converted to floating point and then added to the floating point variable, yielding a floating point result. When adding a double-precision variable to a complex variable, the result is complex because the complex type has a higher position in the hierarchy of data types.
note | When you define a constant as a double data type using “D”, PV-WAVE creates a variable that contains the double precision machine representation for the constant. The expression DOUBLE(3.1) causes PV-WAVE to create a single precision variable (the single precision machine representation of 3.1), and then casts the single precision value into a double precision variable. Limitations in the floating-point format's ability to represent some numbers can cause these two cases to produce slightly different values. |
When writing expressions with mixed types, caution must be used to obtain the desired result. For example, assume the variable A is an integer variable with a value of 5. The following expressions yield the indicated results:
; Evaluates to 2. Integer division is performed. The remainder is
; discarded.
A / 2
; Evaluates to 2.5. The value of A is first converted to floating
; point.
A / 2.
; Evaluates to 3. Integer division is done first because of
; operator precedence. Result is floating point.
A / 2 + 1.
; Evaluates to 3.5. Division is done in floating point and then
; the 1 is converted to Floating point and added.
A / 2. + 1
note | When other types are converted to complex type, the real part of the result is obtained from the original value and the imaginary part is set to zero. |
When a string type appears as an operand with a numeric data type, the string is converted to the type of the numeric term. For example:
'123' + 123.0
is 246.0,
'123.333' + 33
results in a conversion error because 123.333 is not a valid integer constant. In the same manner, 'ABC' + 123 also causes a conversion error.
Type Conversion Functions
PV-WAVE provides a set of functions that convert an operand to a specific type. These functions are useful in many instances, such as forcing the evaluation of an expression to a certain type, outputting data in a mode compatible with other programs, etc. The conversion functions are shown in
Table 3-2: Type Conversion Functions.
For example, the result of the expression FIX(A) is of 16-bit integer type with the same structure (scalar or array) as the variable. The variable may be of any type. These conversion functions operate on data of any structure: scalars, vectors, or arrays. If A lies outside the range of 16-bit integers (–32,768 to +32,767) the resulting values wrap at the minimum/maximum value for the data type, i.e., no promotion to a larger type takes place.
note | To maintain backwards compatiblity, the INT32 data type has lower precedence than the LONG data type even on platforms where they are the same size. For example, the expression A = [33445566i, 33445566] produces an array of type LONG as the second value overrides the explicit selection of the INT32 type for the first value. |
caution | The statement: PRINT, FIX(66000) prints the value 464, which is 66000 – 2 16, with no indication that an error occurred. The FINITE and CHECK_MATH functions test floating point results for valid numbers, and check the accumulated math error status respectively. For details on these error-checking functions, see Chapter 11: Programming with PV-WAVE. |
The statement:
A = FLOAT(A)
is perfectly legitimate; its effect is to force the variable A to have Floating point type.
Special cases of type conversions occur when converting between strings and byte arrays. The result of the BYTE function applied to a string or string array is a byte array containing the ASCII codes of the characters of the string. Converting a byte array with the STRING function yields a string array or scalar with one less dimension than the byte array.
Table 3-3: Examples of Conversion Functions shows examples of conversion on functions.
Extracting Fields
When called with more than a single parameter, the BYTE, COMPLEX,
DCOMPLEX, FIX, INT32, LONG, FLOAT and DOUBLE functions create an expression of the designated type by extracting fields from the input parameter without performing type conversion. The result is that the original binary information is simply interpreted as being of the new type. This feature is handy for extracting fields of data of one type embedded in arrays or scalars of another type.
The general form of the type conversion functions is:
CONV_FUNCTION(expression, offset [, dim1, ..., dimn])
Where:
CONV_FUNCTION is the name of one of the conversion functions listed previously.
expression—An array or scalar expression of any type from which the field is to be extracted.
offset—Starting byte offset within
expression of the field to be extracted. Zero is the first byte.
dim1, ..., dimn—Dimensions of the result. If these dimensions are omitted, the result is a scalar. If more than two parameters appear, the third and following parameters are the dimensions of the resulting array.
For example, assume file unit 1 is open for reading on a file containing 112-byte binary records containing the fields shown in
Table 3-4: Example Fields in Open File:
The following program segment will read a record into an array and extract the fields.
; Define array variable to contain record, 112 bytes.
A = BYTARR(112)
; Read the next record.
READU, 1, A
; Extract TIME. Offset = 0, double-precision.
TIME = DOUBLE(A, 0)
; Extract TYPE. Starting offset is 8.
TYPE = BYTE(A, 8)
; Count, offset = 9, integer.
COUNT = FIX(A, 9)
; DATA = floating array, dimensions of 20-columns by 5-rows,
; starting offset is 11 bytes.
DATA = FLOAT(A, 11, 20, 5)
; Last field, single byte.
QUALITY = BYTE(A, 111)