Home » Support » Release Notes » 6.0 » SPL Enhancements


"A jewel, a fully responsive package that meets the needs of the Test & Evaluation world."

- Mike Alamo, Ordnance Evaluation

DADiSP 6.0 B18 Release Notes

SPL Enhancements


Direct Window Assignments


Windows can be used and assigned directly in SPL routines.

For example:


  wtest()
  {
     w1 := gnorm(100, .01);
     w2 := integ(w1);
  }

Sets W1 to a random series and W2 to integrate the contents of W1. This syntax is much simpler than using SETWFORM.

Note that:


  W1 := gnorm(100, .01)

assigns the formula and data to W1 whereas:


  W1 = gnorm(100, .01)

only assigns the data. The original Window formula is preserved.

Global Variable Assignments


Global hot variables can be assigned with the := operator.


  htest(hvar)
  {
      a := integ(w1);
       if (argc > 0) {
          eval(sprintf("%s := deriv(a)"));
      }
  }


  htest("dadt")

creates two hot variables, A and DADT. This syntax is a bit simpler than SETHOTVAR.

Ternary Conditional Statements


SPL supports C/C++ ternary conditionals. For example:


  a = (b > 0) ? b : b*b;

is equivalent to:


  if (b > 0) {
      a = b;
  }
  else {
      a = b*b;
  }

SPL Error Handlers


Optional user defined SPL error handlers are supported in the form:


  func_error(errnum, errmes)

where func is the original SPL function name, errnum is the supplied error number and errmes is the original error message. For example:


  myfun(x)
  {
      return(x*x);
  }

Running:


  b = myfun();

terminates execution and displays an error message. Because execution was discontinued, variable b is not assigned. However, by specifying an error handler:


  myfun_error(errnum, errmes)
  {
    message(sprintf("myfun error %d, %s",errnum,errmes));
    return(-1);
  }

Running:


  b = myfun();

pops up the message:


  myfun error -102, Line 3 x: Uninitialized Variable

but variable b is now assigned the value -1, the result of the error handler. Of course, the error handler is not required to display or process the error number or message.

An error handler can also terminate execution simply by calling the ERROR function. For example:


  myfun_error(errnum, errmes)
  {
    error(sprintf("myfun error %d, %s",errnum,errmes),1);
  }

is identical to the default behavior except in this case the error message is displayed in a pop-up box.

The errnum and errmes input arguments are optional for an error handler.

Variable SPL Arguments


SPL functions now accept a variable number of optional arguments. For example:


  /* maximum of one or more inputs */
  vmax(argv)
  {
      local i, s;

      /* 0 or 1 arg case */
      if (argc < 2) {
          if (argc < 1) {
              s = max();
          }
          else {
              s = max(getargv(1));
          }
      }
      else {
          /* initialize */
          s = max(getargv(1), getargv(2));

          /* compare input args */
          for (i = 3; i <= argc; i++) {
              s = max(s, getargv(i));
          }
      }
      return(s);
  }

  vmax(1, 3, 2, -1, 0)

returns 3.

The argv specifier indicates the SPL function accepts variable arguments and GETARGV(i) returns the ith argument.

{} Empty Array Syntax


An empty array can be created with the {} assignment.


  x = {}

defines a variable x that is an empty series.

String Comparison Operator


The == operator performs case sensitive string comparison

For example:


  a = "foo"
  b = "foo"
  c = "Foo"

  a == b  returns 1
  a == c  returns 0

Array Syntax for Strings


Strings variables can be addressed with the [] syntax. For example:


  a = "Larry";
  a[1] = 'H';

Variable a contains the string Harry.

Extern Keyword for Global Variables


SPL routines can now designate variables as global with the extern keyword. For example:


  myfun(x)
  {
      extern var;

      var = x * x;
  }

sets the global variable var to the square of the input. This is equivalent to:


  myfun(x)
  {
      setvar("var", x * x);
  }

The extern keyword can also be specified as: global, e.g.


  myfun(x)
  {
      global var;

      var = x * x;
  }

ITERATE Modifier for SPL Functions


Any SPL function can automatically iterate through each column of an input array, one by one, by specifying the ITERATE modifier.

Consider two similar SPL routines:


  scale1(x)
  {
      y = x / min(x);
      return(y);
  }

  ITERATE scale2(x)
  {
      y = x / min(x);
      return(y);
  }

  A = {{1, 2, 3},
       {2, 4, 6},
       {3, 6, 9}}

  y1 = scale1(A);
  y2 = scale2(A);

  y1 == {{1, 2, 3},
         {2, 4, 6},
         {3, 6, 9}}

  y2 == {{1, 1, 1},
         {2, 2, 2},
         {3, 3, 3}}

scale1 is defined as a standard SPL function and receives the entire array A as input. Consequently, the minimum is calculated as the minimum of the entire array, in this case 1.0.

Because scale2 is declared as an ITERATE function, it automatically iterates through each column of the input array one at a time. Since each iteration only receives a single column of the original input, the minimum is calculated as the minimum of the current column. Thus, scale1 behaves as:


     x / min(x)

but scale2 behaves as:


     x / colmin(x)

The ITERATE keyword makes it very easy to write a routine to handle each column of an array in the same manner without having to get bogged down in the details of multi-column operations. Simply write the function as if it will only receive a single column input and DADiSP will automatically apply the function to each column of the input array and accumulate the results.

The iteration behavior of an SPL function can be temporarily set or cleared at run time with the ITERATE function. For example:


     iterate("scale1", 1)

or


     iterate scale1

converts scale1 to an iterator function such that it operates identically to scale2. This behavior persists only for the duration of the current session. Use the ITERATE modifier in the function definition to make the behavior permanent.

SERIES Modifier for SPL Functions


The SERIES modifier forces an SPL routine to return a series. Consider two similar SPL routines:


  smax1(s)
  {
     return(max(s));
  }

  SERIES smax2(s)
  {
     return(max(s));
  }

  a = {{1, 2, 3},
       {2, 4, 6},
       {3, 6, 9}}

  m1 = smax1(a);
  m2 = smax2(a);

  m1 == 9
  m2 == {9}

Since the input is an array, smax1 returns the maximum of the entire array as a scalar, but smax2 returns the maximum as a series. This is equivalent to:


  {max(s)}

The SERIES modifier forces an SPL routine to always return a series. This behavior optimizes evaluation since the return type is already known before the calculation takes place. The optimizations are similar to what occurs with internal functions that always return a series such as FFT or INTEG.

The series mode of an SPL function can be temporarily set or cleared at run time with the SERIES function. For example:


  series("smax1", 1)

or


  series smax1

converts smax1 to a function that always returns a series. This behavior persists only for the duration of the current session. Use the SERIES modifier in the function definition to make the behavior permanent.

END Keyword for Arrays


If A is an array, A[end] returns the last element. For example:


  a = 1..100
  b = a[end]

  b == 100

New @@ Concatenate Operator


The statement:


  a = b @@ c

is more compact and equivalent to:


  a = concat(b, c)

New @= Append Operator


The statement:


  a @= b

is equivalent to:


  append(a, b)

The @= operator appends the series B to the end of series A in place. a @= b is much faster than a = a @@ b for large series because @= operates on the existing series whereas @@ creates and assigns a new series.

Faster FOR and LOOP iterators


The for and loop functions have been optimized for more efficient loop variable access, resulting in approximately 30% faster execution.

Faster ++, --, +=, -=, *=, /= Operators


The ++, --, +=, -=, *=, /= operators have been optimized by using inplace series and variable assignments. These operators now execute directly on the target argument, avoiding duplicate series and variable creation.

Automatic .MAC File Includes


The SPL include statement


  #include mymac.mac

automatically processes mymac.mac as a macro file. This is useful if you wish to specifically include legacy .MAC files into your SPL code.

STARTINDEX Function Sets Array Start Index


The startindex() function sets the start index of an array for the current SPL function. For example:


  func1(a)
  {
      local i, b;

      startindex(0);
      b = 0;

      for (i = 0; i < length(a); i++) {
          b += a[i] * i;
      }
      return(b);
  }

The startindex is automatically reset to the configuration parameter SPL_START_INDEX (default 1) when the function exits. The startindex function only effects the current SPL routine, routines called by the current function are not effected. Startindex makes it easier to develop routines where a starting index other than 1 is more natural for the algorithm.

 New Functions | ActiveX Enhancements