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}