# Operators

The M[UMPS] programming language knows a number of 'operators'. Some operators are the familiar arithmetic ones while others operate on strings or compare values. In M[UMPS], the operators can be mixed in any order, but keep in mind that some operators imply a specific interpretation of their operands. The only order of precedence for binary operators in M[UMPS] is the strict left- to-right evaluation, and unary operators only apply in a right- to-left order. If that order of precedence needs to be overridden, parentheses can be used to indicate that a sub- expression has to be evaluated first.

Depending on where one went to school, different schemes for the order of computations were taught. The main different 'schools' that I am aware of are:

Central Europe   USA and Great Britain
1.Raising to a power1.Raising to a power (including taking roots)
2.Multiplication
3.Division
4.Take root2.Multiplication or division

So that the result of: 4/2*2 is equal to 1 in The Netherlands (multiplication takes precedence over division), but equal to 4 in England (multiplication and division have no difference in precedence, so the left-to-right evaluation prevails).

M[UMPS] evaluates strictly from left to right, so that 1+1*2 yields 4 and not 3.

When a different precedence is to be established, parentheses should be used: the expressions 1+(1*2) and 1*2+1 will both yield 3.

Assume that K=34; the expression "_11_22_33_"["_"_K_"_" will evaluate as "134_". The order of evaluation is: first evaluate "_11_22_33_"["_", which yields 1 (true), then the rest of the expression becomes: 1_K_"_", which leads to the value "134_".
If one wished to perform a check to verify that the value of K is contained in a list, parentheses are required:
"_11_22_33_"[("_"_K_"_") will return a true-or-false value (bve, boolean valued expression), which is only true when K has one of the values 11, 22 or 33.

Assume that L=29 and K=34; the series of commands

IF K=L+3 WRITE !,"K=32"

will result in the text "K=32" being printed, regardless of the value of K.
In this case, the order of evaluation is: first compare K=L, which will yield 0 (false), then the evaluation continues with 0+3, which yields 3 (true), so that the commands following the IF command will always be processed.
The formula that was intended could be either L+3=K or K=(L+3).

## Arithmetic operator 'plus' (+)

Introduced in the 1977 ANSI M[UMPS] language standard.

Reference   Value
1+1   2
2+2   4
(-3)+(-4)   -7

Unary usage

Reference   Value
+1   1

Forced numeric interpretation

Reference   Value
+"27 apples"   27

Reference   Value
+++---+--+3   -3

Force numeric interpretation

Reference   Value
"2 apples"+"3 oranges"   5

## Arithmetic operator 'minus' (-)

Introduced in the 1977 ANSI M[UMPS] language standard.

Reference   Value
3-1   2
7-2   5
2-7   -5
(-3)-(-4)   1

Unary usage

Reference   Value
-1   -1

Reference   Value
+++---+--+3   -3

Force numeric interpretation

Reference   Value
"5 apples"-"3 oranges"   2

## Arithmetic operator 'times' (*)

Introduced in the 1977 ANSI M[UMPS] language standard.

Reference   Value
3*3   9
7.5*2   15
-2.5*2.5   -6.25
2.5*-2.5   -6.25
(-3)*(-4)   12

Force numeric interpretation

Reference   Value
"5 apples"*"3 oranges"   15

## Arithmetic operator 'divided by' (/)

Introduced in the 1977 ANSI M[UMPS] language standard.

Reference   Value
9/3   3
5/2   2.5
5/-2   -2.5
-5/2   -2.5

No leading zero in canonic representation of numbers between -1 and +1:

Reference   Value
1/2   .5
-1/2   -.5

The number of digits is implementation-specific; 1977 ANSI standard guarantees 12 digits

Reference   Value
1/2   .5
1/3   .333333333333
1/128   .0078125

Definitely not equal to 1:

Reference   Value
1/3*3   .999999999999

Force numeric interpretation

Reference   Value
"15 apples"/"3 oranges"   5

In 1995 standard:

The 1995 standard guarantees 15 digits

Reference   Value
1/3   .333333333333333

Added in the 1995 ANSI M[UMPS] language standard:

Reference   Value
X/0   Error (M9)

## Arithmetic operator 'integer divided by' (\)

Introduced in the 1977 ANSI M[UMPS] language standard.

Reference   Value
9\3   3
5\2   2
-5\2   -2
1\2   0
-1\2   0

Definitely not equal to 1

Reference   Value
1\3*3   0

Added in the 1995 ANSI M[UMPS] language standard:

Reference   Value
X\0   Error (M9)

## Arithmetic operator 'modulo' (#)

Introduced in the 1977 ANSI M[UMPS] language standard.

This is probably the most mis-understood operator (or function) in many programming languages. FORTRAN and C have 'remainder' operators, Ada and M[UMPS] have a true 'modulo' operator. These two are not the same (although the result is identical when both operands are positive).

The definition of remainder depends on where you went to school. If you learned math in Europe, you will have a radically different opinion about the sign of a remainder than if you went to school in the USA (when either or both of the operands are negative, that is, when both operands are positive, everyone agrees).
Both 'schools' are correct, and, as long as you follow your definition consistently, you will have no problems.
In M[UMPS], however, there is no remainder operator. There is the modulo instead.
The definition of modulo is based on Abelian group theory, and the true mathematical definition is little known outside of mathematical graduate schools (see for instance Donald Knuth's The Art of Computer Programming, Volume 1, page 23 and further), but the following explanation is close enough for practical purposes:

The mathematical definition of Modulo maps a potentially infinitely large set of numbers onto a (usually finite) subset. The subset is repeated cyclically to map every number from the original set onto a member of the subset.
number#sub means: map the number on the left-hand side onto the subset [0,sub) (0, zero inclusive, sub exclusive). If sub is negative, this should be (sub,0], of course.
For example, number#5 and number#-5 would map as follows:

 number -9 -8 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7 8 9 number#(5) 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 number#(-5) -4 -3 -2 -1 0 -4 -3 -2 -1 0 -4 -3 -2 -1 0 -4 -3 -2 -1

Added in the 1995 ANSI M[UMPS] language standard:

Reference   Value
X#0   Error (M9)

## Arithmetic operator 'to the power of' (**)

Introduced in the 1995 ANSI M[UMPS] language standard.

Reference   Value
2**5   32
2**3   8
-2**3   -8
16**.25   2
-32**(1/5)   -2
-2**.5   not specified
-27**(1/3)   not specified
3**2   9
2**3**4   4096
4**0.5   2
4**(-2)   .0625
27**(1/3)   3 (if 1/3 is that exact...)
2.5**2   6.25
-1**3   -1
-8**(1/3)   -2 or error

Square root:

Reference   Value
4**.5   2
2**.5   1.4142...

The standard does not (yet) define any behavior in the case of imaginary or complex results

Reference   Value
-1**.5   error or "0%1"

This should always work

Reference   Value
32**.2   2

But this depends on the precision that the implementation offers internally

Reference   Value
-32**.2   -2 (or error)

## String operator 'concatenate' (_)

Introduced in the 1977 ANSI M[UMPS] language standard.

Reference   Value
9_3   93

No separator remains

Reference   Value
"First"_"Second"   FirstSecond

Unless embedded in either operand

Reference   Value
"First"_" Second"   First Second

Or explicitly specified

Reference   Value
"First"_" "_"Second"   First Second

## Assignment operator 'becomes' (=)

Introduced in the 1977 ANSI M[UMPS] language standard.

SET X=1
SET X=A+B*23_" apples"

SET X=A=B
Note: the first "=" sign is an assignment operator, the second "=" sign is a relational operator.

## Relational operator 'is equal to' (=)

Introduced in the 1977 ANSI M[UMPS] language standard.

IF A=123 SET X=1
SET Y=\$SELECT(B=938457:124,1:23746)

## Relational operator 'object is equal to' (==)

Approved for inclusion in a future ANSI M[UMPS] language standard.

This operator only returns a true value if both operands are pointers to objects, and both pointer identify the same instance of the same object.

IF docA==docB SET X=1
SET Y=\$SELECT(graph1==graph4:124,1:23746)

## Relational operator 'is greater than' (>)

Introduced in the 1977 ANSI M[UMPS] language standard.

IF A>123 SET X=1
SET Y=\$SELECT(B>938457:124,1:23746)

## Relational operator 'is less than' (<)

Introduced in the 1977 ANSI M[UMPS] language standard.

IF A<123 SET X=1
SET Y=\$SELECT(B<938457:124,1:23746)

## Relational operator 'is less than or equal to' (<=)

Approved for inclusion in a future ANSI M[UMPS] language standard.

IF A<=123 SET X=1
SET Y=\$SELECT(B<=938457:124,1:23746)

## Relational operator 'is greater than or equal to' (>=)

Approved for inclusion in a future ANSI M[UMPS] language standard.

IF A>=123 SET X=1
SET Y=\$SELECT(B>=938457:124,1:23746)

## Relational operator 'matches pattern' (?)

Introduced in the 1977 ANSI M[UMPS] language standard.

The pattern-codes to be used in pattern-matching are:
A: the 26 upper and 26 lower-case alphabetic characters
C: the 33 control-characters
E: the 128 characters in the ASCII set
L: the 26 lower-case characters
N: the 10 digits
P: the 33 punctuation-characters
U: the 26 upper-case characters

Modified for internationalization in the 1995 ANSI M[UMPS] language standard:
A: upper and lower-case characters
C: control-characters
E: all characters in the character set
L: lower-case characters
N: digits
P: punctuation-characters
U: upper-case characters

X?3N1"."2N.U

1 (true) when the value of variable X matches a pattern that "looks like" 3 digits, one point, 2 digits and any number of upper-case symbols, 0 (false) otherwise:

X?2U1"-"2N1"-"2U

1 (true) when the value of variable X matches the pattern of a 1985 Dutch license plate, 0 (false) otherwise:

X?3N1"."1.5N

1 (true) when the value of variable X is a positive number, less than 1000 with at least 1 and at most 5 digits following the decimal point, 0 (false) otherwise:

Addition in the 1995 ANSI M[UMPS] language standard

In order to support the Japanese character sets, two new pattern identifiers are added:

for Kanji (\$CHAR(161) - \$CHAR(223))
for JIS (\$CHAR(8481) - \$CHAR(32382))

Additions in the 1995 ANSI M[UMPS] language standard (and correction in a future) ANSI M[UMPS] language standard:

The concept of 'alternation' is introduced. An 'alternation' is a list of possible patterns that each are a valid match for a pattern.

X?2N1(3P2A,2P3A).E

is equivalent to
(X?2N3P2A.E)!(X?2N2P3A.E)

X?2N1"-"1(3N1"-"1N,1N1":"4N)
would match "12-345-6" and "12-3:4567".

X?.1(1"("3N1")".1(1"-",1"_"))3N.1(1"-",1"_")4N
would match any of:

5551212
555-1212
555_1212
(000)5551212
(000)555-1212
(000)555_1212
(000)-5551212
(000)-555-1212
(000)-555_1212
(000)_5551212
(000)_555-1212
(000)_555_1212

Approved for addition in a future ANSI M[UMPS] language standard:

In order to support the character ISO-8859-1/USA, a new pattern identifier is added:

I: "International" characters (any non-ASCII characters in ISO-8859-1/USA).

It is made possible to exclude certain patterns:

X?.'C

1 (true) when the value of variable X does not contain any control characters, 0 (false) otherwise:

X?1"Y".'"Y"1"Y"

1 (true) when the value of variable X starts and ends with the letter "Y", and no other occurrences of that letter are present in that value, 0 (false) otherwise:

The concept of "ranges" is introduced. It is made possible to specify that a pattern is matched when one of a set of specified characters occurs:

Reference   Value
"word"?.["aeiouAEIOU"]   0 (false)
"ff3a"?.["a":"f"]["A":"F"]N   1 (true)

The first pattern would be matched by strings that contain only vowels; the second pattern would be matched by purely hexadecimal numbers.

As a new feature, it has been made possible to extract the substring that matches a specific sub-pattern from the string that is being "matched". When using this new feature, the name of the variable that is to receive the string-segment in question is named between parentheses following the pattern-atom that it is intended to match.

Assume that the value of local variable X matches the following pattern: X?4N1","1.3N, i.e. 4 numeric digits, one comma and then between one and 3 more digits. The code segment:
IF '(X?4N(ITEM)1","1.3N(QUANT(ITEM)) DO ...
would cause the values of local variables ITEM and QUANT(ITEM) to be set to ITEM=\$EXTRACT(X,1,4) (the part that matches 4N) and QUANT(ITEM)=\$EXTRACT(X,6,\$LENGTH(X)) (the part that matches 1.3N).

Note that the assignment occurs as the pattern is being matched (strict left-to-right), so that the value of local variable ITEM is well defined when the pattern matching processor will attempt to assign a value to QUANT(ITEM).

## Relational operator 'contains' ([)

Introduced in the 1977 ANSI M[UMPS] language standard.

Assume that DIAGNOSIS="flu-patient".

Reference   Value
DIAGNOSIS["pat"   1 (true)
DIAGNOSIS["lu"   1 (true)
DIAGNOSE["flute"   0 (false)
DIAGNOSE["pantie"   0 (false)

Note that all characters of both "pantie" and "flute" do occur in "flu-patient"; those of "flute" even occur in the same order. The contains operator insists not only that the symbols in the substring occur in that order, but also as a 'solid' substring.

## Relational operator 'follows' (])

Introduced in the 1977 ANSI M[UMPS] language standard.

Assume that TXT1="ABC" and TXT2="ABD".

Reference   Value
TXT2]TXT1   1 (true)
"ABCD"]TXT1   1 (true)

Note that the lexicographical order of the texts "1", "2" and "10" is: "1", "10", "2", i.e.:

Reference   Value
10]1   1 (true)
2]1   1 (true)
10]2   0 (false)

## Relational operator 'follows or equal to' (]=)

Approved for inclusion in a future ANSI M[UMPS] language standard.

Reference   Value
10]=10   1 (true)
2]=1   1 (true)
10]=2   0 (false)
10]=1   1 (true)
2]=2   1 (true))

## Relational operator 'collates after' (]])

Introduced in the 1995 ANSI M[UMPS] language standard.

Assume that TXT1="ABC" and TXT2="ABD".

Reference   Value
TXT2]]TXT1   1 (true)
"ABCD"]]TXT1   1 (true)
"ABCD"]]1   1 (true)
TXT1]]2   1 (true)
10]]1   1 (true)
2]]1   1 (true)
10]]2   1 (true)

A future ANSI M[UMPS] language standard introduces an override mechanism for collating purposes. See the library functions \$%COLLATE^CHARACTER and \$%COMPARE^CHARACTER for more information about the override options.

## Relational operator 'collates after or equal to' (]]=)

Approved for inclusion in a future ANSI M[UMPS] language standard.

Reference   Value
TXT2]]=TXT1   1 (true)
"ABCD"]]=TXT1   1 (true)
"ABCD"]]=1   1 (true)
TXT1]]=2   1 (true)
10]]=10   1 (true)
2]]=2   1 (true)
10]]=2   1 (true)

A future ANSI M[UMPS] language standard introduces an override mechanism for collating purposes. See the library functions \$%COLLATE^CHARACTER and \$%COMPARE^CHARACTER for more information about the override options.

## Logical operator 'and' (&)

Introduced in the 1977 ANSI M[UMPS] language standard.

Reference   Value
0&0   0 (false)
0&1   0 (false)
1&0   0 (false)
1&1   1 (true)

Reference   Value
"5 apples"&"3 pears"   1 (true)
1&"3 pears"   1 (true)
"5 apples"&"trees"   0 (false)
"0.125"&1   1 (true)
"5 apples"&0   0 (false)
"apples"&0   0 (false)

Careful with:

Reference   Value
A>3&B<6   1 (always true)

(A>3&B is 0 or 1, both 0 and 1 are <6)
The value of (A>3)&(B<6) depends on the values of A and B

## Logical operator 'or' (!)

Introduced in the 1977 ANSI M[UMPS] language standard.

Reference   Value
0!0   0 (false)
0!1   1 (true)
1!0   1 (true)
1!1   1 (true)

Reference   Value
"5 apples"!"3 pears"   1 (true)
1!"3 pears"   1 (true)
"5 apples"!"trees"   1 (true)
"0.125"!1   1 (true)
"5 apples"!0   1 (true)
"apples"!0   0 (false)

Careful with:

Reference   Value
A>3!B<6   1 (always true)

(A>3!B is 0 or 1, both 0 and 1 are <6)
The value of (A>3)!(B<6) depends on the values of A and B

## Logical operator 'exclusive or' (!!)

Approved for inclusion in a future ANSI M[UMPS] language standard.

Reference   Value
0!!0   0 (false)
0!!1   1 (true)
1!!0   1 (true)
1!!1   0 (false)

Reference   Value
"5 apples"!!"3 pears"   0 (false)
1!!"3 pears"   0 (false)
"5 apples"!!"trees"   1 (true)
"0.125"!!1   0 (false)
"5 apples"!!0   1 (true)
"apples"!!0   0 (false)

Careful with:

Reference   Value
A>3!!B<6   1 (always true)

(A>3!!B is 0 or 1, both 0 and 1 are <6)
The value of (A>3)!!(B<6) depends on the values of A and B

## Logical unary operator 'not' (')

Introduced in the 1977 ANSI M[UMPS] language standard.

Reference   Value
'12345   0 (false)
'0   1 (true)
'"Apples"   1 (true)

The logical or Boolean value of X:

Reference   Value
''X   0 or 1

The exclusive or of two values:

Reference   Value
'X'='Y   X xor Y

This operator can also be used to modify the meaning of other operators:

'= is not equal to
'> is not greater than, i.e. is less than or equal to
'< is not less than, i.e. is greater than or equal to
'? does not match the pattern
'[ does not contain
'] does not follow
'& not and
'! not or

']] does not collate after

To be added in a future standard:
'<= is not less than or equal to, i.e. is greater than
'>= is not greater than or equal to, i.e. is less than
']= does not follow and is not equal to
']]= does not collate after and is not equal to
'!! not exclusive or

## Indirection operator (@)

Introduced in the 1977 ANSI M[UMPS] language standard.

Three types of indirection:

Name indirection

SET X="ABC"
IF 123+@X=456

Argument indirection

SET SPACE="!!!",PAGE="#"
WRITE @\$SELECT(ENOUGH:SPACE,1:PAGE)

Pattern indirection

SET CODE="3U"_\$SELECT(SPECIAL:"2N",1:"")_"5L"
IF X?@CODE

Addition in 1984 ANSI M[UMPS] language standard.

Fourth type of indirection, subscripted reference indirection:

SET ARRAY="PRICES"
SET PRICE=(100+SALESTAX/100)*@ARRAY@(1,2,3)

SET ARRAY="^CUSTOMER(123,45)"
SET TOTAL=TOTAL+@ARRAY@(2,3,4)

Approved for addition in a future ANSI M[UMPS] Language standard.

Fifth type of indirection, "generic" indirection.

This new type of indirection involves a "catch-all" recovery after all other types of indirection have been attempted by a M[UMPS] language processor. When code is encountered that uses indirection, and none of the above forms of indirection leads to a valid interpretation of the code, the indirection operator and the expression on which it operates are to be replaced by the value of the expression in question, and then the line of code is to be re-evaluated. This may lead to some surprising possibilities:

SET X1="Y"
SET X2="Z="
SET X3="SecretAccnt=1E9,N"
SET X4="N=1 HALT"
SET Y="Example"
SET Y1="Example1"
SET Z1="Program"
SET Z2="TAG^Program"
SET Z3="(1,2,3)"
SET Z4=",2,3,4)"

With these values:

SET @X1="HELLO"
will be executed as: SET Y="HELLO"

SET @X2"HELLO"
will be executed as: SET Z="HELLO"

SET @X3="HELLO"
will be executed as: SET SecretAccnt=1E9,N="HELLO"

SET @(X1)1="Example"
will be executed as: SET Y1="Example1"

DO ^@(Z1)(1,2,3)
will be executed as: DO ^Program(1,2,3)

DO @(Z2)(1,2,3)
will be executed as: DO TAG^Program(1,2,3)

DO @(Z2)@Z3
will be executed as: DO TAG^Program(1,2,3)

DO @(Z2)("BLUE"@Z4
will be executed as: DO TAG^Program("BLUE",2,3,4)

This document is © Ed de Moel, 1995-2005.
It is part of a book by Ed de Moel that is published under the title "M[UMPS] by Example" (ISBN 0-918118-42-5).
Printed copies of the book are no longer available.

This document describes the various operators that are defined in the M[UMPS] language standard (ANSI X11.1, ISO 11756).

The information in this document is NOT authoritative and subject to be modified at any moment.
Please consult the appropriate (draft) language standard for an authoritative definition.

In this document, information is included that will appear in future standards.
The MDC cannot guarantee that these 'next' standards will indeed appear.