Liquid Error: Unable to cast object of type 'Treepl.Liquid.Data.PageDocument' to type 'Treepl.Data.ParameterizedObject'.

Gedae Idea Language Reference

Updated May 2012

Algebraic Expressions

Variables can be declared with an expression that sets their value.

  • C = 2 * PI * R;
Data Types

The following data types are supported: float, double, complex, and dcomplex (double complex), char, short, int, INT (32 bit on 32 bit OS, 64 on 64), dint (64 bit), unsigned char, unsigned short, unsigned int, unsigned INT, unsigned dint.

When declaring a variable, the data type can be declared.

When declaring a variable, the data type can be left off and inferred from the expression that sets it.

If a variable is typed, the result of the expression is cast to the data type.

Ranges

Ranges are positive finite values.

  • range i = 10;

All ranges can be used in expressions.

Dimensions

There are three dimension types:

  • Families – preindices using square braces, for example, [f]x
  • Arrays – postindices using square braces, for example, x[r][c]
  • Time – postindices using parentheses, for example, x(t)

On the LHS of equations, dimensions can be expressed only as simple expressions (that is, single range variables).

If a variable is declared without the stream modifier or a time index and its expression does not include any streams, then it is a parameter. Parameters do not have a rate and cannot be dereferenced by a time index. Parameters can be declared without an expression to set their value.

  • x = 1; // parameter
  • int y; // unset parameter
  • z = x + y; // parameter

If a variable is declared with the stream modifier or a time index, then it is a stream. If a variable’s expression includes a stream, then it is a stream. All streams are infinite. All streams must be declared with an expression to set their value.

  • stream x = 1; // stream
  • y = x; // stream

On the RHS of equations, dimensions can be any expression.

Operators

All C binary operators are supported.

The C unary operators ! and ~ are supported.

The C tertiary operator ?: is supported.

The # operator is a unary operator that returns the size of the range.

The ` operator is a binary operator for expressing powers.

A collapsing operator performs an operator across a dimension.

  • Sum += M[i][j]; // matrix sum
  • Dot += X[i] * Y[i]; // dot product
  • Prod += M[i][j] * N[j][k]; // matrix multiply
  • Dil[i][j] ||= Im[i+i1][j+j1]; // dilution image kernel

The dimension(s) of a collapsing operator are all ranges that appear in the RHS of the expression that do not appear on the LHS. If an index appears on the RHS and not the LHS, then the assignment operator must be a collapsing operator.

  • range i = 10;
  • a[i] = i;
  • x = a[i]; // illegal

The following collapsing operators are provided.

Collapsing Operators
Function Description Initialization
+= Increment and assign 0
-= Decrement and assign 0
*= Multiply and assign 1
/= Divide and assign 1
&= Bitwise AND and assign
^= Bitwise exclusive OR and assign 0
|= Bitwise inclusive OR and assign 0
&&= AND and assign 1
||= Inclusive OR and assign 0
^^= Exclusive OR and assign 0
>?= Maximum and assign Lowest negative number
<?= Minimum and assign Highest positive number



Return to Top

Functions

Expressions can be grouped together into functions. Functions can have any number of outputs and any number of inputs, including zero. Function outputs are not typed. The type is determined from the expressions that set the output.

  • Y foo(float X) {
    • Y = (X+1)/2; // implicitly declared as float
  • }
Invocation

Functions can be invoked in expressions.

  • X = 2;
  • Y = foo(1);
  • Z = Y + foo(X);

All inputs from the function’s argument list must be specified in the invocation.

If a multiple output function with N outputs is used, then up to N variables can be listed on the LHS. If M<N variables are listed, then the first M return values are used. When a multiple output function is used in an expression, only the first output is used.

  • Y,Z bar(float X) {
    • Y = (X+1)/2;
    • Z = (X-1)/2;
  • }
  • ...
  • Y = bar(1)+1; // sets Y to 2
  • Y2, Z2 = bar(Y); // sets Y2 to 1 and Z2 to 0
Overloading

Functions can be used for both parameters and streams.

  • Y foo(float X) {
    • Y = (X+1)/2;
  • }
  • ...
  • int x = 2;
  • p = foo(x); // parameter
  • stream float y = x;
  • s = foo(y); // stream
Implementation

Functions can be implemented by expressions or by kernels. Kernels use the Equation Field to define the expression or function that they implement. If a kernel equation defines a function, then the family and token dimensions of the outputs must be specified.

  • Name: mf_qr
  • Equation: q[i][j], r[j][k] = qr(in);

Return to Top

Data Structures

Data structures allow tokens to be organized into a single container and referenced by field name.

Definitions

The C struct syntax is used to define a structure.

  • struct cart {
    • float x;
    • float y;
    • float z;
  • }

The data type of each element is defined in the structure definition. Fields cannot be arrays, but arrays of structures can be created.

Constructor

A data structure is constructed by providing an array of values.

  • float x = 2.9;
  • cart pnt = {x, 3.0, -1.3}; // parameter

Expressions can be used inside the constructor, but the constructor cannot be used inside expressions.

Structures can contain all streams or all parameters.

Reference

The C . (period) infix operator is used in expressions to reference the fields in a structure.

  • out cartDistance(cart in) {
    • out = sqrt(in.x`2 + in.y`2 + in.z`2);
  • }

Return to Top

Data Flow

The introduction of time into a programming language offers a new method of program structure and introduces issues with data flow that must be considered.

Static Rates

The relationship between rates of different streams is determined by their use in expressions. Expressions can be written with relative time indices, stating the number of tokens relative to the current time. When using relative time indices, decreases in rate can be accomplished by referencing multiple tokens at or ahead of the 0 index. Delay and overlap can be accomplished by referencing negative time indices.

  • range i = 10;
  • a = a(-1)+1;
  • b2 = (a + a(1))/2; // decimation by 2 by averaging
  • c = b(-1); // delay by 1
  • c2 = b + b(-1); // overlap of size 1
  • d(i) = c; // hold for 10 samples

The combination of static rates must follow data flow rules. Multiple static rates on the same stream cannot be used in the same construct. The verification of static rates is done by the data flow graph (DFG) compiler.

Tiling

Relative time indices can also be used to specify tiling operations and the interpolation and decimation needed to perform this token decomposition. The interpolation from creating tiles from a matrix can be expressed using arithmetic on smaller ranges. The decimation from reconstituting a larger array from tiles can be expressed using the % and / operators on the ranges. Alternatively, the comma notation can be used.

  • range t = inf;
  • range i = 10; // matrix size
  • range j = 10;
  • range i1 = 5; // tile size
  • range i2 = 2;
  • a[i][j](t) = i+10*j;
  • b[i2][j](i1) = a[i1*#i2+i2][j]; // create tiles
  • c[i2][j] = foo(b[i2][j]);
  • d[i][j] = c[i/#i1][j](i%#i1); // reform matrix
Dynamic Rates

Dynamic ranges can create dynamic rates. The combination of dynamic rates must follow data flow rules. Streams of different rates cannot be used in the same expression. The verification of dynamic rates is done by the DFG compiler.

  • range r = 10;
  • a[r] = r;
  • b(r) = a[r];
  • d[r] = b + a[r]; // illegal combination of rates

Return to Top

Conditionals

Conditionals can be used to set values based on a parameter or stream value. They can also be used to reduce data rate.

If Statement

The C syntax is used for an if statement.

An if statement can introduce a dynamic stream.

  • Threshold = 0;
  • if (a > Threshold)
    • b = a; // b is a slower rate than a

An if statement with else if and/or else clauses can be used to perform a select.

  • Threshold = 0;
  • if (a > Threshold)
    • b = a;
  • else
    • b = Threshold; // b is at the same rate as a

An if statement with else if and/or else clauses can be used to perform branching,

  • if (c == 0)
    • x = foo(a);
  • else
    • y = bar(a);

A complete branch and merge where for each input token, a token is produced on the output stream,

  • if (c == 0)
    • b = foo(a);
  • else
    • b = bar(a); // b is at the same rate as a

And an incomplete branch and merge where some branches do not produce tokens on the stream,

  • if (c == 0)
    • b = foo(a);
  • else if (c == 1)
    • b = bar(a); // b is not produced if c is not 0 or 1

Note a is consumed regardless of the condition. A token must be available on a regardless of the value of c, and that token is consumed regardless of the value of c.

Switch Statement

The C syntax for a switch statement is used with the change that each case statement is assumed to end in a break. Any overlap in case statements can be implemented by duplicating code in each case. As in C, the switch statement does not require a default clause, and thus it can introduce dynamic streams.

  • switch (c) {
    • case 0: e=c+1; d = a;
    • case 1: e=c+1; d = b;
    • default: d = 0;
  • }

Return to Top

Iteration

Loops are used to iterate on tokens, i.e., all tokens are held during the duration of the loop. Loops must iterate on at least one token.

A for, while, or do-while loop specifies iteration. For for loops, the C syntax is used. For while and do-while loops, the syntax is very similar to the C syntax.

For Loop

Variables created by the for loop, called iteration variables, are initialized in the initialization section of the for construct. If these iteration variables are used on the RHS of expressions in the body of the loop, the variable refers to the current value of the token, not the new value computed during the current iteration.

  • for (c=1.0, k=0; k᝺ k=k+1) {
    • c = c * exp(-1); // iteration on held token
  • }

The new value of the token can be reused inside the body of the loop by using an intermediate variable inside the loop. Intermediate variables are variables defined inside the body of the loop.

  • for (c=1.0, d=1.0, k=0; k<10; k=k+1) {
    • temp = c * exp(-1); // intermediate variable for “new” c
    • c = temp;
    • d = d + temp;
  • }
While Loop

While loops and do-while loops are also supported, but their syntax differs from the C syntax by adding a section to initialize iteration variables. This initialization section makes the syntax very similar to for loops.

  • while (c=1.0; c>0.1) {
    • c = c * exp(-1); // iteration on held token
  • }
  • do (d=c) {
    • d = d * exp(1);
  • } while (d<1.0);

Return to Top

State Reset

Conditionals and loops all include the resetting of state. Iteration constructs reset state at the beginning of the loop. Conditional constructs reset state when the branch changes.

The following example implements a conditional low pass filter. The low pass filter uses a delay to store the previous tokens. This state is reset whenever valid(-1) == 0 and valid == 1.

  • if (valid) {
    • y = y(-1) + alpha * ( x – y(-1) );
  • }

State variables can be used in the data flow graph language to retain information across conditional or loop boundaries.

Return to Top

Return to the LEARN main page.