Basic expression tutorial
The expression is the central entity of KFR framework.
Input expressions can be read from and output expressions can be written to. Class can be an input and output expression at same time. univector is an example of such class.
Data type of an input expressions can be determined by calling value_type_of. However, not all expressions have their types specified. In such cases value_type_of will return special type generic.
Size (length) of an expression also can be specified or not. counter is an example of generic (untyped) expression without the size.
Calling functions
Passing an expression into a function doesn’t calculate value immediately. Instead, new expression will be created.
Example:
auto a = counter(); // a is an expression without type
auto b = a * 2 + 1; // b is an expression without type
univector<int, 5> c = b; // fill c with values 1, 3, 5, 7, 9
In the example above, only the last line does actual calculations. This is similar to concept of lazy evaluation.
univector<int, 6> d = sqr(counter());
print(d); // prints 0, 1, 4, 9, 16, 25
const double w = c_pi<double> * 0.125;
univector<int, 6> e = sin(counter() * w);
print(e); // prints 0 0.382683 0.707107 0.92388 1 0.92388
counter()
counter()
is an expression which outputs values from 0 to infinity.
This expression have no type specified, so can be used in any expression.
We will use the following simple function to print the first ten values of an expression:
template <typename E>
void print10(const E& e)
{
univector<double, 10> v = e; // do actual calculations
println(v); // print result
}
Examples:
print10(counter() * 2); // 0, 2, 4, 6, 8, 10, 12, 14, 16, 18
print10(1 << (counter()+1)); // 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024
print10(clamp(counter(), 2, 7)); // 2, 2, 2, 3, 4, 5, 6, 7, 7, 7
auto freq = counter() * c_pi<double, 2> * 1000.0 / 44100.0;
auto sine = sin(freq);
print10(sine); // print the first ten samples
// of 1000hz sinusoid sampled at 44100hz