### Relational Operators

SPL includes a number of relational and logical operators and functions:

 Operator Function Description < LESSER less than <= LESSEREQ less than or equal > GREATER greater than >= GREATEREQ greater than or equal == EQUAL Equal != NOTEQ not equal && AND logical and || OR logical or ! NOT logical not XOR exclusive or % MOD Modulo

For example, the expression a != 10 is functionally equivalent to noteq(a, 10).

Relational and logical operators return a binary result (1 or 0) for scalar parameters. For example:

a = 1;

a < 10; returns: 1

a != 1; returns: 0

Here are two functions that determine whether a number is even or odd:

/* returns 1 if number is even, else 0 */

iseven(x)

{

return(2*(int(x/2)) == x);

}

/* returns 1 if number is odd, else 0 */

isodd(x)

{

return(not(iseven(x)));

}

The built-in int function returns the integer part of a number. The % operator could also be used to detect an even or odd number.

/* returns 1 if number is even, else 0 */

iseven(x)

{

return(x % 2 == 0);

}

/* returns 1 if number is odd, else 0 */

isodd(x)

{

return(x % 2 != 0);

}

A function that returns the sign of a number is quite straightforward:

/*

*  returns the sign of a number,

*  1: positive, 0: zero, -1: negative

*/

sgn(n)

{

local sign;

sign = (n > 0) - (n < 0);

return(sign);

}

Relational and logical operators also work on entire series, returning a binary series (a series consisting of 1's or 0's) as the result.

s = {1, 2, 3, 4};

t = s >= 2;

The series t contains the values {0, 1, 1, 1}. This feature results in very powerful and compact SPL code. Consider the function:

/* replace series values based on logical condition */

replace(s, cond, val)

{

local result;

result = s * not(cond) + val * cond;

return(result);

}

Now replace(w1, w1 > 10, 11) replaces all the values in W1 that exceed 10.0 with the value 11.0. The expression replace(w1, w1 < w2, w2) creates a series that contains the larger of the values of W1 and W2 on a point by point basis. Notice again that traditional looping is not required.

As a related example, the following function returns the indices of the non-zero elements of a series or array.

/* return indices of non-zero elements of an array */

findnz(x)
{
local len, ncol, nz, ind, rowind;

(len, ncol) = size(x);

/* length for indices */
num = len * ncol;

/* get non-zero values */
nz = (unravel(x) != 0.0);

/* generate indices */
ind = 1..num;

/*
*  get indices by multiplying and
*  removing the zero elements
*/

rowind = nz * ind;
rowind = delete(rowind, rowind == 0.0);

return(rowind);
}

The size function returns the number of rows and columns of an array. By exploiting the series processing feature of SPL, the series nz is 1 where the input is non-zero and 0 where the input is zero. Multiplying nv by a linear ramp of slope 1 and then removing the zero elements produces a series that contains the indices of the non-zero elements of the input. For example:

a = {1, 0, 5};

b = findnz(a);

c = findnz(a > 1);

d = a[b];

b == {1, 3}

c == {3}

d == {1, 5}

The built-in find function returns the indices of the non-zero elements of array as a single "unraveled" series. These indices can be used to address arrays.

a = {{1, 2, 3}, {4, 5, 2}, {2, 8, 9}};

b = find(a == 2);

c = a[b];

b == {3, 4, 8}

c == {2, 2, 2}