Programmer Guide/Command Reference/EVAL: Difference between revisions

From STX Wiki
Jump to navigationJump to search
No edit summary
 
(145 intermediate revisions by 4 users not shown)
Line 1: Line 1:
{{DISPLAYTITLE:{{SUBPAGENAME}}}}__TOC__
{{DISPLAYTITLE:{{SUBPAGENAME}}}}
== Introduction ==
The <code>EVAL</code> command implements the evaluation of numerical expressions. These expressions may be built up from numerical constants, from scalar, vector, and matrix variables, and from a large number of [[#Functions|functions]] and [[#Operators|operators]].
The <code>EVAL</code> command can be used to evaluate numerical expressions. These expressions may be built up from numerical constants, from scalar, vector, and matrix variables, and from a large number of [[#Functions|functions]] and [[#Operators|operators]].


The <code>EVAL</code> command was added to the S_TOOLS-STx language in version 3.7. It replaces and extends the old <code>EVALUATE</code> command.  
The <code>EVAL</code> command was added to the {{STX}} language in version 3.7. It replaces and extends the old <code>EVALUATE</code> command.  


See also: [[Programmer Guide/Command Reference/EVALCHECK|EVALCHECK]], [[Programmer Guide/Command Reference/INT|INT]], [[Programmer Guide/Command Reference/INTCHECK|INTCHECK]],[[Programmer Guide/Command Reference/NUM|NUM]] and [[Programmer Guide/Command Reference/NUMCHECK|NUMCHECK]]
See also [[Programmer Guide/Command Reference/INT|INT]] ([[Programmer Guide/Command Reference/INTCHECK|INTCHECK]]) and [[Programmer Guide/Command Reference/NUM|NUM]] ([[Programmer Guide/Command Reference/NUMCHECK|NUMCHECK]]) for commands evaluating simpler forms of expressions.


== Syntax ==
== Syntax ==
An <code>EVAL</code> command uses the following general syntax:
=== General ===
  ''result'' ''':= eval''' ''expression''
The <code>EVAL</code> command uses the following general syntax:
  ''target'' ''':= eval''' ''expression''
or
or
  ''result'' ''':= evalcheck''' ''expression''
  ''target'' ''':= evalcheck''' ''expression''
;''result'': This is the target to be assigned with the result of the evaluation of the numerical ''expression''. The result can be a shell variable or a [[#Numerical objects|numerical object]]
;''target'': This is the target to be assigned with the result of the evaluation of the numerical ''expression''. The result can be a shell variable or a [[#Numerical objects|numerical object]].
;''expression'': The numerical expression to be evaluated. The expression consists of [[#Numerical objects|numerical objects]], [[#Functions|functions]] and [[#Operators|operators]].
;''expression'': The numerical expression to be evaluated. The expression consists of [[#Numerical objects|numerical objects]], [[#Functions|functions]] and [[#Operators|operators]].
The return value of the <code>EVAL</code> is a [[#Numerical objects|numerical object]] which is the result of the ''expression'' evaluation.


Examples:
If the evaluation fails, the return value of <code>EVAL</code> and <code>EVALCHECK</code> is the empty string (<nowiki>''</nowiki>) and the variables <var>RC</var> and <var>EMSG</var> are set to the ''numerical error code'' and ''error description''. Here <code>EVAL</code> and <code>EVALCHECK</code> differ in that <code>EVAL</code> will consider a failed evaluation an error (and treat it as such), whereas <code>EVALCHECK</code> will only return a numerical warning code in its description in <var>RC</var> and <var>EMSG</var>, respectively.
* <code>result := eval (5 * 10) % 3</code>
* <code>result := eval init(10,1,1)</code>
* <code>result := eval 5+max(fill(6,1,1))</code>


The following list shows the syntax of <code>EVAL</code> ''expression'' using the '''EBNF''' notation. The expressions are listed in the reverse order of priority (lowest first). The operators with lower priority are evaluated after that with higher priority.
=== Examples ===
result := eval (5 * 10) % 3          // remainder of 50 divided by 3
result := eval [[Programmer_Guide/Command_Reference/EVAL/init|init]](10,1,2)          // matrix of 10 rows and 1 column
                                      // (i.e., a column vector), each element set to 2
result := eval 5+[[Programmer_Guide/Command_Reference/EVAL/max|max]]([[Programmer_Guide/Command_Reference/EVAL/fill|fill]](6,1,1))


{| cellpadding="4"
=== EBNF ===
The following list shows the syntax of <code>EVAL</code> ''expression'' using the [[wikipedia:Extended_Backus%E2%80%93Naur_Form|EBNF]] notation. The expressions are listed in the reverse order of priority (lowest first). The operators with lower priority are evaluated after that with higher priority.
 
{| cellpadding="3" class="keinrahmen"
|-
|-
! assignment  
| '''assignment'''
| <pre>Value = Or [ "?" Or ":" Or ]</pre>
| <pre>Value = Or [ "?" Or ":" Or ]</pre>
|-
|-
! logical or
| '''logical or'''
| <pre>Or = And { "||" And }</pre>
| <pre>Or = And { "||" And }</pre>
|-
|-
! logical and      
| '''logical and'''
| <pre>And = Comparison { "&&" Comparison }</pre>
| <pre>And = Comparison { "&&" Comparison }</pre>
|-
|-
! comparison:       
| '''comparison'''
| <pre>Comparison = AddSub { "<" | "<=" | "==" | "!=" | ">=" | ">" AddSub }</pre>
| <pre>Comparison = AddSub { "<" | "<=" | "==" | "!=" | ">=" | ">" AddSub }</pre>
|-
|-
! add, substract   
| '''add, subtract'''
| <pre>AddSub := MulDiv { "+" | "-" MulDiv }</pre>
| <pre>AddSub = MulDiv { "+" | "-" MulDiv }</pre>
|-
|-
! multiply, divide
| '''multiply, divide'''
| <pre>MulDiv := Pwr [ "*" | "/" | "%" Pwr ]*</pre>
| <pre>MulDiv = Pwr [ "*" | "/" | "%" Pwr ]*</pre>
|-
|-
! power
| '''power'''
| <pre>Pwr := NegInv [ "^" NegInv ]</pre>
| <pre>Pwr = NegInv [ "^" NegInv ]</pre>
|-
|-
! negate, invert   
| '''negate'''
| <pre>NegInv := [ "-" | "!" ] Atom </pre>
| <pre>NegInv = [ "-" | "!" ] Atom </pre>
|-
|-
! brackets, functions,<BR>numerical objects
| '''brackets, functions,<BR>numerical objects'''
| <pre>Atom := "(" expression ")"  |  "|" expression "|" |  
| <pre>Atom = "(" expression ")"  |  "|" expression "|" |  
         functionName "(" [ expression { "," expression } ] ")" |  
         functionName "(" [ expression { "," expression } ] ")" |  
         numericalObject</pre>
         numericalObject</pre>
|}
|}


If the ''expression'' is syntactically ill-formed an error (<code>EVAL</code>) or warning (<code>EVALCHECK</code>) is reported and the assignment is not performed (content of result is not changed). See the example script <code>expression_check.sts</code> for details. You can also use the BScript console to try out the <code>EVAL</code> command.
If the ''expression'' is syntactically ill-formed an error (<code>EVAL</code>) or warning (<code>EVALCHECK</code>) is reported and the assignment is not performed (content of result is not changed). See the example script <code>expression_check.sts</code> for details. Note that a good place to try out the <code>EVAL</code> command is the [[Programmer_Guide/BScript]] console.
 
Note: The special ''bracket'' '''<nowiki>|</nowiki>''expression''<nowiki>|</nowiki>''' implements a short form to compute the absolute value of ''expression''. The result is always a number (scalar).
::*'''<nowiki>|</nowiki>''x<sub>S</sub>''<nowiki>|</nowiki>''' &rarr; the absolute value of number ''x<sub>S</sub>''
::*'''<nowiki>|</nowiki>''x<sub>V</sub>''<nowiki>|</nowiki>''' &rarr; the length of the vector ''x<sub>V</sub>''
::*'''<nowiki>|</nowiki>''x<sub>M</sub>''<nowiki>|</nowiki>''' &rarr; the determinant of the square matrix ''x<sub>M</sub>''
The functions [[Programmer Guide/Command Reference/EVAL/abs|abs(''x'')]] and [[Programmer Guide/Command Reference/EVAL/abs|det(''x'')]] can be used as aliases for '''<nowiki>|</nowiki>''expression''<nowiki>|</nowiki>'''.


==Numerical objects==
==Numerical objects==
The following numerical objects are known to the <code>EVAL</code> command. The fields of the [[Programmer_Guide/Shell_Items/Table|table item]] ''table'' are all numeric (extended table or  parameter table). The [[Programmer_Guide/Shell_Items/Value|value item]] ''value'' can contain numbers, vectors or matrices. The [[Programmer_Guide/Shell_Items/Wave|wave item]] ''wave'' is any wave item.
The following numerical objects are known to the <code>EVAL</code> command.
 
{|class="einrahmen"
{| border="1"  
|+'''numerical objects'''
|-
|-
! Syntax !! Description !! Data type
! Syntax !! Description !! Data type
|-
|-
|''constant''
|''constant''
|a scalar constant. E.g. '''4.5''' or '''4'''
|a scalar constant. Any number ('''17''', '''4.5''', '''2.5e-6''', ...) or one of the following strings:<BR>'''pi''' (3.14159...), '''e''' (2.71828...), '''true''' (1) or '''false''' (0)
|scalar
|scalar
|-
|-
Line 72: Line 81:
|vector, matrix
|vector, matrix
|-
|-
|''table''[''i'',*] or ''table''[''i'',]
|''table''[''i'',*]<BR>''table''[''i'',]
|the ''i''-th row of the table
|the ''i''-th row of the table
|scalar, vector
|scalar, vector
|-
|-
|''table''[*,''j''] or ''table''[,''j'']
|''table''[*,''j'']<BR>''table''[,''j'']
|the ''j''-th column of the table
|the ''j''-th column of the table
|scalar, vector
|scalar, vector
Line 88: Line 97:
|scalar, vector, matrix
|scalar, vector, matrix
|-
|-
|''value''[''i'',*] or ''value''[''i'',]
|''value''[''i'',*]<BR>''value''[''i'',]
|the ''i''-th row of the value item
|the ''i''-th row of the value item
|scalar, vector
|scalar, vector
|-
|-
|''value''[*,''j''] or ''value''[,''j'']
|''value''[*,''j'']<BR>''value''[,''j'']
|the ''j''-th column of the value item
|the ''j''-th column of the value item
|scalar, vector
|scalar, vector
Line 100: Line 109:
|scalar
|scalar
|-
|-
|''wave''[!signal,*] or ''wave''[!signal,]
|''wave''[!signal,*]<BR>''wave''[!signal,]
|the signal from all channels
|the signal from all channels
|vector, matrix
|vector, matrix
Line 109: Line 118:
|-
|-
|''wave[!signal,*,''b'',''l'']
|''wave[!signal,*,''b'',''l'']
|the signal from all channels from sample ''b'' (0 <= b < ''wave''[!length]) to sample ''b''+''l''-1 (l > 0)
|the signal from all channels from sample ''b'' (0 <= b < ''wave''[!length]) to sample ''b''+''l''-1 (l > 0)<BR>If ''b'' is lower than 0 or ''b''+''l'' is greater than ''wave''[!length] zero padding is applied to the result
|vector, matrix
|vector, matrix
|-
|-
Line 115: Line 124:
|the signal from channel ''ch'' from sample ''b'' to sample ''b''+''l''-1
|the signal from channel ''ch'' from sample ''b'' to sample ''b''+''l''-1
|vector
|vector
|-
|''gdxfile''[!data]
|all columns of the GDX file item
|vector, matrix
|-
|''gdxfile''[!data,''icol'',''ncol'']
|the columns of ''icol'' to ''icol''+''ncol''-1 of the GDX file item
|vector, matrix
|}
|}
*The fields of the [[Programmer_Guide/Shell_Items/Table|table item]] ''table'' are all numeric ([[Programmer_Guide/Shell_Items/Table/Introducing_Table_Items#Extended_Table|extended table]] or [[Programmer_Guide/Shell_Items/Table/Introducing_Table_Items#Parameter_Table|parameter table]]).
*The [[Programmer_Guide/Shell_Items/Value|value item]] ''value'' can contain numbers, vectors or matrices.
*The [[Programmer_Guide/Shell_Items/Wave|wave item]] ''wave'' is any wave item. It must address a (part of a) soundfile if ''wave'' is used as target.
*The [[Programmer_Guide/Shell_Items/File|file item]] ''gdxfile'' must be of type '''GDX'''. This is a special form of the binary files, which can be used as numerical object and can also be connected to an input of a [[Programmer_Guide/Shell_Items/Graph|graph item]]. A '''GDX''' file item may contain one vector or one matrix.


====row  and column vectors====
:In {{STX}} it is not possible to differentiate between ''row vectors'' and ''column vectors''. Normally a vector is a row vector, but it depends on the context (the operator or function used) which type of vector is supposed.


Notes:
====complex numbers====
* ''wave'': If ''b'' is lower than 0 or ''b''+''l'' is greater than ''wave''[!length] zero padding is applied to the result
:The current versions of {{STX}} do not implement the datatype ''complex'', but a lot of functions take ''complex'' arguments and/or return ''complex'' results. Therefore the following convention for numerical objects holding complex numbers is used:
:*'''complex number''': A vector with two elements. If the number is stored in the cartesian format, the first element is the ''real part'' and the second the ''imaginary part''. If it is stored in polar format, the first element is the ''magnitude'' (or ''length'') and the second the ''phase''.
:*'''complex vector''': A vector of '''N''' complex numbers consists of '''2N''' elements. The element '''2i''' is the real part (or magnitude) and the element '''2i+1''' is the imaginary part (or phase) of the '''i-th''' complex number ('''i = 0..N-1''').
:*'''complex matrix''': A matrix of '''N x M''' complex numbers consists of '''2N''' rows and '''M'''. Each row is formatted like a complex vector described above.
:The <code>EVAL</code> implements a set of functions for [[Programmer_Guide/Command_Reference/EVAL/complex arithmetic|complex arithmetic and special handling of complex numbers]].


====polygons====
:The <code>EVAL</code> command implements a set of functions to manipulate 2-dimensional polygons. These functions are using specially formatted matrices to store information about one or more polygons. Some examples for the use of polygon functions and data types can be found in the example script '''scripts\examples\polygon_examples.sts'''.
:;closed point-list (''pg_cplist''): Is a list of '''N''' points '''P<sub>i</sub>''' in a 2-dimensional plane. Each pair '''(P<sub>i</sub> , P<sub>i+1</sub>)''' builds one edge of a polygon. The list is called closed, because P<sub>N-1</sub> is connected to P<sub>0</sub>. A ''pg_cplist'' is stored in a matrix ''PL'' with '''N''' rows and 2 columns. The coordinates of point P<sub>i</sub> are stored in ''PL''[''i'',0] (x<sub>i</sub>) and ''PL''[''i'',1] (y<sub>i</sub>).
:;simple-polygon (''pg_simple''): Is a closed point-list (''pg_cplist'') defining a polygon without crossing edges.
:;polygon-stream (''pg_stream''): Is a packed format to store the point-list and some additional information for one or more simple-polygons. This format is created by the [[Programmer_Guide/Command_Reference/EVAL/pginit|initialisation function]] and used as argument and/or result by the most other polynom processing functions. A ''pg_stream'' is stored in a matrix with 2 columns and '''8M+N<sub>0</sub>+..+N<sub>M-1</sub>''' rows, where M means the number of polynoms stored in the stream and N<sub>i</sub> the number of points of the i-th polynom. The data for the i-th polygon are stored in the matrix in the following format:
::{| class="einrahmen"
|-
! row<BR>index !! value of<BR>column 0 !! value of<BR>column 1 !! comment
|-
| '''o<sub>i</sub>+0'''
| N<sub>i</sub>: number of points
| reserved (set to '''0''')
|
|-
| '''o<sub>i</sub>+1'''
| IX<sub>i</sub>: the index of the leftmost/lowest point (used for computations ''y=f(x)'')
| IY<sub>i</sub>: the index of the lowest/leftmost point (used for computations ''x=f(y)'')
|
|-
| '''o<sub>i</sub>+2'''
| XMIN<sub>i</sub>: minimum x of all points
| YMIN<sub>i</sub>: minimum y of all points
| The point (XMIN<sub>i</sub>,YMIN<sub>i</sub>) is the lower left corner of the bounding rectangle
|-
| '''o<sub>i</sub>+3'''
| XMAX<sub>i</sub>: maximum x of all points
| YMAX<sub>i</sub>: maximum y of all points
| The point (XMAX<sub>i</sub>,YMAX<sub>i</sub>) is the upper right corner of the bounding rectangle
|-
| '''o<sub>i</sub>+4'''
| XC<sub>i</sub>: x value of the center of gravity
| YC<sub>i</sub>: y value of the center of gravity
| The point (XC<sub>i</sub>,YC<sub>i</sub>) is the center of gravity of the polygon
|-
| '''o<sub>i</sub>+5'''
| A<sub>i</sub>: area
| L<sub>i</sub>: circumference
|
|-
| '''o<sub>i</sub>+6'''
| '''1''' if the center of gravity is inside the polygon,<BR>'''0''' otherwise
| '''1''' if the polygon is convex,<BR>'''0''' otherwise
|
|-
| '''o<sub>i</sub>+7'''
| reserved (set to '''0''')
| reserved (set to '''0''')
|
|-
| '''o<sub>i</sub>+8<BR>..<BR>o<sub>i</sub>+N<sub>i</sub>-1'''
| x values of points
| y values of points
| the coordinates of the points (corners) of the (simple) polygon
|}
::with: o<sub>i</sub> is the first row index of the i-th polynum; o<sub>0</sub>=0, o<sub>i</sub>=o<sub>i-1</sub>+8+N<sub>i-1</sub> (i = 1..M-1)


==Operators==
==Operators==


===Numerical operators===


{| border="1" cellpadding="2"
{| class="einrahmen"
|+'''numerical operators'''
|-
|-
! Symbol !! Syntax !! Description !! Datatype of<BR>Result
! Syntax !! Description !! Data type of<BR>Result
|-
|-
!<nowiki>-</nowiki>
|<nowiki>-</nowiki>''x''
|<nowiki>-</nowiki>''x''
|Negate all elements of ''x''.
|Negate all elements of ''x''.
|same as ''x''
|same as ''x''
|-
|-
!<nowiki>+</nowiki>
|''y''+''x''<sub>S</sub><BR>''x''<sub>S</sub>+''y''
|''y''+''x''<sub>S</sub> or ''x''<sub>S</sub>+''y''
|Add the scalar ''x''<sub>S</sub>'' to all elements of ''y''.
|Add the scalar ''x''<sub>S</sub>'' to all elements of ''y''.
|same as ''y''
|same as ''y''
|-
|-
!<nowiki>+</nowiki>
|''x''+''y''
|''x''+''y''
|Add elements of ''x'' to the elements of ''y''. Both operands must be of the same type.
|Add elements of ''x'' to the elements of ''y''. Both operands must be of the same type.
|same as ''x'' and ''y''
|same as ''x'' and ''y''
|-
|-
!<nowiki>-</nowiki>
|''y''-''x''<sub>S</sub>
|''y''-''x''<sub>S</sub>
|Subtract the scalar ''x''<sub>S</sub> from each element in ''y''.
|Subtract the scalar ''x''<sub>S</sub> from each element in ''y''.
|same as ''y''
|same as ''y''
|-
|-
!<nowiki>-</nowiki>
|''x''<sub>S</sub>–''y''
|''x''<sub>S</sub>–''y''
|Subtract all elements of ''y'' from the scalar ''x''<sub>S</sub>.
|Subtract all elements of ''y'' from the scalar ''x''<sub>S</sub>.
|same as ''y''
|same as ''y''
|-
|-
!<nowiki>-</nowiki>
|''x''-''y''
|''x''-''y''
|Subtract elements of ''x'' from the elements of ''y''. Both operands must be of the same type.
|Subtract elements of ''x'' from the elements of ''y''. Both operands must be of the same type.
|same as ''x'' and ''y''
|same as ''x'' and ''y''
|-
|-
!<nowiki>*</nowiki>
|''y''*''x''<sub>S</sub><BR>''x''<sub>S</sub>*''y''
|''y''*''x''<sub>S</sub> or ''x''<sub>S</sub>*''y''
|Multiply all elements of ''y'' with the scalar ''x''<sub>S</sub>.
|Multiply all elements of ''y'' with the scalar ''x''<sub>S</sub>.
|same as ''y''
|same as ''y''
|-
|-
!<nowiki>*</nowiki>
|''x''<sub>V</sub>*''y''<sub>V</sub>
|''x''<sub>V</sub>*''y''<sub>V</sub>
|The inner (or dot) product of the vectors ''x''<sub>V</sub> and ''y''<sub>V</sub>. The length of both vectors must be the same.
|The inner (or dot) product of the vectors ''x''<sub>V</sub> and ''y''<sub>V</sub>. The length of both vectors must be the same.
|scalar
|scalar
|-
|-
!<nowiki>*</nowiki>
|''x''<sub>M</sub>*''y''<sub>V</sub>
|''x''<sub>M</sub>*''y''<sub>V</sub>
|The product of the matrix ''x''<sub>M</sub> and the vector ''y''<sub>V</sub>. The length of the vector ''y''<sub>V</sub> must be the same as the number of columns in the matrix ''x''<sub>M</sub>.
|The product of the matrix ''x''<sub>M</sub> and the vector ''y''<sub>V</sub>. The length of the vector ''y''<sub>V</sub> must be the same as the number of columns in the matrix ''x''<sub>M</sub>.
|vector with '''nrow(''x''<sub>M</sub>)''' elements
|vector with '''nrow(''x''<sub>M</sub>)''' elements
|-
|-
!<nowiki>*</nowiki>
|''x''<sub>M</sub>*''y''<sub>M</sub>
|''x''<sub>M</sub>*''y''<sub>M</sub>
|The product of the matrix ''x''<sub>M</sub> and ''y''<sub>M</sub>. The number of rows in ''y''<sub>M</sub> must be equal to the number of columns in ''x''<sub>M</sub>.
|The product of the matrix ''x''<sub>M</sub> and ''y''<sub>M</sub>. The number of rows in ''y''<sub>M</sub> must be equal to the number of columns in ''x''<sub>M</sub>.
|matrix with '''nrow(''x''<sub>M</sub>)''' rows and '''ncol(''y''<sub>M</sub>))''' columns
|matrix with '''nrow(''x''<sub>M</sub>)''' rows and '''ncol(''y''<sub>M</sub>))''' columns
|-
|-
!<nowiki>/</nowiki>
|''y''/''x''<sub>S</sub>
|''y''/''x''<sub>S</sub>
|Divide all elements of y through the scalar xS. The value of ''x''<sub>M</sub> may not be 0.
|Divide all elements of y through the scalar xS. The value of ''x''<sub>M</sub> may not be 0.
|same as ''y''
|same as ''y''
|-
|-
!<nowiki>/</nowiki>
|''x''<sub>S</sub>/''y''<sub>M</sub>
|''x''<sub>S</sub>/''y''<sub>M</sub>
|Multiply all elements of the inverse matrix of ''y''<sub>M</sub> with the scalar ''x''<sub>S</sub>. The matrix ''y''<sub>M</sub>must be a square matrix.The special case '''1/''y''<sub>M</sub>''' returns the inverse matrix. Note that the function inv(''y'') can also be used to invert scalars and matrices.
|Multiply all elements of the inverse matrix of ''y''<sub>M</sub> with the scalar ''x''<sub>S</sub>. The matrix ''y''<sub>M</sub>must be a square matrix.The special case '''1/''y''<sub>M</sub>''' returns the inverse matrix. Note that the function [[Programmer_Guide/Command_Reference/EVAL/inv|inv(''y'')]] can also be used to invert scalars and matrices.
|same as ''y''<sub>M</sub>
|same as ''y''<sub>M</sub>
|-
|-
!<nowiki>%</nowiki>
|''y''%''x''<sub>S</sub>
|''y''%''x''<sub>S</sub>
|The rest of the division of every element in ''y'' through the scalar ''x''<sub>S</sub> (modulo)
|The rest of the division of every element in ''y'' through the scalar ''x''<sub>S</sub> (modulo)
|same as y
|same as y
|-
|-
!<nowiki>^</nowiki>
|''y''^''x''<sub>S</sub>
|''y''^''x''<sub>S</sub>
|Raise every element of ''y'' to the power of the scalar xS.<BR>Special cases: <code>''y''^-1</code> is calculated like <code>1/''y''</code> and <code>''y''^2</code> is calculated like this <code>''y''*''y''</code>
|Raise every element of ''y'' to the power of the scalar xS.<BR>Special cases: <code>''y''^-1</code> is calculated like <code>1/''y''</code> and <code>''y''^2</code> is calculated like this <code>''y''*''y''</code>
Line 201: Line 273:
|}
|}


Notes:
If one of the numerical operands has the prefix ''?'' then the operation is carried out element per element. Example:
* If one of the binary operands has the prefix ''?'' (e.g. ''?*'') then the operation is carried out element per element.
<pre>#dotprod := eval $#x * $#y // dot product of vectors #x and #y
 
#winsig := eval $#x ?* $#y // multiply elements of #x and #y (e.g. to apply signal windowing)</pre>
===Comparison operators, Logical operators===
 
The comparison and logical operators can be used to build logical expressions.
 
The result of a comparison of two numerical expressions is (logical) ''true'' (numerical ''1''), if the condition is fulfilled, otherwise it is (logical) ''false'' (numerical ''0''). Normally it make only sense to compare scalars or, more generally, numerical objects with equal dimensions. The following rules applies to a comparison:
:* The numerical objects ''x'' and ''y''' are '''equal''' (''x''==''y'' is true), if (and only if) the dimensions of ''x'' and ''y'' are the same '''and''' all pairs of elements (''x''<sub>i,j</sub>,''y''<sub>i,j</sub>) are numerically equal.
:* The numerical objects ''x'' and ''y'' are ''not equal'' (''x''!=''y'' is true), if the dimensions of ''x'' and ''y'' are different ''or'' at least one element pair (''x''<sub>i,j</sub>,''y''<sub>i,j</sub>) is numerically not equal.
:* For all other comparisons the dimensions of ''x'' and ''y'' must be the same, otherwise the comparison failes. The result is true, if the condition is fulfilled for all pairs of elements (''x''<sub>i,j</sub>,''y''<sub>i,j</sub>).
 


{| border="1" cellpadding="2"
===Comparison operators===
|+'''comparison operators'''
{| class="einrahmen"
|-
|-
! Symbol !! Syntax !! Description   
! Syntax !! Description   
|-
|-
!<nowiki><</nowiki>
|''x''<''y''
|''x''<''y''
|''x'' '''less''' than ''y''
|''x'' '''less''' than ''y''
|-
|-
!<nowiki>></nowiki>
|''x''>''y''
|''x''>''y''
|''x'' '''greater''' than ''y''
|''x'' '''greater''' than ''y''
|-
|-
!<nowiki><=</nowiki>
|''x''<=''y''
|''x''<=''y''
|''x'' '''less than'' or '''equal''' to ''y''
|''x'' '''less than''' or '''equal''' to ''y''
|-
|-
!<nowiki>>=</nowiki>
|''x''>=''y''
|''x''>=''y''
|''x'' '''greater than''' or '''equal''' to ''y''
|''x'' '''greater than''' or '''equal''' to ''y''
|-
|-
!<nowiki>==</nowiki>
|''x''==''y''
|''x''==''y''
|''x'' '''equal''' to ''y''.  
|''x'' '''equal''' to ''y''.  
|-
|-
!<nowiki>!=</nowiki>
|''x''!=''y''
|''x''!=''y''
|''x'' '''not equal''' to ''y''.  
|''x'' '''not equal''' to ''y''.  
|}
|}


The result of a comparison of two numerical expressions is (logical) '''true''' (numerical '''1'''), if the condition is fulfilled, otherwise it is (logical) '''false''' (numerical '''0'''). Normally it make only sense to compare scalars or, more generally, numerical objects with equal dimensions. The following rules applies to a comparison:
:* The numerical objects ''x'' and ''y'' are '''equal''' (''x''==''y'' is true), if (and only if) the dimensions of ''x'' and ''y'' are the same '''and''' all pairs of elements <code>(''x''<sub>i,j</sub> , ''y''<sub>i,j</sub>)</code> are numerically equal.
:* The numerical objects ''x'' and ''y'' are '''not equal''' (''x''!=''y'' is true), if the dimensions of ''x'' and ''y'' are different '''or''' at least one element pair <code>(''x''<sub>i,j</sub> , ''y''<sub>i,j</sub>)</code> is numerically not equal.
:* For all other comparisons the dimensions of ''x'' and ''y'' must be the same, otherwise the comparison failes. The result is true, if the condition is fulfilled for all pairs of elements <code>(''x''<sub>i,j</sub> , ''y''<sub>i,j</sub>)</code>.


*In most cases it make no sense to mix numerical and logical expressions.
===Logical operators===
*The logical value of a numerical object is true
 
 
The result of a logical expression is a logical (boolean) value. The following rules are used to convert logical to numerical values and vice versa:
The numerical result of a logical expression is the value ...
:*''1'' if the logical expression is ''true''
:*''0'' if the logical expression is ''false''
The logical value of a numerical object (or expression) is ...
:*''true'' if one of its elements is not equal to zero.
:*''false'' if all of its elements are equal to zero.


 
{| class="einrahmen"
{| border="1" cellpadding="2"
|+'''logical operators'''
|-
|-
! Symbol !! Syntax !! Description
! Syntax !! Description
|-
|-
!<nowiki>||</nowiki>
|''x''<nowiki>||</nowiki>''y''
|''x''<nowiki>||</nowiki>''y''
|logical or
|logical or
|-
|-
!<nowiki>&&</nowiki>
|''x''<nowiki>&&</nowiki>''y''
|''x''<nowiki>&&</nowiki>''y''
|logical and
|logical and
|-
|-
!<nowiki>!</nowiki>
|<nowiki>!</nowiki>''x''
|<nowiki>!</nowiki>''x''
|unary not
|unary not
|}
|}


The result of a logical operation is '''true''' (numerical '''1''') or '''false''' (numerical '''0'''). The arguments ''x'' and ''y'' can be any numerical type. It is also possible to use arguments with different types. The following rules are used to convert logical (boolean) to numerical values and vice versa:
The numerical result of a logical operation is the value ...
:*'''1''' if the logical expression is '''true'''
:*'''0''' if the logical expression is '''false'''
The logical value of a numerical object (or expression) is ...
:*'''true''' if one of its elements is '''not equal to 0'''.
:*'''false''' if all of its elements are '''equal to 0'''.


===Selection operator===
===Selection operator===
The selection operator used in <code>EVAL</code> expressions works similar to the [[Programmer_Guide/Command_Reference/COND|COND command]].


  ''log_expr'' '''?''' ''true_expr'' ''':''' ''false_expr''
  ''log_expr'' '''?''' ''true_expr'' ''':''' ''false_expr''
Line 285: Line 340:
;''true_expr'': This expression is evaluated and returned as result of the selection operator, if ''log_expr'' is '''false'''.
;''true_expr'': This expression is evaluated and returned as result of the selection operator, if ''log_expr'' is '''false'''.


If the selection operator is nested, it must be surrounded by brackets, e.g.:
In contrast to the [[Programmer_Guide/Command_Reference/COND|COND command]], the selection operator of the <code>EVAL</code> command can be nested, but must be surrounded by brackets, e.g.:
  result := eval 1 > 2 ? (5 == 5 ? 5 : 0) : (4 == 5 ? 3 : 4) // result is 4
  result := eval 1 > 2 ? (5 == 5 ? 5 : 0) : (4 == 5 ? 3 : 4) // result is 4


 
==Functions==
==Functions===
<!-- A.N.: Bei ändern/hinzufügen der Dokumentation einer EVAL Funktion bitte hier richtiges Datum setzen -->
latest update: March 2, 2015 (J.W.)
<!-- J.W.: added f0sp documentation (direct from cpp source file) -->
<!-- A.N.:
Die Beschreibung der EVAL Funktionen entspricht dem aktuellen Stand.
Es fehlen nur die folgenden Funktionen, die auch in der Freeware Version nicht enthalten sind:
    mbbm1:  Korrektur von Drehfehlern bei Zahnrädern
            siehe: kfslib\cogECorr.*
    mbbm2:  Synchronisation von Teilmessungen im Zeitbereich
            siehe: kfsatom\VATDS*.*
    mbbm3:  Cohen Class Implementierung (PWD, SPWD, CWD)
            siehe: kfsatom\wl*.* (Wavelets) und kfsatom\cc*.* (Cohen Class)
    zffunc1: Beurteilung von Getriebegeräuschen
            siehe: kfslib\ZF*.doc, kfslib\TM*.doc
-->
<splist
<splist
parent=Programmer_Guide/Command_Reference/EVAL
parent=Programmer_Guide/Command_Reference/EVAL
Line 297: Line 366:
liststyle=bar
liststyle=bar
kidsonly=yes
kidsonly=yes
></splist>  <!-- C.G. 22.3.2011 -->
></splist>
 
==Examples==
The result of the evaluation returned to the script is a number, vector or matrix. Numbers are returned in a ''string'' format (as usual in {{STX}}), and vectors or matrices are stored and returned in a temporary (local) parameter table. The return value may be assigned to a variable, a shell item or an addressed part of a shell item. The following examples show some possible assignments.
 
Assign to a '''variable''': Only the returned string - the value of the number or name of the temporary table - is stored.
#x := eval [[Programmer_Guide/Command_Reference/EVAL/rand|rand]](0,100)    // generate a vector with 100 pseudo random numbers in the range -1 to 1
                            // the name of the returned temporary table is assigned to the variable #x
#y := eval $#x * (1 - $#x) // compute the dot-product of 2 vectors
                            // the returned number is assigned to variable #y
 
=== Assigning to a table item ===
Assign to a [[Programmer_Guide/Shell_Items/Table|table item]]: Both the content and the definition of the table is replaced by the content and definition of the result item.
// the following code is often used to assign an eval result to a permanent item
#x := new table *          // create a dummy simple table
$#x := eval [[Programmer_Guide/Command_Reference/EVAL/rand|rand]](0,100)    // overwrite the dummy table with the result of the evaluation
// for those prefering compact code: the following line is equivalent to the above code
$(#x := new table *) := eval [[Programmer_Guide/Command_Reference/EVAL/rand|rand]](0,100)
 
// the number of table columns is fixed (defined in the NEW command)
// the number of table rows is variable:
#y := new table * * num:x:50 /param    // create a parameter table with 50 columns (x0 .. x49)
$#y[3,*] := eval [[Programmer_Guide/Command_Reference/EVAL/fill|fill]]($#y[!ncol],1,50)  // assign a vector to row 3, the rows 0 to 2 are
                                        // automatically created and filled with zeros
$#y[$#y[!nrow]+1,*] := eval &hellip;          // append a row to a table
 
=== Assigning to a value item ===
Assign to a [[Programmer_Guide/Shell_Items/Value|value item]]: The data stored in the value item is replaced by the result. The timer configuration of the value item is not changed.
// create a value item
#x := new value *
// assign a vector to the value item
$#x := eval [[Programmer_Guide/Command_Reference/EVAL/fill|fill]](10,0,1)
[[Programmer_Guide/Macro_Library/StdLib#ConLog|conlog]] 'attributes: $#x[!type], $#x[!data]' // output: 'attributes: Vector, 10'
// assign a number to the value item
$#x := eval [[Programmer_Guide/Command_Reference/EVAL/sum|sum]]($#x)
[[Programmer_Guide/Macro_Library/StdLib#ConLog|conlog]] 'attributes: $#x[!type], $#x[!data]' // output: 'attributes: Number, 45'
// assign a string to the value item
$#x := set 'sum(x)'
[[Programmer_Guide/Macro_Library/StdLib#ConLog|conlog]] 'attributes: $#x[!type], $#x[!data]' // output: 'attributes: String, sum(x)'
 
=== Assigning to a matrix row or column ===
Assign to a '''row''' or '''column''' of a matrix. Matrices are stored in table or value items.
#x := eval [[Programmer_Guide/Command_Reference/EVAL/init|init]](20,20,0)      // create a 20x20 matrix
$#x[0,] := eval [[Programmer_Guide/Command_Reference/EVAL/fill|fill]](20,0,1)  // replace row 0 of the matrix
$#x[,1] := eval [[Programmer_Guide/Command_Reference/EVAL/fill|fill]](20,0,1)  // replace column 1 of the matrix
$#x[,2] := eval [[Programmer_Guide/Command_Reference/EVAL/fill|fill]](100,0,1)  // error: the vector is to long!
$#x[2,] := eval [[Programmer_Guide/Command_Reference/EVAL/fill|fill]](5,0,1)    // error: the vector is to short!
 
=== Assigning to an entry of a matrix, or a vector ===
Assign to an '''element''' (i.e., a cell, i.e., a field) of an item:
  #x := new table * * str:a num:b // create a table with a string field a numeric field
$#x[0,a] := eval [[Programmer_Guide/Command_Reference/EVAL/fill|fill]](10,1,1)  // the fill command returns a vector (temp. table),
                                // the id of the returned item is assigned to the cell
$#x[0,b] := eval [[Programmer_Guide/Command_Reference/EVAL/fill|fill]](10,1,1)  // error: a string can not be assigned to a numeric field!
$#x[0,b] := eval [[Programmer_Guide/Command_Reference/EVAL/sum|sum]]($#x[0,b])  // okay: the sum is assigned to the cell
 
=== Storing a signal in a wave item ===
Store signal in a [[Programmer_Guide/Shell_Items/Wave|wave item]].
// create a soundfile (32kHz, stereo, 24bit) and store a 1s tone (440Hz, 880Hz)
// in channel 1 and a 1s noise in channel 2
 
// create the soundfile and the wave item
bsf open $@work\testtone.wav; create; 32000; 2; pcm24; wave
#x := new wave * 0_1s
 
// initialize both channels
// the number of samples stored in x equals the length of the assigned vectors
$#x[!signal,1,0] := eval [[Programmer_Guide/Command_Reference/EVAL/fill|fill]]($#x[!length],0,2*pi*440/$#x[!srate])/2
$#x[!signal,2,0] := eval [[Programmer_Guide/Command_Reference/EVAL/rand|rand]](0,$#x[!length],1) / 4
 
// its also possible to assign a matrix to a wave item
// number of columns  = must be equal to the number of channels
// number of rows    = number of samples to be written
#matrix := eval init(10000, 2, 0)
$#matrix[*,0] := [[Programmer_Guide/Command_Reference/EVAL/fill|fill]]($#matrix[!length],0,2*pi*880/$#x[!srate])/2
$#matrix[*,1] := [[Programmer_Guide/Command_Reference/EVAL/fill|fill]]($#matrix[!length],0,2*pi*660/$#x[!srate])/2
$#x[!signal,*,10000] := $#matrix
 
// the signal of a wave item can be modified (e.g. ramp)
$#x[!signal,1,0] := eval $#x[!signal,1,0,1000] ?* [[Programmer_Guide/Command_Reference/EVAL/fill|fill]](1000,0,1/1000)
 
// now you can play the generated signal
playwave $#x ; Signal generation test!
delete $#x
bsf close $@work\testtone.wav
 
===Using GDX files===
[[Programmer_Guide/Shell_Items/File|GDX file items]] are special binary files which can be used directly in a numerical expression and which can also be connected to an input of a [[Programmer_Guide/Shell_Items/Graph|graph item]]. One matrix can be stored per GDX file.
 
[macro computeSpectrogram #wave #len=1024 #hop=256]
// Compute a spectrogram and store it in a GDX file
// Args:  #wave      a mono wave item
//        #len, #hop  the analysis window length and the hopsize in samples
// Result: the path of the GDX file containing the spectrogram
//---
    #path := [[Programmer_Guide/Command_Reference/UNIQUE|unique]] '$@work' gdx 1 8        // get unique output file name
    #lfft := eval [[Programmer_Guide/Command_Reference/EVAL/fft|fft]]($#len)                // compute transformation length
    #nfrm := int $#wave[!length] / $#hop    // compute number of frames
    #file := [[Programmer_Guide/Shell_Items/File/NEW_FILE|new file]] * '$#path' 4 $#nfrm $(int $#lfft/2+1) // create GDX file
    // compute and save one log. amplitude spectrum / frame
    for #i := 0 to $#i < $#nfrm step #i := int $#i+1
        #pos := int $#i * $#hop - $#len/2
        $#file[!data,$#i] := eval [[Programmer_Guide/Command_Reference/EVAL/fft|fft]]($#wave[!signal,1,$#pos,$#len] ?* whanning($#len) , $#lfft, 4)
    end
    delete /Var #file  // close the file
    exit 1 set '$#path'
 
[macro computeAvrPowerspectrum #path]
// Compute the average powerspectrum of a spectrogram stored in a GDX file
// Args:  #path      the path of the GDX file containing the spectrogram
// Result: the average log. powerspectrum (a temp. numeric table item)
//---
    #file := [[Programmer_Guide/Shell_Items/File/NEW_FILE|new file]] * '$#path' // open GDX file
    // compute average spectrum
    #avr := eval [[Programmer_Guide/Command_Reference/EVAL/fill|fill]]($#file[!nrow],0,0)
    for #i := 0 to $#i < $#file[!ncol] step #i := int $#i+1
        $#avr := eval $#avr + [[Programmer_Guide/Command_Reference/EVAL/log2lin|log2lin]]($#file[!data,$#i,1], 1, 10) / $#file[!ncol]
    end
    delete /Var #file  // close the file
    exit 1 eval [[Programmer_Guide/Command_Reference/EVAL/lin2log|lin2log]]($#avr, 1, 20)
 
=== Script examples ===
The following script shows some examples how to use the <code>EVAL</code> command.  
[Macro eval_example]
// force this macro to be run in the debugger
message debug on
message debug init /Step
// note: use the script debugger to view the results
// assign constants
#a := 0
#b := 1
#c := 2
#d := 3
// simple numerical expressions
#e1 := eval $#d*$#c+$#b
#e2 := eval $#b+$#d*$#c
#e3 := eval $#d*($#c+$#b)
// simple logical expressions
#c1 := eval $#a || $#b || $#c
#c2 := eval $#a && $#b && $#c
#c3 := eval $#a && $#b || $#c
#c4 := eval $#c || $#a && $#b
#c5 := eval ($#c || $#a) && $#b
#c6 := eval ! $#a || ! $#b
#c7 := eval ! $#a && ! $#b
// compare numbers
#c1 := eval $#a > $#b
#c2 := eval $#a >= $#b
#c3 := eval $#a < $#b
#c4 := eval $#a <= $#b
#c5 := eval $#a == $#b
#c6 := eval $#a != $#b
// selection operator (conditional assignment)
#c1 := eval $#a < $#b ? $#a+$#b : $#a-$#b
#c2 := eval $#a > $#b ? $#a+$#b : $#a-$#b
#c3 := eval $#a == $#b ? $#a+$#b : $#a-$#b
#c4 := eval $#a != $#b ? $#a+$#b : $#a-$#b
// nested "? :" statements may be hard to read
#c := eval $#a > $#b ? ($#a == $#b ? 1 : 2) : ($#a == $#b ? 3 : 4)
// ...especially if you leave out readability blanks...
#c := eval $#a>$#b?($#a==$#b?1:2):($#a==$#b?3:4)
// using "? :" to select a function argument
#c1 := eval [[Programmer_Guide/Command_Reference/EVAL/sin|sin]]( $#a > $#b ? $#a : $#b )
#c2 := eval [[Programmer_Guide/Command_Reference/EVAL/sin|sin]]( $#a < $#b ? $#a : $#b )
// initialize vectors
#v1 := eval [[Programmer_Guide/Command_Reference/EVAL/fill|fill]]( 10, 0.1, 0.2 ) // ten elements
#v2 := eval [[Programmer_Guide/Command_Reference/EVAL/fill|fill]]( 10, 0.2, 0.1 )  // also ten elements
#v3 := eval [[Programmer_Guide/Command_Reference/EVAL/fill|fill]]( 5,  0.2, 0.1 ) // only five elements
// ten elements each of which is larger than the corresponding element in #v1
#v4 := eval $#v1 + 1
// compare vectors
#c1 := eval $#v1 == $#v2
#c2 := eval $#v1 != $#v2
#c3 := eval $#v1 >  $#v2
#c4 := eval $#v1 <  $#v2
#c5 := eval $#v1 >  $#v4
#c6 := eval $#v1 <  $#v4
// the "element-wise" operator
#x1 := eval $#v4 ^  2 // normal operation
#x2 := eval $#v4 ?^ 2 // element-wise operation
// vectors of different size are trivially unequal
#c1 := eval $#v1 == $#v3
#c2 := eval $#v1 != $#v3
// illegal comparisons due to different size
#c3 := eval $#v1 < $#v3 // illegal!
#c4 := eval $#v1 > $#v3 // illegal!
// replace the vector v1
$#v1 := eval [[Programmer_Guide/Command_Reference/EVAL/fill|fill]]( 11, -5, 1 )
// limit all values to be >= -1 and <= 2
$#v2 := eval [[Programmer_Guide/Command_Reference/EVAL/limit|limit]]( $#v1, -2, 2 )
// set lowest bound only
$#v2 := eval [[Programmer_Guide/Command_Reference/EVAL/limit|limitLow]]( $#v1, -2 )
// set highest bound only
$#v2 := eval [[Programmer_Guide/Command_Reference/EVAL/limit|limitHigh]]( $#v1, 2 )
// this works with a number (as opposed to vectors and matrices), too
#c1 := 123.5
#c2 := eval [[Programmer_Guide/Command_Reference/EVAL/limit|limit]]($#c1,0,100)
#c2 := eval [[Programmer_Guide/Command_Reference/EVAL/limit|limitLow]]( $#c1, 100 )
#c2 := eval [[Programmer_Guide/Command_Reference/EVAL/limit|limitHigh]]( $#c1, 100 )
// pick out the smallest/largest value from vec1, vec2 and a number of numbers
#min := eval [[Programmer_Guide/Command_Reference/EVAL/min|min]]($#v1, $#v2, 100, 20)
#max := eval [[Programmer_Guide/Command_Reference/EVAL/max|max]]($#v1,$#v2, 100, 20)
// merge vectors and numbers
$#v3 := eval [[Programmer_Guide/Command_Reference/EVAL/vv|vv]]($#v1, $#c1, $#v2, $#c2)


== Examples ==
In the directory '''scripts\examples''' of the {{STX}} installation, you can find a lot of script files using <code>EVAL</code> for differnt purposes (dsp_examples.sts, eval_example.sts, expression_checks.sts, matrix_algebra_examples.sts, parameter_table_example.sts, plot_sample.sts, polygon_examples.sts, ...)
For an extensive list of examples, see the script <code>eval_examples.sts</code>:
{{:Programmer_Guide/Command_Reference/EVAL_Examples/EVAL_Examples}}  <!-- C.G. 22.3.2011 -->

Latest revision as of 14:12, 2 March 2015

The EVAL command implements the evaluation of numerical expressions. These expressions may be built up from numerical constants, from scalar, vector, and matrix variables, and from a large number of functions and operators.

The EVAL command was added to the STx language in version 3.7. It replaces and extends the old EVALUATE command.

See also INT (INTCHECK) and NUM (NUMCHECK) for commands evaluating simpler forms of expressions.

Syntax

General

The EVAL command uses the following general syntax:

target := eval expression

or

target := evalcheck expression
target
This is the target to be assigned with the result of the evaluation of the numerical expression. The result can be a shell variable or a numerical object.
expression
The numerical expression to be evaluated. The expression consists of numerical objects, functions and operators.

The return value of the EVAL is a numerical object which is the result of the expression evaluation.

If the evaluation fails, the return value of EVAL and EVALCHECK is the empty string ('') and the variables RC and EMSG are set to the numerical error code and error description. Here EVAL and EVALCHECK differ in that EVAL will consider a failed evaluation an error (and treat it as such), whereas EVALCHECK will only return a numerical warning code in its description in RC and EMSG, respectively.

Examples

result := eval (5 * 10) % 3          // remainder of 50 divided by 3
result := eval init(10,1,2)          // matrix of 10 rows and 1 column
                                     // (i.e., a column vector), each element set to 2
result := eval 5+max(fill(6,1,1))

EBNF

The following list shows the syntax of EVAL expression using the EBNF notation. The expressions are listed in the reverse order of priority (lowest first). The operators with lower priority are evaluated after that with higher priority.

assignment
Value = Or [ "?" Or ":" Or ]
logical or
Or = And { "||" And }
logical and
And = Comparison { "&&" Comparison }
comparison
Comparison = AddSub { "<" | "<=" | "==" | "!=" | ">=" | ">" AddSub }
add, subtract
AddSub = MulDiv { "+" | "-" MulDiv }
multiply, divide
MulDiv = Pwr [ "*" | "/" | "%" Pwr ]*
power
Pwr = NegInv [ "^" NegInv ]
negate
NegInv = [ "-" | "!" ] Atom 
brackets, functions,
numerical objects
Atom = "(" expression ")"  |  "|" expression "|" | 
        functionName "(" [ expression { "," expression } ] ")" | 
        numericalObject

If the expression is syntactically ill-formed an error (EVAL) or warning (EVALCHECK) is reported and the assignment is not performed (content of result is not changed). See the example script expression_check.sts for details. Note that a good place to try out the EVAL command is the Programmer_Guide/BScript console.

Note: The special bracket |expression| implements a short form to compute the absolute value of expression. The result is always a number (scalar).

  • |xS| → the absolute value of number xS
  • |xV| → the length of the vector xV
  • |xM| → the determinant of the square matrix xM

The functions abs(x) and det(x) can be used as aliases for |expression|.

Numerical objects

The following numerical objects are known to the EVAL command.

Syntax Description Data type
constant a scalar constant. Any number (17, 4.5, 2.5e-6, ...) or one of the following strings:
pi (3.14159...), e (2.71828...), true (1) or false (0)
scalar
table the content of the whole table vector, matrix
table[i,*]
table[i,]
the i-th row of the table scalar, vector
table[*,j]
table[,j]
the j-th column of the table scalar, vector
table[i,j] the value of the i-th row and j-th column of the table scalar
value the content of the value item scalar, vector, matrix
value[i,*]
value[i,]
the i-th row of the value item scalar, vector
value[*,j]
value[,j]
the j-th column of the value item scalar, vector
value[i,j] the value of the i-th row and j-th column of the value item scalar
wave[!signal,*]
wave[!signal,]
the signal from all channels vector, matrix
wave[!signal,ch] the signal from channel ch (=1,2,...) vector
wave[!signal,*,b,l] the signal from all channels from sample b (0 <= b < wave[!length]) to sample b+l-1 (l > 0)
If b is lower than 0 or b+l is greater than wave[!length] zero padding is applied to the result
vector, matrix
wave[!signal,ch,b,l] the signal from channel ch from sample b to sample b+l-1 vector
gdxfile[!data] all columns of the GDX file item vector, matrix
gdxfile[!data,icol,ncol] the columns of icol to icol+ncol-1 of the GDX file item vector, matrix
  • The fields of the table item table are all numeric (extended table or parameter table).
  • The value item value can contain numbers, vectors or matrices.
  • The wave item wave is any wave item. It must address a (part of a) soundfile if wave is used as target.
  • The file item gdxfile must be of type GDX. This is a special form of the binary files, which can be used as numerical object and can also be connected to an input of a graph item. A GDX file item may contain one vector or one matrix.

row and column vectors

In STx it is not possible to differentiate between row vectors and column vectors. Normally a vector is a row vector, but it depends on the context (the operator or function used) which type of vector is supposed.

complex numbers

The current versions of STx do not implement the datatype complex, but a lot of functions take complex arguments and/or return complex results. Therefore the following convention for numerical objects holding complex numbers is used:
  • complex number: A vector with two elements. If the number is stored in the cartesian format, the first element is the real part and the second the imaginary part. If it is stored in polar format, the first element is the magnitude (or length) and the second the phase.
  • complex vector: A vector of N complex numbers consists of 2N elements. The element 2i is the real part (or magnitude) and the element 2i+1 is the imaginary part (or phase) of the i-th complex number (i = 0..N-1).
  • complex matrix: A matrix of N x M complex numbers consists of 2N rows and M. Each row is formatted like a complex vector described above.
The EVAL implements a set of functions for complex arithmetic and special handling of complex numbers.

polygons

The EVAL command implements a set of functions to manipulate 2-dimensional polygons. These functions are using specially formatted matrices to store information about one or more polygons. Some examples for the use of polygon functions and data types can be found in the example script scripts\examples\polygon_examples.sts.
closed point-list (pg_cplist)
Is a list of N points Pi in a 2-dimensional plane. Each pair (Pi , Pi+1) builds one edge of a polygon. The list is called closed, because PN-1 is connected to P0. A pg_cplist is stored in a matrix PL with N rows and 2 columns. The coordinates of point Pi are stored in PL[i,0] (xi) and PL[i,1] (yi).
simple-polygon (pg_simple)
Is a closed point-list (pg_cplist) defining a polygon without crossing edges.
polygon-stream (pg_stream)
Is a packed format to store the point-list and some additional information for one or more simple-polygons. This format is created by the initialisation function and used as argument and/or result by the most other polynom processing functions. A pg_stream is stored in a matrix with 2 columns and 8M+N0+..+NM-1 rows, where M means the number of polynoms stored in the stream and Ni the number of points of the i-th polynom. The data for the i-th polygon are stored in the matrix in the following format:
row
index
value of
column 0
value of
column 1
comment
oi+0 Ni: number of points reserved (set to 0)
oi+1 IXi: the index of the leftmost/lowest point (used for computations y=f(x)) IYi: the index of the lowest/leftmost point (used for computations x=f(y))
oi+2 XMINi: minimum x of all points YMINi: minimum y of all points The point (XMINi,YMINi) is the lower left corner of the bounding rectangle
oi+3 XMAXi: maximum x of all points YMAXi: maximum y of all points The point (XMAXi,YMAXi) is the upper right corner of the bounding rectangle
oi+4 XCi: x value of the center of gravity YCi: y value of the center of gravity The point (XCi,YCi) is the center of gravity of the polygon
oi+5 Ai: area Li: circumference
oi+6 1 if the center of gravity is inside the polygon,
0 otherwise
1 if the polygon is convex,
0 otherwise
oi+7 reserved (set to 0) reserved (set to 0)
oi+8
..
oi+Ni-1
x values of points y values of points the coordinates of the points (corners) of the (simple) polygon
with: oi is the first row index of the i-th polynum; o0=0, oi=oi-1+8+Ni-1 (i = 1..M-1)

Operators

Numerical operators

Syntax Description Data type of
Result
-x Negate all elements of x. same as x
y+xS
xS+y
Add the scalar xS to all elements of y. same as y
x+y Add elements of x to the elements of y. Both operands must be of the same type. same as x and y
y-xS Subtract the scalar xS from each element in y. same as y
xSy Subtract all elements of y from the scalar xS. same as y
x-y Subtract elements of x from the elements of y. Both operands must be of the same type. same as x and y
y*xS
xS*y
Multiply all elements of y with the scalar xS. same as y
xV*yV The inner (or dot) product of the vectors xV and yV. The length of both vectors must be the same. scalar
xM*yV The product of the matrix xM and the vector yV. The length of the vector yV must be the same as the number of columns in the matrix xM. vector with nrow(xM) elements
xM*yM The product of the matrix xM and yM. The number of rows in yM must be equal to the number of columns in xM. matrix with nrow(xM) rows and ncol(yM)) columns
y/xS Divide all elements of y through the scalar xS. The value of xM may not be 0. same as y
xS/yM Multiply all elements of the inverse matrix of yM with the scalar xS. The matrix yMmust be a square matrix.The special case 1/yM returns the inverse matrix. Note that the function inv(y) can also be used to invert scalars and matrices. same as yM
y%xS The rest of the division of every element in y through the scalar xS (modulo) same as y
y^xS Raise every element of y to the power of the scalar xS.
Special cases: y^-1 is calculated like 1/y and y^2 is calculated like this y*y
same as y

If one of the numerical operands has the prefix ? then the operation is carried out element per element. Example:

#dotprod := eval $#x * $#y // dot product of vectors #x and #y
#winsig := eval $#x ?* $#y // multiply elements of #x and #y (e.g. to apply signal windowing)

Comparison operators

Syntax Description
x<y x less than y
x>y x greater than y
x<=y x less than or equal to y
x>=y x greater than or equal to y
x==y x equal to y.
x!=y x not equal to y.

The result of a comparison of two numerical expressions is (logical) true (numerical 1), if the condition is fulfilled, otherwise it is (logical) false (numerical 0). Normally it make only sense to compare scalars or, more generally, numerical objects with equal dimensions. The following rules applies to a comparison:

  • The numerical objects x and y are equal (x==y is true), if (and only if) the dimensions of x and y are the same and all pairs of elements (xi,j , yi,j) are numerically equal.
  • The numerical objects x and y are not equal (x!=y is true), if the dimensions of x and y are different or at least one element pair (xi,j , yi,j) is numerically not equal.
  • For all other comparisons the dimensions of x and y must be the same, otherwise the comparison failes. The result is true, if the condition is fulfilled for all pairs of elements (xi,j , yi,j).

Logical operators

Syntax Description
x||y logical or
x&&y logical and
!x unary not

The result of a logical operation is true (numerical 1) or false (numerical 0). The arguments x and y can be any numerical type. It is also possible to use arguments with different types. The following rules are used to convert logical (boolean) to numerical values and vice versa:

The numerical result of a logical operation is the value ...

  • 1 if the logical expression is true
  • 0 if the logical expression is false

The logical value of a numerical object (or expression) is ...

  • true if one of its elements is not equal to 0.
  • false if all of its elements are equal to 0.

Selection operator

The selection operator used in EVAL expressions works similar to the COND command.

log_expr ? true_expr : false_expr
log_expr
A logical expression which is used to select the expression to be evaluated.
true_expr
This expression is evaluated and returned as result of the selection operator, if log_expr is true.
true_expr
This expression is evaluated and returned as result of the selection operator, if log_expr is false.

In contrast to the COND command, the selection operator of the EVAL command can be nested, but must be surrounded by brackets, e.g.:

result := eval 1 > 2 ? (5 == 5 ? 5 : 0) : (4 == 5 ? 3 : 4) // result is 4

Functions

latest update: March 2, 2015 (J.W.)

abs · absmax · absmin · absv · acos · aseg1 · asin · asp2osp · atan · avr · cepstrum · complex arithmetic · corr · corrfun · cos · cvphase · dct · density · dev · dft · dist · em · exp · f0ac · f0sp · fft · fill · fir1 · floor · formants · grand · haclust · hcomb · hist · hth · hz2bark · hz2cent · hz2erb · hz2mel · ifft · iir1 · imax · imin · init · int · interp · inv · ipeak · limit · log · log2lin · lpc · map2map · mapmind · max · median · min · modclust · mul · ncol · npow2 · nrow · optmm · otrack1 · pgget · pghull · pgiline · pginit · pgitest · pgsplit · pgtrans · pgxgrid · pztf · qdet · qinterp · rand · rleqs · round · rpoly · rpolyreg · sample · select · shuffle · sig2osp · sign · sin · sinc · smooth · sort · sqrt · sum · svd · tan · ticks2f1 · trn · var · vmcol · vmrow · vsubc · vsubn · vv · vvcat · vvget · vvset · wconvert · window · wsum · ydiff · yint · zcross

Examples

The result of the evaluation returned to the script is a number, vector or matrix. Numbers are returned in a string format (as usual in STx), and vectors or matrices are stored and returned in a temporary (local) parameter table. The return value may be assigned to a variable, a shell item or an addressed part of a shell item. The following examples show some possible assignments.

Assign to a variable: Only the returned string - the value of the number or name of the temporary table - is stored.

#x := eval rand(0,100)     // generate a vector with 100 pseudo random numbers in the range -1 to 1
                           // the name of the returned temporary table is assigned to the variable #x
#y := eval $#x * (1 - $#x) // compute the dot-product of 2 vectors
                           // the returned number is assigned to variable #y

Assigning to a table item

Assign to a table item: Both the content and the definition of the table is replaced by the content and definition of the result item.

// the following code is often used to assign an eval result to a permanent item
#x := new table *          // create a dummy simple table
$#x := eval rand(0,100)    // overwrite the dummy table with the result of the evaluation

// for those prefering compact code: the following line is equivalent to the above code
$(#x := new table *) := eval rand(0,100)
// the number of table columns is fixed (defined in the NEW command)
// the number of table rows is variable:
#y := new table * * num:x:50 /param     // create a parameter table with 50 columns (x0 .. x49)
$#y[3,*] := eval fill($#y[!ncol],1,50)  // assign a vector to row 3, the rows 0 to 2 are
                                        // automatically created and filled with zeros
$#y[$#y[!nrow]+1,*] := eval …           // append a row to a table

Assigning to a value item

Assign to a value item: The data stored in the value item is replaced by the result. The timer configuration of the value item is not changed.

// create a value item
#x := new value *

// assign a vector to the value item
$#x := eval fill(10,0,1)
conlog 'attributes: $#x[!type], $#x[!data]' // output: 'attributes: Vector, 10'

// assign a number to the value item
$#x := eval sum($#x)
conlog 'attributes: $#x[!type], $#x[!data]' // output: 'attributes: Number, 45'

// assign a string to the value item
$#x := set 'sum(x)'
conlog 'attributes: $#x[!type], $#x[!data]' // output: 'attributes: String, sum(x)'

Assigning to a matrix row or column

Assign to a row or column of a matrix. Matrices are stored in table or value items.

#x := eval init(20,20,0)       // create a 20x20 matrix
$#x[0,] := eval fill(20,0,1)   // replace row 0 of the matrix
$#x[,1] := eval fill(20,0,1)   // replace column 1 of the matrix
$#x[,2] := eval fill(100,0,1)  // error: the vector is to long!
$#x[2,] := eval fill(5,0,1)    // error: the vector is to short!

Assigning to an entry of a matrix, or a vector

Assign to an element (i.e., a cell, i.e., a field) of an item:

#x := new table * * str:a num:b // create a table with a string field a numeric field
$#x[0,a] := eval fill(10,1,1)   // the fill command returns a vector (temp. table), 
                                // the id of the returned item is assigned to the cell
$#x[0,b] := eval fill(10,1,1)   // error: a string can not be assigned to a numeric field!
$#x[0,b] := eval sum($#x[0,b])  // okay: the sum is assigned to the cell

Storing a signal in a wave item

Store signal in a wave item.

// create a soundfile (32kHz, stereo, 24bit) and store a 1s tone (440Hz, 880Hz) 
// in channel 1 and a 1s noise in channel 2
// create the soundfile and the wave item
bsf open $@work\testtone.wav; create; 32000; 2; pcm24; wave
#x := new wave * 0_1s
// initialize both channels
// the number of samples stored in x equals the length of the assigned vectors
$#x[!signal,1,0] := eval fill($#x[!length],0,2*pi*440/$#x[!srate])/2
$#x[!signal,2,0] := eval rand(0,$#x[!length],1) / 4
// its also possible to assign a matrix to a wave item
// number of columns  = must be equal to the number of channels
// number of rows     = number of samples to be written
#matrix := eval init(10000, 2, 0)
$#matrix[*,0] := fill($#matrix[!length],0,2*pi*880/$#x[!srate])/2
$#matrix[*,1] := fill($#matrix[!length],0,2*pi*660/$#x[!srate])/2
$#x[!signal,*,10000] := $#matrix
// the signal of a wave item can be modified (e.g. ramp)
$#x[!signal,1,0] := eval $#x[!signal,1,0,1000] ?* fill(1000,0,1/1000)
// now you can play the generated signal
playwave $#x ; Signal generation test!
delete $#x
bsf close $@work\testtone.wav

Using GDX files

GDX file items are special binary files which can be used directly in a numerical expression and which can also be connected to an input of a graph item. One matrix can be stored per GDX file.

[macro computeSpectrogram #wave #len=1024 #hop=256]
// Compute a spectrogram and store it in a GDX file
// Args:   #wave       a mono wave item
//         #len, #hop  the analysis window length and the hopsize in samples
// Result: the path of the GDX file containing the spectrogram
//---
    #path := unique '$@work' gdx 1 8        // get unique output file name
    #lfft := eval fft($#len)                // compute transformation length
    #nfrm := int $#wave[!length] / $#hop    // compute number of frames
    #file := new file * '$#path' 4 $#nfrm $(int $#lfft/2+1) // create GDX file
    // compute and save one log. amplitude spectrum / frame
    for #i := 0 to $#i < $#nfrm step #i := int $#i+1
        #pos := int $#i * $#hop - $#len/2
        $#file[!data,$#i] := eval fft($#wave[!signal,1,$#pos,$#len] ?* whanning($#len) , $#lfft, 4)
    end
    delete /Var #file  // close the file
    exit 1 set '$#path'
[macro computeAvrPowerspectrum #path]
// Compute the average powerspectrum of a spectrogram stored in a GDX file
// Args:   #path       the path of the GDX file containing the spectrogram
// Result: the average log. powerspectrum (a temp. numeric table item)
//---
    #file := new file * '$#path' // open GDX file
    // compute average spectrum
    #avr := eval fill($#file[!nrow],0,0)
    for #i := 0 to $#i < $#file[!ncol] step #i := int $#i+1
        $#avr := eval $#avr + log2lin($#file[!data,$#i,1], 1, 10) / $#file[!ncol]
    end
    delete /Var #file  // close the file
    exit 1 eval lin2log($#avr, 1, 20)

Script examples

The following script shows some examples how to use the EVAL command.

[Macro eval_example]
// force this macro to be run in the debugger
message debug on
message debug init /Step
// note: use the script debugger to view the results

// assign constants
#a := 0
#b := 1
#c := 2
#d := 3

// simple numerical expressions
#e1 := eval $#d*$#c+$#b
#e2 := eval $#b+$#d*$#c
#e3 := eval $#d*($#c+$#b)

// simple logical expressions
#c1 := eval $#a || $#b || $#c
#c2 := eval $#a && $#b && $#c
#c3 := eval $#a && $#b || $#c
#c4 := eval $#c || $#a && $#b
#c5 := eval ($#c || $#a) && $#b
#c6 := eval ! $#a || ! $#b
#c7 := eval ! $#a && ! $#b

// compare numbers
#c1 := eval $#a > $#b
#c2 := eval $#a >= $#b
#c3 := eval $#a < $#b
#c4 := eval $#a <= $#b
#c5 := eval $#a == $#b
#c6 := eval $#a != $#b

// selection operator (conditional assignment)
#c1 := eval $#a < $#b ? $#a+$#b : $#a-$#b
#c2 := eval $#a > $#b ? $#a+$#b : $#a-$#b
#c3 := eval $#a == $#b ? $#a+$#b : $#a-$#b
#c4 := eval $#a != $#b ? $#a+$#b : $#a-$#b

// nested "? :" statements may be hard to read
#c := eval $#a > $#b ? ($#a == $#b ? 1 : 2) : ($#a == $#b ? 3 : 4)
// ...especially if you leave out readability blanks...
#c := eval $#a>$#b?($#a==$#b?1:2):($#a==$#b?3:4)

// using "? :" to select a function argument
#c1 := eval sin( $#a > $#b ? $#a : $#b )
#c2 := eval sin( $#a < $#b ? $#a : $#b )

// initialize vectors
#v1 := eval fill( 10, 0.1, 0.2 ) 	// ten elements
#v2 := eval fill( 10, 0.2, 0.1 )  	// also ten elements
#v3 := eval fill( 5,  0.2, 0.1 )	// only five elements

// ten elements each of which is larger than the corresponding element in #v1
#v4 := eval $#v1 + 1

// compare vectors
#c1 := eval $#v1 == $#v2
#c2 := eval $#v1 != $#v2
#c3 := eval $#v1 >  $#v2
#c4 := eval $#v1 <  $#v2
#c5 := eval $#v1 >  $#v4
#c6 := eval $#v1 <  $#v4

// the "element-wise" operator
#x1 := eval $#v4 ^  2	// normal operation
#x2 := eval $#v4 ?^ 2	// element-wise operation

// vectors of different size are trivially unequal
#c1 := eval $#v1 == $#v3
#c2 := eval $#v1 != $#v3

// illegal comparisons due to different size
#c3 := eval $#v1 < $#v3	// illegal!
#c4 := eval $#v1 > $#v3	// illegal!

// replace the vector v1
$#v1 := eval fill( 11, -5, 1 )

// limit all values to be >= -1 and <= 2
$#v2 := eval limit( $#v1, -2, 2 )
// set lowest bound only
$#v2 := eval limitLow( $#v1, -2 )
// set highest bound only
$#v2 := eval limitHigh( $#v1, 2 ) 

// this works with a number (as opposed to vectors and matrices), too
#c1 := 123.5
#c2 := eval limit($#c1,0,100)
#c2 := eval limitLow( $#c1, 100 )
#c2 := eval limitHigh( $#c1, 100 )

// pick out the smallest/largest value from vec1, vec2 and a number of numbers
#min := eval min($#v1, $#v2, 100, 20)
#max := eval max($#v1,$#v2, 100, 20)

// merge vectors and numbers
$#v3 := eval vv($#v1, $#c1, $#v2, $#c2)

In the directory scripts\examples of the STx installation, you can find a lot of script files using EVAL for differnt purposes (dsp_examples.sts, eval_example.sts, expression_checks.sts, matrix_algebra_examples.sts, parameter_table_example.sts, plot_sample.sts, polygon_examples.sts, ...)

Navigation menu

Personal tools