Mapping String Calculation Operands
Topics
Specifying a calculation operand
Introduction to the calculator
Specifying numeric literals
Specifying large numeric literals
Expression Operators
Operation and use of calculations in mapping strings
Calculator commandline test program
Specifying a calculation operand
For the sequence items SD and SX, and the numeric conversion items DD, DX, XD and XX, you are allowed to perform arithmetic operations on the value before it is formatted as a numeric value. This is done by specifying a calculation operand, which is a string operand containing an arithmetic expression string. The expression string is processed by a calculation function, which evaluates the expression and produces a numeric result, which in turn is formatted by the SD, SX, DD, DX, XD and XX mapping items.
You can invoke an SPFLite primary command from an SPFLite macro, using the builtin macro function SPF_Cmd(). When you do this, and your SPFLite command is a CHANGE command with a mapping string (a string2 operand with an M string), the mapping string can contain one or more SD, SX, DD, DX, XD or XX mapping items, which in turn may have calculation operands.
You can also invoke the calculation function directly from an edit macro, using the builtin function SPF_Calc(). See the macro documentation for more information, by issuing the command HELP MACRO from the SPFLite primary command line.
You are likely to find the calculation function will allow you to perform any calculations you might need in connection with your use of mapping strings, and then some. The design of the calculation features was made with future enhancements and developments of SPFLite in mind.
Introduction to the calculator
The calculation function has the following features.
 The calculation function accepts a calculation operand as a string value, containing one or more arithmetic expressions. It processes this string and produces a numeric result. Only integer calculations are performed. The string is treated as caseinsensitive.
 The calculation operand may contain one or more expressions, separated by ; semicolons. The main reason to specify more than one expression is to perform assignments to more than one variable, as generally only one variable is assigned per expression. In this sense, “expressions” are somewhat like “statements” in a programming language, although as used in the calculation function, it is not quite so formal. The last or only expression may optionally omit the final ; semicolon. Extra semicolons are ignored.
 The calculation function operates with 64bit integer arithmetic, which has a capacity of 19 decimal digits or 16 hex digits. The highest decimal value is 9,223,372,036,854,775,807 and so there are actually 18 full decimal digits available. Note that no check is made for numeric overflow. For applications involving the editor, it is unlikely you would exceed this limit.
 When the calculation function is called, it is provided with an initial value. For the numeric conversion items DD, DX, XD and XX, the initial value is the number acquired by the mapping item, and for the sequence items SD and SX, the initial value is the sequence number. When you invoke the calculation function from an edit macro using the builtin function SPF_Calc(), the initial value is one of the supplied arguments.
 The calculation function provides 26 variables named A through Z, which you can use like variables in a conventional program. These variables are 64bit integer values, which can be read and modified. A variable is read by its appearance as a term in an expression, and is modified by being on the left side of an assignment or swap operator. The variable names are case insensitive.
 When the calculation function begins, the variables are preinitialized as follows:
 Variable X and variable R both contain the initial value.
 Variable S contains the contents of the sequence number.
 Variable L contains the line number where the CHANGE command found the source string.
 Variable C contains the beginning column number where the CHANGE command found the source string.
 For the SD and SX commands, variables X, R and S will all have the same value.
 The remaining 21 variables will be initialized to zero.
 You are free to modify any variables. Because the preinitialized variables noted above define initial conditions, you may wish to treat these variables as readonly and avoid modifying them, unless their preinitialized values are not needed.
 When you call the calculation function from the SPFLite builtin function SPF_Calc(), the preinitialization of variables is handled somewhat differently. See the Help entry for SPF_Calc() in HELP MACRO for more information.
 For variable S, the sequence number value associated with it is the ordinal number of the order in which a string was found during a CHANGE ALL command. During the course of a CHANGE ALL operation that contains a mapping string, which in turn contains a calculation operand, the first string so found has a sequence number of 1, the second has a sequence number of 2, etc. You can use this information to tailor the way you calculate the value returned from your expression. For instance, you may wish to develop a sequence number as a prefix or suffix of some name or string, or, you may wish to enumerate paragraphs or sections of a document that are not amenable to the use of the Enumeration keyboard functions (which require aligned columns of numbers). If you use the calculation function in a context for which there is no defined sequence number, variable S will contain zero.
 After you perform your calculations, the calculation function determines and returns a final value as follows:
 If you have assigned a new value to variable R, the last value assigned to variable R will be used as the returned value. Variable R takes on a role that a RETURN statement or a function result value provides in many programming languages.
 If you have not have assigned a new value to variable R, but you have assigned a new value to variable X, the last value assigned to variable X will be used as the returned value.
 If you do not assign a value to either variable R or variable X, but have specified one or more expressions, the value of the rightmost or only expression is assumed to be the returned value. Because of such assumed returned values, you can make the expression simple and brief by omitting any assignments, if these are not needed. For example, if you just want to add 5 to the initial value, this may be done with X+5. When 5 is added to the initial value, it leaves the result as the lastevaluated expression. Since the expression X+5 makes no assignments to R or X, it is assumed that its calculated value is what you want as the result. For purposes of determining a returned value, assignments to any variables other than R and X are ignored.
 If you have both assignments and references to variable R or variable X, only the assignments will be considered when determining the return value. For example, if the initial value is 10, the expression R=X*2; R+1 will return 20 rather than 21. That is because the last assignment to R set it to 20, and the fact that the last expression had a value of 21 is disregarded. If you wanted that final value to be returned, you would either have to make a second assignment like R=X*2; R+=1 or you could omit all assignments and have a simple expression like X*2+1.
Because the calculation function will often be used for very simple calculations, a further expression simplification is supported. When the leftmost part of the calculation operand is a binary operator, it is assumed that the expression is preceded by an implied X variable. When the calculation operand begins with + or – these are assumed to be binary operators (not unary), with an implied X on the left. For instance, a calculation operand of +5 will be assumed to mean X+5, and then this will be treated as described in the preceding paragraph
When you use this shortcut, you must ensure that the resulting expression, including the implied X variable, is syntactically correct.
The X variable is not implied when the calculation operand has a leading operator that is only used as unary. For example, a calculation operand of !4 would not imply X!4 because ! is the unary NOT operator. Thus, !4 would calculate the value of !4 without reference to variable X.
The only case where this could be an issue is if you needed a leading + or – unary operator, since the implied X rules would be used, and a calculation adding to or subtracting from X would be performed. An actual unary + operator is never algebraically required, and can be omitted. However, if you needed an expression like ‑4*S and did not want this to mean, X4*S, you would need to change your calculation operand. For the unary – operator, if you really need to begin your expression this way, you can do any of the following:
 Precede the initial unary – operator with a ; semicolon.
example: ;4*S
 Precede the initial unary – operator with a 0, which is numerically the same.
example: 04*S
 Enclose the term having the initial unary – operator in parentheses.
example: (4)*S or (4*S)
 Rewrite the expression so it does not begin with an initial unary – operator.
example: S*4 or 4*S
 Rewrite the expression so it explicitly assigns variable R or X.
example: R=4*S
 If you specify a blank or empty expression, it will be determined that there is no final value and that neither variable R nor variable X have been assigned, and then the returned value will be made the same as the initial value. You can use this fact to specify blanks as a “nooperation” expression, if you sometimes don’t want to alter the initial value. Other “nooperation” expressions that will return the initial value unchanged include R, X, R=X and expressions that only contain semicolons.
 The calculation function uses an expression syntax largely modeled on the C programming language. This was done to make these expressions as concise as possible. Some extensions to C syntax were made, to make it compatible with common usage in other languages, and to add additional operators to take the place of common arithmetic functions.
 A large number of arithmetic operators are available to calculate numeric values. These are unary (prefix) and binary (infix) operators. A number of binary operators can be used as arithmetic assignment operators. For example, to multiply variable A by 5, you can use A = A * 5, or as A *= 5 with the *= arithmetic assignment operator. Unlike the C language, there are no increment or decrement operators like ++ and . If you want to increment variable A, you must use A = A + 1 or A += 1 rather than A++ or ++A. As noted above, if you just want to increment or decrement the initial value to produce the result value, you can do this with a calculation operand of +1 or 1 respectively.
 When an operator like * can be used as an arithmetic assignment operator, it is said to be assignable. Any binary operator that is assignable may be used to modify a variable by putting a variable name on the left, then the operator, then an = equal sign. Thus, the assignable multiply operator * becomes *= with a variable name on its left, and an expression on its right, as in A *= 5. Because many operators are assignable, this is simply noted in the table, rather than listing them all separately. If you are familiar with C expressions, assignable operators like A += 1 should be clear. Otherwise, you can use the longer form A = A + 1 if you prefer.
 Calculation expressions follow typical rules for expression formation. Operator precedence, associativity and nested parentheses are handled as usual. An operator precedence table appears below. The table largely follows C expression rules.
 Numeric literals may be specified in decimal or hex. In either case, these values are converted to 64bit integer values. An extended notation is available for specifying large numeric values more concisely.
 Variable names and/or numeric literals may not be adjacent to each other, either with or without intervening blanks. Some kind of operator, parentheses or other punctuation must separate these items. You can use underscores to clarify large numbers, such as 123_456. You cannot begin a number with an underscore but these can be freely used elsewhere within the number. Blanks in expressions are ignored, except that multiplecharacter operators like <> and numeric literals must not have embedded blanks.
 There is no direct support for conditional calculations, such as the ? and : conditional operators in C. There is also no facility for defining tables or doing table lookups. Instead, the calculation function uses the concept of set expressions and set indexing to serve both of these purposes, using a simplified syntax.
Literals may be specified in decimal or hex. You can optionally use underscores for readability with large numbers, and these will be ignored.
 For decimal numbers, up to 19 digits may be used, and 18 full decimal digits are available. The largest positive value is 9,223,372,036,854,775,807, and the smallest negative number is –9,223,372,036,854,775,808. If you attempt to specify a number outside these limits, an overflow will occur, and the resulting value will be the smallest negative number.
 For hex numbers, up to 16 hex digits may be used. Hex numbers are introduced by a leading . dot. Hex digits > 9 are A to F and are case insensitive. For example, 255 and .FF are the same value, and so are 65_535 and .F_FFF .
Specifying large numeric literals
The calculation function provides a means to concisely specify large decimal and hex values that have repeating digits. It is somewhat similar to E notation commonly used for floating point numbers, but the same syntax provided will work in both decimal and hex integers (the E notation would not work in hex, since E is a hex digit) and is more flexible.
Large numbers may be required in applications involving calculations of checksums, hash keys or encryption values on your user data.
If your work does not involve large numbers, you can skip the rest of this section.
The large number syntax relies on three suffixes, comparable to floatingpoint E notation, namely a “Low Suffix”, a “High Suffix” and a “Repeated Suffix”. These are used the same as you might specify a floating point value of 5E4 to mean 50000.0. A number may have only one suffix, which appears at the end of the number without any intervening blanks. These suffixes operate as follows:
 A Low Suffix consists of the letter L followed by a decimal number. The Low Suffix indicates the number of 0 digits that are to be appended to the number. For example, to concisely specify the decimal number 700_000, you would use 7L5. To concisely specify the hex number .F00_000, you would use .FL5 .
 A High Suffix consists of the letter H followed by a decimal number. The High Suffix indicates, for decimal numbers, the number of 9 digits that are to be appended to the number, and for hex numbers, the number of F digits that are to be appended to the number. For example, to concisely specify the decimal number 799_999, you would use 7H5. To concisely specify the hex number .7FF_FFF, you would use .7H5
 A decimal number requires one leading digit before specifying a suffix. For instance, to concisely specify the decimal number 999_999_999, you would could use either 9H8 (an initial 9 digit, plus eight more 9’s) or 0H9 (an initial 0 digit which is numerically ignored, plus nine more 9’s)
 Because a hex number is already introduced by the leading dot, it is not necessary to have any leading digits before specifying the hex High Suffix. For instance, to concisely specify the hex number .FFFF_FFFF, you could use .H8 .
 A Repeat Suffix consists of a decimal or hex digit, then the letter R followed by a decimal number. The Repeat Suffix indicates the number of specified digits that are to be appended to the number, in cases where the digit in question being repeated is not necessarily 0, 9 (for decimal) or F (for hex) where the L or H suffix might have been used. Because of the need to specify a digit to be repeated, you number must use at least one leading digit before using this suffix. For example, to concisely specify the decimal number 733_333, you would use 73R5. To concisely specify the hex number .F33_333, you would use .F3R5 . Note that the count after the R reflects the total number of digits, including the digit that precedes the R. For this reason, a repetition number less than 3 will not reduce the size of the literal and would normally not be used.
The decimal number in a suffix is limited to 2 digits. Its value may not exceed 19 for a decimal number or 16 for a hex number; the minimum value is 1 in both cases. Additionally, the suffix cannot cause the final number of digits to exceed 19 for a decimal number or 16 for a hex number. If the decimal number in a suffix is outside these limits, a syntax error is detected and the calculation halts. For the mapping string, the returned value will be unchanged from the initial value. Readability underscores in numbers are ignored and do not affect the maximum number of digits allowed.
The following table describes the operators, their precedence and associativity. Operators with higher precedence are performed ones with lower precedence. Higherprecedence operators are listed with higher precedence numbers. Operators at level 15, if present, are performed first, while operators at level 1, if present, are performed last.
This precedence follows the traditional C language expression syntax and semantics. As is true of many beginning C programmers, some may find the extensive number of operators and precedence levels to be intimidating. However, experience has shown that this arrangement actually implements the most frequently desired choice of actions, in cases where specifying the fewest number of parentheses is desired. Of course, whenever in doubt, you are free to use parentheses as needed to clarify to the calculation function and to yourself what your intentions are.
Headings:
 Oper: Operator
 Prec: Precedence level
 Assoc: Associativity:
LTR = Left to Right
RTL = Right to Left
NON = NonAssociative. Some operators are nonassociative, because allowing two or more such operators in a row (without using parentheses) may be ambiguous or confusing.
Note: Even where operators may be LTR or RTL, expressions must still be written carefully and properly. For example, R = X < Y < Z is a “valid” expression, but it probably will not do what you want. First, X < Y is evaluated; if true, its value 1, else 0. Then, Z is compared to that result, so that you would be either be comparing 0 < Z or 1 < Z. If your intent was to determine if X, Y and Z were in numeric order, the right way to do that is with R = (X < Y) && (Y < Z).
 Asgn: Assignable. If an operator is assignable, you can make the operator an assignment operator by adding a trailing = equal sign.. For instance, the multiply operator * is assignable, so you can use a *= multiplyandassign operator. Only binary operators are capable of being assignable. Operators for which being assignable is not applicable will appear as “n/a” . When assignability is shown as No, it reflects an operation seldom needed or not easily incorporated by the syntax. If needed, the effect can usually be accomplished by a longer expression with an explicit assignment operator.
 When you use an assignment operator such as *= it no longer has its original precedence ( the * operator has an original precedence of 14) but rather the same precedence as the := assignment operator; namely, 2. All such assignment operators like *= associate Right to Left, even though * associates Left to Right. (Associating Right to Left is necessary for assignments, because the expression on the right has to be evaluated first, before it can be assigned to the variable on the left.)
Oper 
Prec 
Assoc 
Description 
Asgn 
+ 
15 
RTL 
Unary arithmetic positive, ignored except to clarify an expression. Not needed, but supported to conform to conventional usage. 
n/a 
 
15 
RTL 
Unary arithmetic negation 
n/a 
! 
15 
RTL 
Unary logical not If X = 0, !X = 1 If X not = 0, !X = 0 
n/a 
~ 
15 
RTL 
Unary bitwise negation (one’s complement) 
n/a 
@ 
15 
RTL 
Unary absolute value, like ABS function in Basic If X < 0, @X = –X If X >= 0, @X = X 
n/a 
$ 
15 
RTL 
Unary sign function, like SGN function in Basic If X < 0, $X = –1 If X = 0, $X = 0 If X > 0, $X = 1 
n/a 
$$ 
15 
RTL 
Unary sign index function, like 2+SGN function in Basic If X < 0, $X = 1 If X = 0, $X = 2 If X > 0, $X = 3 
n/a 
* 
14 
LTR 
Multiply 

/ 
14 
LTR 
Integer divide 

% \ 
14 14 
LTR LTR 
Modulus (remainder) % is the C language operator, \ is a common alternative notation. Both have same meaning and are interchangeable. Note that Integer Divide and Modulus (remainder) operators calculate in such a way that the quotient and remainder will have the same absolute values regardless of the signs of the dividend and divisor. This is done by doing a preliminary Divide or Modulus using the absolute values of the numeric terms, and then correcting the signs afterwards. Attempting a Divide or Modulus with a righthand term of zero is an error which will halt the calculation and the mapping string that contains it. 
Yes 
+ 
13 
LTR 
Add 
Yes 
 
13 
LTR 
Subtract 
Yes 
<< 
12 
LTR 
Bitwise (unsigned) shift left. Zero bits are filled on the right. If you shift with a negative shift amount, it will reverse the direction of the shift. An expression of X << 4 will shift left 4 bits, while an expression of X << –4 will operate the same as X >> 4. The determination of a negative shift amount is not just a matter of an explicit – minus sign operator, but is based on the evaluation of the expression. 
Yes 
>> 
12 
LTR 
Bitwise (unsigned) shift right. Zero bits are propagated on the left. If you shift with a negative shift amount, it will reverse the direction of the shift. An expression of X >> 4 will shift right 4 bits, while an expression of X >> –4 will operate the same as X << 4. The determination of a negative shift amount is not just a matter of an explicit – minus sign operator, but is based on the evaluation of the expression. 
Yes 
+> 
12 
LTR 
Numeric (signed) shift right. The sign bit is propagated on the left. If you shift with a negative shift amount, it will reverse the direction of the shift. An expression of X +> 4 will shift right 4 bits, while an expression of X +> –4 will operate the same as X << 4. The determination of a negative shift amount is not just a matter of an explicit – minus sign operator, but is based on the evaluation of the expression. The operator +> is equivalent to the >>> operator in Java. 
Yes 
# 
12 
LTR 
Numeric scale In the expression X # S, the value X is divided by S. Each division operation is counted, with the first one treated as division number 1. After division, a test is made to see if the result is 0; if so, the # operator halts; otherwise, the quotient is divided again and process repeats. The result of the # operator is the count of the number of divisions performed. If S < 2, X # S produces 0. When S is 10, X # S is the number of decimal digits required to represent X. For example, 123456 # 10 will produce 6. When X is zero and S >= 2, X # S will produce 1. 
Yes 
## 
12 
LTR 
Bitwise scale In the expression X ## S, the value X is unsignedshifted right by S, the same as done by X >> S. Each shift operation is counted, with the first one treated as shift number 1. After a shift, a test is made to see if the result is 0; if so, the ## operator halts; otherwise, the result is shifted again and process repeats. The result of the ## operator is the count of the number of shifts performed. If S < 1 or S > 63, X ## S produces 0. When S is 4, X ## S will report the number of hex digits required to represent X. For example, .FF123 ## 4 will produce 5. When S is 1, X ## S is the number of binary digits (bits) required to represent X. When X is zero, and 1<=S<=63 , X ## S will produce 1. 
Yes 
> 
11 
LTR 
Greater Than. If X is > Y, the value of X > Y is 1. If X is not > Y, the value of X > Y is 0. 
No 
< 
11 
LTR 
Less Than. If X is < Y, the value of X < Y is 1. If X is not < Y, the value of X < Y is 0. 
No 
>= 
11 
LTR 
Greater Than or Equal To. If X is >= Y, the value of X >= Y is 1. If X is not >= Y, the value of X >= Y is 0. 
No 
<= 
11 
LTR 
Less Than or Equal To. If X is <= Y, the value of X <= Y is 1. If X is not <= Y, the value of X <= Y is 0. 
No 
!> 
11 
LTR 
Not Greater Than. This operator is equivalent to a MIN function in some programming languages. In the expression X !> Y, the intent is to limit the value of X such that it is not greater than Y. If X is > Y, the value of X !> Y is Y. If X is not > Y, the value of X !> Y is X. 
No 
!< 
11 
LTR 
Not Less Than. This operator is equivalent to a MAX function in some programming languages. In the expression X !< Y, the intent is to limit the value of X such that it is not less than Y. If X is < Y, the value of X !< Y is Y. If X is not < Y, the value of X !< Y is X. 
No 
!>= 
11 
LTR 
Not Greater Than or Equal To In the expression X !>= Y, the intent is to limit the value of X such that it is not greater than or equal to Y. If X is >= Y, the value of X !>= Y is Y–1 . If X is not >= Y, the value of X !>= Y is X. 
No 
!<= 
11 
LTR 
Not Less Than or Equal To In the expression X !<= Y, the intent is to limit the value of X such that it is not less than or equal to Y. If X is <= Y, the value of X !<= Y is Y+1. If X is not <= Y, the value of X !=< Y is X. 
No 
!= <> 
10 10 
LTR LTR 
Not Equal To != is the C language operator, <> is a common alternative notation. Both have same meaning and are interchangeable. If X is equal to Y, the value of X <> Y is 0. If X is not equal Y, the value of X <> Y is 1. 
No 
== 
10 
LTR 
Equal To. == is the C language operator. If X is not equal to Y, the value of X == Y is 0. If X is equal Y, the value of X == Y is 1. 
No 
= 
10 
LTR 
Equal To. The calculation function defines the = operator by context. When it appears enclosed within () parentheses , the = operator is treated as an alias for the == comparison operator, meaning it has the same priority and associativity. When = appears with [] set enclosures or is not enclosed, it is treated the same as the := explicit assignment operator. Only one unenclosed = may appear in a given statement or set clause. This means that expressions like X = Y = Z are illegal. The calculation function performs this context determination in order to prevent common misuse of = and == inside of comparison subexpressions, to help prevent errors. Because a plain = outside of parentheses is assumed to be an assignment, if you wanted to perform a comparison instead, you must either use an explicit == comparison operator, or put the expression with = in parentheses. 
No 
& 
9 
LTR 
Bitwise AND 
Yes 
^ 
8 
LTR 
Bitwise XOR 
Yes 
 
7 
LTR 
Bitwise OR 
Yes 
&& 
6 
LTR 
Logical AND. X && Y is equivalent to !!X & !!Y.
If X=0 or Y=0, X && Y = 0 If X not = 0 and Y not = 0, X && Y = 1 
Yes 
^^ 
5 
LTR 
Logical XOR. X ^^ Y is equivalent to !!X ^ !!Y. The operator returns 1 if X and Y are logically different. If X=0 and Y=0, X ^^ Y = 0 If X = 0 and Y not = 0, X ^^ Y = 1 If X not = 0 and Y = 0, X ^^ Y = 1 If X not = 0 and Y not = 0, X ^^ Y = 0 
Yes 
 
4 
LTR 
Logical OR. X  Y is equivalent to !!X  !!Y. If X=0 and Y=0, X  Y = 0 If X not = 0 or Y not = 0, X  Y = 1 
Yes 
:: 
3 
NON 
Swap variables. Both the lefthand operand and the righthand operand must be variables. The contents of the two variables are swapped. It is not an error if the two variables are the same, but this would serve no purpose. Once the operator is executed, the value of the expression as a whole is the value of the variable on the left side after the swap occurs. That is, after X :: Y is performed, the value of the expression will be the new value of X which will be the former value of Y. 
No 
<: 
3 
NON 
Conditional swap variables for <= Both the lefthand operand and the righthand operand must be variables. The operator implements a “sorting” or “ordering” function. In the expression X <: Y, the intent is to conditionally swap the contents of the two variables, if necessary, so that the relationship X <= Y holds true. If X <= Y is already true, no swap occurs. If X <= Y is false, a swap occurs. It is not an error if the two variables are the same, but this would serve no purpose. Once the operator is executed, the value of the expression as a whole is the value of the variable on the left side, whether swapped or not. That is, after X <: Y is performed, the value of the expression will be the new value of X which will be the former value of Y if a swap occurred, otherwise it will be the former value of X. 
No 
>: 
3 
NON 
Conditional swap variables for >= Both the lefthand operand and the righthand operand must be variables. The operator implements a “sorting” or “ordering” function. In the expression X >: Y, the intent is to conditionally swap the contents of the two variables, if necessary, so that the relationship X >= Y holds true. If X >= Y is already true, no swap occurs. If X >= Y is false, a swap occurs. It is not an error if the two variables are the same, but this would serve no purpose. Once the operator is executed, the value of the expression as a whole is the value of the variable on the left side, whether swapped or not. That is, after X >: Y is performed, the value of the expression will be the new value of X which will be the former value of Y if a swap occurred, otherwise it will be the former value of X. 
No 
[ ] 
2 
RTL 
Set expression A set expression provides a means both to evaluate expressions conditionally, and to do a simple tablelookup operation. The general form of a set expression is: expr select [ expr 1 , expr 2 , … expr n ] Each expression inside the brackets is called a set clause. The selector expression is evaluated.
If your selector expression is a conditional operator, in which true expressions evaluate to 1 and false expressions evaluate to 0, you would write an expression that used such a condition like this: conditionalExpression [ truePart , falsePart ] For example, if you wanted a value of 123 if X is greater than 5, otherwise a value of 456, you would use: X > 5 [123, 456] Here, if X>5 is true, the condition evaluates to 1, and the first set clause (123) is selected. If X>5 is false, the condition evaluates to 0, which is an outofbounds set selector, resulting in the last set clause of the set expression (456) being selected by default. Suppose you wanted to set the return variable R (or other variable) to one of these two values. In a programming language, you might do this with a statement something like, if x > 5 then r = 123 else r = 456 endif In a calculation operand, you could do the same thing with: R = X > 5 [123, 456] You are allowed to use assignment operators within a set expression. For example, if you wanted a value of 123 assigned to variable R if X is greater than 5, otherwise a value of 456, you can rewrite the expression above as: X > 5 [R=123, R=456] When you use such expressions, only the selected set clause is executed, including any variable assignments within it; the remainder is skipped. Variable assignment operators in set clauses that are not selected are not performed. If you want to use a set expression to look up values, you write the set clauses in the order you want the selector expression to choose them. Suppose variable X was supposed to be from 1 to 3, and you wanted this converted to some special values, but set to 0 if it was out of range. You could do that with a set expression like this: X[123,456,789,0] 
n/a 
= 
1 
NON 
Assignment. The calculation function defines the = operator by context. When it appears within parentheses, the = operator is treated as an alias for the == comparison operator. When = appears with [] set enclosures or not enclosed, it is treated the same as the := operator. Only one unenclosed = may appear in a given statement or set clause. This means that expressions like X = Y = Z are illegal, because when the = operator is considered an assignment operator, it is nonassociative. That means the second equal sign has neither higher nor lower precedence than the first one, but is simply illegal. The first = equal sign between X and Y is valid, but the one between Y and Z is invalid. The reason this is done is to prevent confusing the intent of the expression. If the intent is to compare Y and Z for equality, and assign the comparison result to X, use X = (Y = Z) or X = Y == Z. If the intent is to first assign Z to Y, then assign Y to X, use X = Y := Z or X := Y := Z. The calculation function performs this context determination in order to prevent common misuse of = and == inside of comparison subexpressions. The lefthand operand must be a variable name. The value of an assignment expression is the value assigned to the variable. 
n/a 
:= 
1 
RTL 
Assignment. The lefthand operand must be a variable name. The value of an assignment expression is the value assigned to the variable. The := operator may be used in chained assignments (as shown above) and inside of parentheses and set expressions. 
n/a 
Operation and use of calculations in mapping strings
As noted in the beginning of this article, calculation operands can be used with the sequence mapping items SD and SX, and the numeric conversion mapping items DD, DX, XD and XX in mapping strings.
For a complete description of mapping strings, see Working with Mapping Strings. For concise information on specific mapping commands, see Mapping Strings Quick Reference Syntax and Examples.
Here are some brief examples.
1. Suppose you want to find some “words” and append a dash and a decimal numeric suffix to them. The first “word” gets a sequence number 1, the second get 2, etc. Let’s say your data looks like this:
000151 ***** one +++
000152 ***** two +++
000153 ***** three +++
000154 ***** four +++
You can find “word” strings of varying length with a Regular Expression of R'[az]+'. In order for the sequence number mechanism of mapping strings to function, you will have to use ALL in your CHANGE command.
For the M string portion, you will want to do the following:
 emit the original word; you can do that with a 1+ mapping code
 emit a dash; this is done with a '' literal
 create a sequence number value using the mapping command SD
If you want the shortest possible number used as the numeric suffix, you would use the Varying length format, with SDV or just SD alone. If you wanted a fixed number of digits (say, 4) you would specify a command like SD4F.
Put that all together, and your CHANGE command would look like this:
CHANGE ALL R'[az]+' M"1+ '' SD4F"
That would change your data as follows:
000151 ***** one0001 +++
000152 ***** two0002 +++
000153 ***** three0003 +++
000154 ***** four0004 +++
You will note that you can do all the above without the need of a calculation operand. But, suppose you didn’t want the suffix to be a value from 1 by 1, but a value from 0 by 20 plus a constant of 5. The SD command alone can’t do that, but used with a calculation operand, it can.
Recall from the description of the preinitialized values for calculation variables, variable S will contain the value of the original sequence number. In this example, that original sequence number ranges from 1 to 4. To get the numbers the way you want, you would have to subtract one from the sequence number, multiply it by 20, and then add 5. To make that the returned value, you would then assign the result to variable R. You would specify this in a calculation operand as R=(S1)*20+5. You incorporate the calculation operand into the mapping string and issue your command like this:
CHANGE ALL R'[az]+' M"1+ '' SD4F'R=(S1)*20+5'"
That would change your data as follows:
000151 ***** one0005 +++
000152 ***** two0025 +++
000153 ***** three0045 +++
000154 ***** four0065 +++
2. Continuing with the first example, suppose what you wanted was, not to append a sequential number, but the actual line number where the data lines are found. Let’s say our data is similar to the first example, but there are excluded lines between them:
****** ****************** Top of Data *******************
  < 000150 > 
000151 ***** one +++
  < 000010 > 
000162 ***** two +++
  < 000012 > 
000175 ***** three +++
  < 000014 > 
000190 ***** four +++
****** ***************** Bottom of Data *****************
We can accomplish this basically the same way as in example 1. We will again use the SD command.
You might wonder how we can use SD if we are not going to use the sequence number in the value. The answer is that when SD has a calculation operand, the calculation function is called and variables get preinitialized as described above. However, there is no requirement that SD or any of the other mapping commands that can use a calculation operand must reference variable S or any other variable. For our second example here, we will simply ignore variable S. The reason SD is the right command to use is that we want to “generate” a number that is not based on our input data – which here consists of words, rather than numbers.
The calculation operand here will be very simple. Variable L contains the line number where the CHANGE command finds the words in question. We just have to make sure than only nonexcluded lines are affected, and change the calculation operand to copy the value of variable L to variable R.
You would issue your command like this:
CHANGE ALL NX R'[az]+' M"1+ '' SD4F'R=L'"
That would change your data as follows:
****** ****************** Top of Data *******************
  < 000150 > 
000151 ***** one0151 +++
  < 000010 > 
000162 ***** two0162 +++
  < 000012 > 
000175 ***** three0175 +++
  < 000014 > 
000190 ***** four0190 +++
****** ***************** Bottom of Data *****************
3. Converting data to a hash key. This is just a madeup example, but it may give you some idea of what you can do with calculation operands, when you have an elaborate computation to perform.
Suppose you had a series of 5digit numbers, and you want to calculate a hash value. You have various issues to contend with:
 To make the process flexible, numbers > 99999 will be limited to 5 digits using an initial modulus, just to be safe. That is done with X \ 1L5.
 You calculate a second modules into 100003, but some of your numbers could be zero, and you can’t divide by zero. Instead, when the divisor is zero you force it to one.
 After taking a final modulus of 9973, the value will be in the range of 0 to 9972, but when the value was zero you want to force it to 9973.
Since we want to process original numeric data, this requires a DD command instead of SD. To keep the example simple, the data will be in fixed columns:
****** ****************** Top of Data *******************
000001 19453
000002 48470
000003 03085
000004 66247
****** ***************** Bottom of Data *****************
The numbers themselves are found with a picture of P'#####' 1 5, and variable X is set to this value. The result string will be 4 digits, so the basic DD command will appear as DD4F.
 The first modulus of X is calculated as A=X\1L5, to limit the values to 5 digits.
 Divide this into 100003, but if the value from the first step was zero, substitute 1 instead. Adding the conditional expression A=0 to A, whenever A is zero the value would be replaced by 1. Tests for equality have lower precedence than addition, so this part must be in parentheses. This gives B=100003\(A+(A=0)).
 The final modulus is calculated as R=B\9973.
 Forcing a zero value to 9973 requires a test for zero. Since assignments are also expressions that have the value assigned to the variable, we can take that assignment and compare it to zero. We have to use an explicit assignment of := so the expression is understood not to be a comparison operation. If it is zero, we can use the result of the comparison to select a substitute value for R using a set expression that contains an assignment to R. When R is not zero, we simply select a dummy set clause of 0, which is discarded, leaving the value of R unchanged.
This gives us the following calculation:
A=X\1L5;B=100003\(A+(A=0));((R:=B\9973)=0)[R=9973,0]
The complete CHANGE command would be:
C P'#####' 1 5 M"DD4F'A=X\1L5;B=100003\(A+(A=0));((R:=B\9973)=0)[R=9973,0]'"
Of course, a command this long is something you would prepare ahead of time. You can place the mapping string into an SPFLite SET variable, like this:
SET MYMAP = `M"DD4F'A=X\1L5;B=100003\(A+(A=0));((R:=B\9973)=0)[R=9973,0]']`
Then, issue the command as:
C P'#####' 1 5 =MYMAP
You can also compose long mapping strings in an SPFLite edit macro, and issue them using the SPF_Cmd() builtin function. The results of the CHANGE command would appear as follows. Note that these results were tested using the actual calculation function, and verified with an Excel spreadsheet:
****** ****************** Top of Data *******************
000001 2738
000002 3063
000003 1283
000004 3837
****** ***************** Bottom of Data *****************
Calculator commandline test program
Because the use of a calculator in a text editor is a somewhat novel feature, you may need a little practice working with it to be sure you understand how it works. One way to do that is by creating experimental mapping strings with calculation operands, and observing how they operate on test data. However, that process could be somewhat timeconsuming.
An easier way to explore this is with a small commandline test program called mapping_calc.exe.
This program will first prompt you for an initial sequence number (seq ‑>). If you use expressions that reference variable S, this will provide an incrementing value for each calc expression you supply, starting with the number you enter. If you just press Enter, the starting number will be 1. If you provide a starting number of 0, variable S will be set to 0 each time the calculation function is called, and the value will not be incremented.
You cannot directly set the values of the Linenumber variable L or the Columnnumber variable C. Instead, mapping_calc.exe will assign random numbers to these values for testing purposes, with variable L receiving random numbers between 1 and 1000, and variable C receiving random numbers between 1 and 80.
The program will then prompt you for an initial value (init ‑>) and a calculation operand (calc ‑>). The initial value is used to initialize variables R and X.
You type these in as you would in a mapping string (just the calculation part). It will then return the calculated result in decimal (dec ‑>) and hex (hex ‑>), and report any errors it may have found.
If a specific column is associated with an error, it will appear at the beginning of the error message in parentheses. For example, if you specified a calculation operand of R=X/\2 this would be an error, since both / and \ are binary operators, and there is no such operator as /\. Since the error would be detected when the \ was reached in position 5 of the expression, you would see the error message (5): Calc operand has syntax error at \.
To terminate the program, simply press Enter twice at the (init ‑>) prompt, or click on the [x] Windows button. In this program, hex values are entered and displayed with a leading . dot notation. You can use this hex format for both the initial value and in the calculation expression itself, as described above in the section Specifying numeric literals.
The mapping_calc.exe program is distributed with the SPFLite installation.
Created with the Personal Edition of HelpNDoc: Easily create Web Help sites