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:
assigns the formula and data to W1 whereas:
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:
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:
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:
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.
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:
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:
but scale2 behaves as:
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:
or
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:
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:
or
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:
is more compact and equivalent to:
New @= Append Operator
The statement:
is equivalent to:
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
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.