Algebraic Functions

Format

A [ ; ] expression

The A code converts A codes into F codes in order to perform mathematical operations on the field values of a record, or to manipulate strings. The A code functions in the same way as the F code but is easier to write and to understand.

expression can be one or more of the following:

A data location or string

loc[R]
Field number specifying a data value, followed by an optional R (repeat code).
N(name)
name is a dictionary entry for a field. The name is referenced in the file dictionary. An error message is returned if the field name is not found. Any codes specified in field 3 of name are applied to the field defined by name, and the converted value is processed by the A code.
string
Literal string enclosed in pairs of double quotation marks ( " ), single quotation marks ( ' ), or backslashes ( \ ).
number
Constant number enclosed in pairs of double quotation marks ( " ), single quotation marks ( ' ), or backslashes ( \ ). Any integer, positive, negative, or zero can be specified.
D
System date (in internal format).
T
System time (in internal format).

A special system counter operand

@NI
Current® system counter (number of items listed or selected).
@ND
Number of detail lines since the last BREAK on a break line.
@NV
Current value counter for columnar listing only.
@NS
Current subvalue counter for columnar listing only.
@NB
Current BREAK level number. 1 = lowest level break. This has a value of 255 on the grand-total line.
@LPV
Load Previous Value: load the result of the last correlative or conversion onto the stack.

A function

Table 1. A function
R(exp) Remainder after integer division of the first operand by the second. For example, R(2,"5") returns the remainder when field 2's value is divided by 5.
S(exp) Sum all multi-values in exp. For example, S(6) sums the multi-values of field 6.
IN(exp) Test for the null value.
[ ] Extract substring. Field numbers, literal numbers, or expressions can be used as arguments within the brackets. For example, if the value of field 3 is 9, then 7["2",3] returns the second through ninth characters of field 7. The brackets are part of the syntax and must be typed.

IF(expression) | THEN(expression) | ELSE(expression)

(conv) Conversion expression in parentheses (except A and F conversions).

An arithmetic operator

*
Multiply operands.
/
Divide operands. Division always returns an integer result: for example, "3" / "2" evaluates to 1, not to 1.5.
+
Add operands.
-
Subtract operands.
:
Concatenate operands.

A relational operator

=
Equal to
<
Less than
>
Greater than
# or <>
Not equal to
<=
Less than or equal to
>=
Greater than or equal to

A conditional operator

AND
Logical AND
OR
Logical OR

In most cases F and A codes do not act on a data string passed to them. The code specification itself contains all the necessary data (or at least the names of fields that contain the necessary data). So the following A codes produce identical F codes, which in turn assign identical results to X:

X = OCONV( "123", "A;'1' + '2'" )
X = OCONV( "", "A;'1' + '2'" )
X = OCONV( @ID, "A;'1' + '2'" )
X = OCONV( "The quick brown fox jumped over a lazy 
dog's
   back","A;'1' + '2'" )

The data strings passed to the A code-123, the empty string, the record ID, and "The quick brown fox..." string-simply do not come into play. The only possible exception occurs when the user includes the LPV (load previous value) special operand in the A or F code. The following example adds the value 5 and the previous value 123 to return the sum 128:

X = OCONV( "123", "A;'5' + LPV" )

It is almost never right to call an A or F code using the vector conversion functions OCONVS and ICONVS. In the following example, Y = 123V456V789:

X = OCONVS( Y, "A;'5' + '2' )

The statement says, "For each value of Y, call the A code to add 5 and 2." (V represents a value mark.) The A code gets called three times, and each time it returns the value 7. X, predictably, gets assigned 7. The scalar OCONV function returns the same result in much less time.

What about correlatives and conversions within an A or F code? Since any string in the A or F code can be multi-valued, the F code calls the vector functions OCONVS or ICONVS any time it encounters a secondary correlative or conversion. In the following example, the F code-itself called only once-calls OCONVS to ensure that the G code gets performed on each value of @RECORD< 1 >. X is assigned the result cccVfff:

@RECORD< 1 > = aaa*bbb*cccVddd*eee*fff
X = OCONV( "", "A;1(G2*1)"

The value mark is reserved to separate individual code specifications where multiple successive conversions must be performed.

The following dictionary entry specifies that the substring between the first and second asterisks of the record ID should be extracted, then the first four characters of that substring should be extracted, then the masked decimal conversion should be applied to that substring:

001: D
002: 0
003: G1*1VT1,4VMD2
004: Foo
005: 6R
006: S

To attempt to define a multi-valued string as part of the A or F code itself rather than as part of the @RECORD produces invalid code. For instance, both:

X = OCONV( "", "A;'aaa*bbb*cccVddd*eee*fff'(G2*1)" )

and the dictionary entry:

001: D
002: 0
003: A;'aaa*bbb*cccVddd*eee*fff'(G2*1)
004: Bar
005: 7L
006: S

are invalid. The first returns an empty string (the original value) and a status of 2. The second returns the record ID; if the STATUS function were accessible from dictionary entries, it would also be set to 2.