Home | Categories | Alphabetical | Classes | All Contents | [ < ] | [ > ]

IDL Operators


As described in the previous Overview section, operators are used to combine terms and expressions. IDL supports the following types of operators:

Parentheses

Parentheses are used to group expressions and to enclose function parameter lists. Parentheses can be used to override the order of operator evaluation described above. Examples:

;Parentheses enclose function argument lists. 
SIN(ANG * PI/180.) 
 
;Parentheses specify order of operator evaluation. 
(A + 5)/B 

The right parenthesis must always close the list begun by the left parenthesis.

Square Brackets

Square brackets are used to create arrays and to enclose array subscripts.

;Use brackets when assigning elements to an array. 
ARRAY = [1, 2, 3, 4, 5] 
 
;Brackets enclose subscripts. 
ARRAY[X, Y] 

Note
In versions of IDL prior to version 5.0, parentheses were used to enclose array subscripts. While using parentheses to enclose array subscripts will continue to work as in previous version of IDL, we strongly suggest that you use brackets in all new code. See Array Subscript Syntax: [ ] vs. ( ) for additional details.

Mathematical Operators

There are seven basic IDL mathematical operators, described below.

Assignment

The equal sign (=) is the assignment operator. The value of the expression on the right hand side of the equal sign is stored in the variable, subscript element, or range on the left side. For example, the following assigns the value 32 to A.

A = 32 

See Assignment for more information.

Compound Assignment Operators

In addition to the standard assignment operator, there are numerous compound operators (+=, -=, etc.) that combine assignment with another operator. Compound assignment operators provide succinct syntax for expressions in which the same variable would otherwise be present on both sides of the equal sign. For example, the following statements both add 100 to the current value of the variable A:

A = A + 100 
A += 100 

See Compound Assignment Operators for more information and a list of compound assignment operators.

Addition

The positive sign (+) is the addition operator. When applied to strings, the addition operator concatenates the strings. For example:

;Store the sum of 3 and 6 in B. 
B = 3 + 6 
 
;Store the string value of "John Doe" in B. 
B = 'John' + ' ' + 'Doe' 

Subtraction and Negation

The negative sign (-) is the subtraction operator. Also, the minus sign is used as the unary negation operator. For example:

;Store the value of 5 subtracted from 9 in C. 
C = 9 - 5 
 
;Change the sign of C. 
C = -C 

Multiplication

The asterisk (*) is the multiplication operator. For example:

; Store the product of 2 and 5 in variable C: 
C = 2 * 5 

Division

The forward slash (/) is the division operator. For example:

; Store the result of 10.0 divided by 3.2 in variable D: 
D = 10.0/3.2 

Exponentiation

The caret (^) is the exponentiation operator. A^B is equal to A raised to the B power.

For real numbers, A^B is evaluated as follows:

For complex numbers, A^B is evalutated as follows. The complex number A can be represented as A = a + ib, where a is the real part, and ib is the imaginary part. In polar form, we can represent the complex number as A = reiq = r cosq + ir sinq, where r cosq is the real part, and ir sinq is the imaginary part:

Modulo

The keyword MOD is the modulo operator. I MOD J is equal to the remainder when I is divided by J. The magnitude of the result is less than that of J, and its sign agrees with that of I. For example:

;Assign the value of 9 modulo 5 (4) to A. 
A = 9 MOD 5 
 
;Compute angle modulo 2p. 
A =(ANGLE + B) MOD (2 * !PI) 

Increment/Decrement

The increment (++) and decrement (--) operators can be applied to variables (including array subscripts or structure tags) of any numeric type. The ++ operator increments the target variable by one. The -- operator decrements the target by one. When written in front of the target variable (that is, using prefix notation), the operations are known as preincrement and predecrement, respectively. When written following the target variable (using postfix notation), they are called postincrement and postdecrement.

Note
The increment and decrement operators can only be applied to variable expressions to which a value can be assigned. Hence, the following is not allowed:

A = 23++

because it attempts to apply the increment operator to a constant. Another way of stating this rule is to say that it must be possible for the expression being incremented or decremented to appear on the left-hand side of the equal sign.

The increment and decrement operators can be used either as standalone statements or within a larger enclosing expression. Although the two forms are very similar, the expression form has some efficiency and side-effect issues (described below) that do not apply to the statement form.

Increment/Decrement Statements

Increment and decrement operators can be used, along with a variable, as standalone statements:

The increment or decrement operator may be placed either before or after the target variable. The same operation is carried out in either case. These operators are very efficient, since the variable is incremented in place and no temporary copies of the data are made.

Increment/Decrement Expressions

Increment and decrement operators can be used within expressions. When the operator follows the target expression, it is applied after the value of the target is evaluated for use in the surrounding expression. When the operator precedes the target expression, it is applied before the value of the target is evaluated for use in the surrounding expression. For example, after executing the following statements, the value of the variable A is 27, while B is 28:

B = 27 
A = B++ 

In contrast, after executing the following statements, both A and B have a value of 26:

B = 27 
A = --B 
Efficiency of Prefix vs. Postfix Operations

When used as part of an expression, the prefix form of the increment and decrement operators has an efficiency advantage over the postfix form. The reason for this is that the postfix form requires IDL to make a copy of the data, while the prefix form does not. The operations carried out by IDL to execute a prefix increment or decrement operation are:

  1. Fetch the target variable.
  2. Increment or decrement the target variable in place (no copies are made).
  3. Use the variable when evaluating the surrounding expression.

This is very efficient. In contrast, the postfix form requires IDL to make a copy of the variable in order to use its old value in the surrounding expression following the increment/decrement. The operations carried out by IDL to execute a postfix increment or decrement operation are:

  1. Fetch the target variable.
  2. Make a temporary copy of the variable.
  3. Increment or decrement the original variable.
  4. Use the temporary copy when evaluating the surrounding expression.

If your computation requires the postfix form, then these operations are necessary and reasonable. If not, the prefix form will use fewer resources and is the better choice. The larger the data involved, the more important this becomes. It is not a concern for small variables.

Order Of Side Effects

The way that the increment and decrement operators change the value of a variable in addition to using its value in a surrounding expression is called a side effect. In most cases, the side effects are desired, and cause no problems. Side effects can cause problems, however, if the increment or decrement operator is applied to a variable that appears more than once within a single statement or expression. Consider the following statement (taken from The C Programming Language by Brian W. Kernighan and Dennis M. Ritchie):

A[i] = i++ 

Which value of i is used to index A? Is it the original value of i, or the incremented value? The answer depends on the order in which the various parts of the statement are evaluated. Either answer might be considered correct, and IDL does not require one or the other. Similarly, in the statements

B = 23 
A = B++ + B 

the value of A could be either 47 or 46, depending on which part of the expression is evaluated first.

Note that this situation falls outside the rules of operator precedence - it is the order in which the variables themselves are evalutated that affects the result. Let's examine the situation closely:

As with most languages that implement increment and decrement operators, IDL does not require any particular ordering of evaluation within an expression in which such side effects occur. Different versions or implementations of IDL may evaluate the same expression differently. As a result, you should avoid writing code that depends on a particular ordering of the side effects.

Minimum and Maximum Operators

The IDL minimum and maximum operators return the smaller or larger of their operands, as described below. Note that negated values must be enclosed in parentheses in order for IDL to interpret them correctly.

The Minimum Operator

The "less than" sign (<) is the IDL minimum operator. The value of "A < B" is equal to the smaller of A or B. For example:

;Set A equal to 3.  
A = 5 < 3 
 
;Set A equal to -6.  
A = 5 < (-6) 
 
;Syntax Error. IDL attempts to perform a subtraction operation if  
;the "-6" is not enclosed in parentheses. 
A = 5 < -6 
 
;Set all points in array ARR that are larger than 100 to 100. 
ARR = ARR < 100 
 
;Set X to the smallest of the three operands. 
X = X0 < X1 < X2 
 

For complex numbers the absolute value (or modulus) is used to determine which value is smaller. If both values have the same magnitude then the first value is returned.

For example:

; Set A equal to 1+2i, since ABS(1+2i) is less than ABS(2-4i) 
A = COMPLEX(1,2) < COMPLEX(2,-4) 
 
; Set A equal to 1-2i, since ABS(1-2i) equals ABS(-2+i) 
A = COMPLEX(1,-2) < COMPLEX(-2,1) 

The Maximum Operator

The "greater than" sign (>) is the IDL maximum operator. "A > B" is equal to the larger of A or B. For example:

;'>' is used to avoid taking the log of zero or negative numbers. 
C = ALOG(D > 1E - 6) 
 
;Plot positive points only. Negative points are plotted as zero. 
PLOT, ARR > 0 
 

For complex numbers the absolute value (or modulus) is used to determine which value is larger. If both values have the same magnitude then the first value is returned. For example:

 
; Set A equal to 2-4i, since ABS(2-4i) is greater than ABS(1+2i) 
A = COMPLEX(1,2) > COMPLEX(2,-4) 
 
; Set A equal to 1-2i, since ABS(1-2i) equals ABS(-2+i) 
A = COMPLEX(1,-2) > COMPLEX(-2,1) 

Matrix Multiplication

IDL has two operators used to multiply arrays and matrices.

The # Operator

The # operator computes array elements by multiplying the columns of the first array by the rows of the second array. The second array must have the same number of columns as the first array has rows. The resulting array has the same number of columns as the first array and the same number of rows as the second array.

Tip
If one or both of the arrays are also transposed as part of a matrix multiplication, such as TRANSPOSE(A) # B, it is more efficient to use the MATRIX_MULTIPLY function, which does the transpose simultaneously with the multiplication.

The ## Operator

The ## operator does what is commonly referred to as matrix multiplication. It computes array elements by multiplying the rows of the first array by the columns of the second array. The second array must have the same number of rows as the first array has columns. The resulting array has the same number of rows as the first array and the same number of columns as the second array.

For an example illustrating the difference between the two, see Multiplying Arrays.

Array Concatenation

The square brackets are used as array concatenation operators. Operands enclosed in square brackets and separated by commas are concatenated to form larger arrays. The expression [A,B] is an array formed by concatenating A and B, which can be scalars or arrays, along the first dimension.

Similarly, [A,B,C] concatenates A, B, and C. The second and third dimensions can be concatenated by nesting the bracket levels; [[1,2],[3,4]] is a 2-element by 2-element array with the first row containing 1 and 2 and the second row containing 3 and 4. Operands must have compatible dimensions; all dimensions must be equal except the dimension that is to be concatenated, e.g., [2,INTARR(2,2)] are incompatible. Examples:

;Define C as three-point vector. 
C = [-1, 1, -1] 
 
;Add 12 to the end of C. 
C = [C, 12] 
 
;Insert 12 at the beginning of C. 
C = [12, C] 
 
;Plot ARR2 appended to ARR1.    
PLOT, [ARR1, ARR2] 
 
;Define a 3x3 matrix. 
KER = [[1,2,1], [2,4,2], [1,2,1]] 

Note
Array concatenation is a relatively inefficient operation, and should only be performed once for a given set of data if possible.

Logical Operators

There are three logical operators in IDL: &&, ||, and ~.

&&

The logical && operator performs the logical short-circuiting "and" operation on two scalars or one-element arrays, returning 1 if both operands are true and 0 if either operand is false.

||

The logical || operator performs the logical short-circuiting "or" operation on two scalars or one-element arrays, returning 1 if either of the operands is true and 0 if both are false.

~

The logical ~ operator performs the logical "not" operation on a scalar or array operand. If the operand is a scalar, it returns scalar 1 if the operand is false or scalar 0 if the operand is true. If the operand is an array, it returns an array containing a 1 for each element of the operand array that is false, and a 0 for each element that is true.

Note
Programmers familiar with the C programming language, and the many languages that share its syntax, may expect ~ to perform bitwise negation (1's complement), and for ! to be used for logical negation. This is not the case in IDL: ! is used to reference system variables, the NOT operator performs bitwise negation, and ~ performs logical negation.

When is an Operand True?

When evaluated by a logical operator, an expression is considered to be "true" under the following conditions:

Short-circuiting

The && and || logical operators are short-circuiting operators. This means that IDL does not evaluate the second operand unless it is necessary in order to determine the proper overall answer. Short-circuiting behavior can be powerful, since it allows you to base the decision to compute the value of the second operand on the value of the first operand. For instance, in the expression:

Result = Op1 && Op2  

IDL does not evaluate Op2 if Op1 is false, because it already knows that the result of the entire operation will be false. Similarly in the expression:

Result = Op1 || Op2  

IDL does not evaluate Op2 if Op1 is true, because it already knows that the result of the entire operation will be true.

If you want to ensure that both operands are evaluated (perhaps because the operand is an expression that changes value when evaluated), use the LOGICAL_AND and LOGICAL_OR functions or the bitwise AND and OR operators.

Logical Operator Examples

Results of relational expressions can be combined into more complex expressions using the logical operators. Some examples of relational and logical expressions are as follows:

;True if A is between 25 and 50. If A is an array, then the result  
;is an array of zeros and ones. 
(A LE 50) && (A GE 25) 
 
;True if A is less than 25 or greater than 50. This is the inverse  
;of the first. 
(A GT 50) || (A LT 25) 

Bitwise Operators

There are four bitwise operators in IDL: AND, NOT, OR, and XOR. For integer operands (byte, signed- and unsigned-integer, longword, and 64-bit longword data types), bitwise operators operate on each bit of the operand or operands independently.

AND

The bitwise AND operator performs the logical "and" operation on two scalar or array operands. If the operands are scalars, it returns a scalar value. If either operand is an array, it returns an array containing one value for each element of the shortest array operand. The returned values are as follows:

NOT

The bitwise NOT operator returns the bitwise inverse of its scalar or array operand. If the operand is a scalar, it returns a scalar value. If the operand is an array, it returns an array containing one value for each element of the operand array. The returned values are as follows:

Warning
Use caution when using the return value from the bitwise NOT operator as an operand for the logical operators && and ||. See Note on the NOT Operator for additional discussion.

Note
Modern computers use the "2s complement" representation for negative signed integers. This means that to arrive at the decimal representation of a negative binary number (a string of binary digits with a one as the most significant bit), you must take the complement of each bit, add one, convert to decimal, and prepend a negative sign. For example, NOT 0 equals -1, NOT 1 equals -2, etc.

OR

The bitwise OR operator performs the logical "inclusive or" operation on two scalar or array operands. If the operands are scalars, it returns a scalar value. If either operand is an array, it returns an array containing one value for each element of the shortest array operand. The returned values are as follows:

XOR

The bitwise XOR operator performs the logical "exclusive or" operation on two scalar or array operands. If the operands are scalars, it returns a scalar value. If either operand is an array, it returns an array containing one value for each element of the shortest operand array. The returned values are as follows:

Bitwise Operator Examples

Some examples of bitwise expressions are as follows:

; Displays the "negative" of an image contained in the array IMG. 
TV, NOT IMG 
 
; Adds the hexadecimal constant FF (255 in decimal) to the array 
; ARR. This masks the lower 8-bits and zeros the upper bits. 
ARR AND 'FF'X 

Note on the NOT Operator

Due to the bitwise nature of the NOT operator, logical negation operations should always use ~ in preference to NOT, reserving NOT exclusively for bitwise computations. Consider a statement such as:

IF ((NOT EOF(lun)) && device_ready) THEN statement 

which wants to execute statement if the file specified by the variable lun has data remaining, and the variable device_ready is non-zero. When EOF returns the value 1, the expression NOT EOF(lun) yields -2, due to the bitwise nature of the NOT operator. The && operator interprets the value -2 as true, and will therefore attempt to execute statement incorrectly in many cases. The proper way to write the above statement is:

IF ((~ EOF(lun)) && device_ready) THEN statement 

Relational Operators

The IDL relational operators can be used to test the relationship between two arguments. The six relational operators are described in the following table:

Operator
Description
EQ
Equal to
NE
Not equal to
GE
Greater than or equal to
GT
Greater than
LE
Less than or equal to
LT
Less than

Relational operators apply a relation to two operands and return a logical value of true or false. The resulting logical value can be used as the predicate in IF, WHILE or REPEAT statements can be combined using Boolean operators with other logical values to make more complex expressions. For example: "1 EQ 1" is true, and "1 GT 3" is false.

The rules for evaluating relational expressions with operands of mixed modes are the same as those given above for arithmetic expressions. For example, in the relational expression "2 EQ 2.0", the integer 2 is converted to floating point and compared to the floating point 2.0. The result of this expression is true, as represented by a byte 1.

In IDL, the value "true" is represented by the following:

Conversely, false is represented as anything that is not true-zero or even-valued integers; zero-valued, floating-point quantities; and the null string.

The relational operators return a value of 1 for true and 0 for false. The type of the result is always byte.

EQ

EQ is the relational "equal to" operator. This operator returns true if its operands are equal; otherwise, it returns false. This operator always returns a byte value of 1 for true and a byte value of 0 for false.

For complex numbers both the real and imaginary parts must be equal. For example:

print, COMPLEX(1,2) EQ COMPLEX(1,2) ; returns true

print, COMPLEX(1,2) EQ COMPLEX(1,-2) ; returns false

NE

NE is the "not-equal-to" relational operator. This operator returns true whenever the operands are different. For example "sun" NE "fun" returns true.

For complex numbers both the real and imaginary parts must be equal to return a false value. For example:

print, COMPLEX(1,2) NE COMPLEX(1,2) ; returns false

print, COMPLEX(1,2) NE COMPLEX(1,-2) ; returns true

GE

GE is the "greater than or equal to" relational operator. The GE operator returns true if the operand on the left is greater than or equal to the one on the right. One use of relational operators is to mask arrays as shown in the following statement:

A = ARRAY * (ARRAY GE 100) 

This command sets A equal to ARRAY whenever the corresponding element of ARRAY is greater than or equal to 100. If the element is less than 100, the corresponding element of A is set to zero.

Strings are compared using the ASCII collating sequence: " " is less than "0" is less than "9" is less than "A" is less than "Z" is less than "a" which is less than "z".

For complex numbers the absolute value (or modulus) is used for the comparison.

GT

GT is the "greater than" relational operator. This operator returns true if the operand on the left is greater than the operand on the right. For example, "6 GT 5" returns true.

For complex numbers the absolute value (or modulus) is used for the comparison.

LE

LE is the "less-than or equal-to" relational operator. This operator returns true if the operand on the left is less than or equal to the operand on the right. For example, "4 LE 4" returns true.

For complex numbers the absolute value (or modulus) is used for the comparison.

LT

LT is the "less-than" relational operator. This operator returns true if the operand on the left is less than the operand on the right. For example, "3 LT 4" returns true.

For complex numbers the absolute value (or modulus) is used for the comparison.

Using Relational Operators with Arrays

Relational operators can be applied to arrays, and the resulting array of ones and zeroes can be used as an operand. For example, the expression, ARR * (ARR LE 100) is an array equal to ARR except that all points greater than 100 have been reduced to zero. The expression (ARR LE 100) is an array that contains a 1 where the corresponding element of ARR is less than or equal to 100, and zero otherwise. For example, to print the number of positive elements in the array ARR:

PRINT,TOTAL(ARR GT 0) 

Using Relational Operators with Infinity and NaN Values

On Windows and Solaris x86 platforms, using relational operators with the values infinity or NaN (Not a Number) causes an "illegal operand" error. The FINITE function's INFINITY and NAN keywords can be used to perform comparisons involving infinity and NaN values. For more information, see FINITE and Special Floating-Point Values.

Conditional Expression

The conditional expression-written with the ternary operator ?:-has the lowest precedence of all the operators. It provides a way to write simple constructions of the IF...THEN...ELSE statement in expression form. In the following example, Z receives the larger of the values contained by A and B:

IF (A GT B) THEN Z = A ELSE Z = B 

This statement can be written more concisely using a conditional expression:

Z = (A GT B) ? A : B 

The general form of a conditional expression is:

expr1 ? expr2 : expr3 

The expression expr1 is evaluated first. If expr1 is true, then the expression expr2 is evaluated and set as the value of the conditional expression. If expr1 is false, expr3 is evaluated and set as the value of the conditional expression. Only one of expr2 or expr3 is evaluated, based on the result of expr1. (See Definition of True and False for details on how the "truth" of an expression is determined.)

Note
Since ?: has very low precedence-just above assignment-parentheses are not necessary around expr1. However, parentheses are often used in this situation, as they enhance the readability of the expression.


Home | Categories | Alphabetical | Classes | All Contents | [ < ] | [ > ]