Basic functions
There is a large number of functions stored in SA Engine's in-memory object-oriented database. For example, the following function call returns the version of SA Engine you are running.
system_version()
Run the function by clicking the play button play_circle
Documentation of functions and other SA Engine artifacts are stored in
the database as well. You can query the database about the
documentation of a function named myfunction
by evaluating
doc("myfunction")
. The doc()
function returns the documentation of
the function as a string.
Example:
doc("sqrt")
You can edit the examples in the tutorial. Try changing sqrt
to sin
!
You can enter several OSQL statements by separating
them with a ;
.
Examples:
doc("heartbeat");
doc("euclid")
If you don't know exactly the name of a function you can use
apropos("string")
to return all functions having the string in their
names.
Example:
apropos("atan");
The function call apropos("atan")
returns as objects the
functions having the string tan
in their names. Objects are
displayed as #[OID n id]
where n
is a unique object number and
id
is an optional object name.
Only knowing the function objects is usually not very useful. Here, we
would rather like to get documentations about the functions we found.
The expression doc(apropos("atan"))
calls the function doc()
for
each function retrieved by apropos("atan")
to retrieve the two
documentation strings.
Example:
doc(apropos("atan"))
The function sourcecode("function")
returns the function's
definition stored in the database.
Example:
sourcecode("atan")
As doc()
, sourcecode()
works also for objects.
Example:
sourcecode(apropos("atan"))
The functionality of SA Engine is grouped into topics stored in the database. Navigate to Topics in the Reference section for documentation of a specific topic.
Math functions
There is a large library of basic mathematical functions built into the system and the usual arithmetic operators are available.
Example:
sin(3.14/2)*cos(3.14)
To learn more about basic math functions go to Math in the Topics section.
Session variables
During sessions with SA Engine it is often practical to temporarily
save values of expressions in session variables prefixed with :
by using the set
statement, e.g.:
set :pi = asin(1)*2;
sin(:pi/2)*cos(:pi)
The session variable :pi
is first assigned the value of asin(1)*2
.
Session variables disappear when you exit SA Engine. To permanently save values in the built-in database you must use stored functions, as explained next.
Stored functions
Analysis models are defined in terms of a number of OSQL
functions. OSQL functions are created and stored in the database by
evaluating a create function
statement. There are functions of
different kinds, depending on how they are used.
Stored functions are functions that hold tabulated
function values permanently in the built-in database. They are created
by a create function ... as stored
statement.
Example:
create function const(Charstring c) -> Real
as stored
The above statement creates a tabulated function called const
taking
a string c
as argument and returning a real number as
result.
You are recommended to document your functions by a master comment
preceding the as
.
Example:
create function const(Charstring c) -> Real
/* The value of the math constant named `c` */
as stored;
doc("const")
Stored functions can be populated using the set
statement.
Example:
set const("pi") = 3.14;
set const("e") = 2.71;
const("pi");
ln(const("e"));
sin(const("pi")/2)*cos(const("pi"));
You can also update stored functions using set
, for example:
set const("pi") = asin(1)*2;
set const("e") = exp(1);
ln(const("e"));
sin(const("pi")/2)*cos(const("pi"))
Functions may have no arguments at all.
Example:
create function mypi() -> Real
/* The constant PI */
as stored;
set mypi() = asin(1)*2;
mypi()
Derived functions
A derived function is a function defined by an OSQL expression.
Example: The following function converts Celsius degrees to Fahrenheit:
create function ctof(Real c) -> Real
/* Convert a Celsius degree `c` to Fahrenheit */
as c * 9 / 5 + 32;
ctof(10)
The head of the function, e.g ctof(Real c) -> Real
, is called
the function's signature. It defines the name(s) of the
argument(s) (c
in ctof(c)
), the type(s) of the argument(s)
(e.g. Real
), and the type of the result from the computation,
(e.g. -> Real
).
Temporal functions
The function local_time()
returns the current wall time as an ISO
time stamp.
While local_time
returns the current wall time as a string, the
function now()
returns the wall time as an object of type Timeval
,
which is the internal representation of time points.
Examples:
local_time();
now()
The function ts(Object o)->Timeval
returns a time stamped object,
which represents a timestamped value o
.
Examples:
ts(1);
value(ts(1));
local_time(ts(1))
For more about functions over time visit Time in the Topics section.
Vectors
So far the function calls were made over single values and sets of
single values. Building mathematical models, e.g. to identify
interesting properties of streams, also require vectors with the
usual [...]
notation.
Example:
[1,4,3,2]+[1,5,6,7]
Change visualization of the vector to Bar plot
by adding //plot: Bar plot
before the query.
The mathematical operators +,-,*,/,^
can be used for whole vectors
or mixes of vectors and scalar values.
Example:
[1,4,3,2]-[0,2,3,4]+1
How would it look as text?
A .
in front of an operator indicates element-wise application of it
on each element of the vectors. For example, for multiplication the
*
operator over vectors returns the scalar product while .*
returns element-wise multiplication.
Examples:
[1, 2, 3, 4] * [5, 6, 7, 8];
[1, 2, 3, 4] .* [5, 6, 7, 8]
More examples:
"Addition";
[1, 2, 3, 4] + [5, 6, 7, 8];
"Scalar times vector";
5 * [1, 2, 3, 4];
"Element-wise power of two";
[1, 2, 3, 4] .^ 2
There are many built-in vector functions, e.g.:
"sum";
sum([1, 2, 3, 4]);
"mean";
mean([1, 2, 3, 4]);
"standard deviation";
stdev([1, 2, 3, 4]);
"median";
median([1, 4, 2, 3]);
"max";
max([1, 4, 2, 3]);
"dimension";
dim([1, 3, 2])
Often vectors are used in derived function definitions. For example,
the following function computes the Euclidean distance between vector
v
and w
:
create function dist(Vector v, Vector w) -> Real
/* Compute the Euclidean distance between `v` and `w` */
as sqrt(sum((v - w) .^ 2));
dist([1,2],[3,4])
The built-in function euclid(v,w)
does the same.
The general Minkowski distance computation function minkowski(v,w,r)
is
also built-in. This example shows Manhattan distance (), Euclidean
() and Chebyshev () distance expressed in terms of
minkowski(v,w,r)
.
Examples:
minkowski([1,2],[3,4], 1);
minkowski([1,2],[3,4], 2);
minkowski([1,2],[3,4], 1.e320);
Matrices
A matrix is a two-dimensional numerical vector. It is the same
as type Vector of Vector of Number
.
Examples:
[[1,2],[3,4]] * [[2,3],[6,7]];
[[1,2],[3,4]] .* [[2,3],[6,7]]
The Fast Fourier Transform
The function rfft(v)
computes the real number Fast Fourier
Transform
(FFT) over a vector of numbers v
.
Example:
rfft([1, 2, 3, 4])
The inverse real FFT is computed with irfft(v)
.
Example:
irfft(rfft([1, 2, 3, 4]))
The later tutorial section Querying the microphone shows how user-defined functions over vectors and FFT can be used for filtering audio streams in real-time.
Vectors of objects
So far the vectors contained only numbers, as required by math functions and operators. Actually, vectors can contain any kind of objects including strings and numbers. For example, the following vector contains both a number and a string:
Example:
["Tore", 1234]
In general vectors are used for representing ordered finite sequences of objects. By contrast, a stream can be seen as a possibly infinite growing sequence of objects. Vectors can be used to group elements in streams, as will be explained later.
Go to Vector in the Topics section for documentation of vectors.
Sets and bags
Functions can also produce sets of objects where the order is not
guaranteed as with vectors. For example, the function range(n)
returns the set of numbers from 1 up to n
.
Example:
range(10)
Here range(10)
produces the set of all integers from 1 to 10.
Example:
sin(range(200)*0.2)
Here the sine function is applied one each element in the set of all integers from 1 to 200.
Applying other functions, such as sin(x)
on a set
means that the function is applied on each element of the set.
Try visualizing the result as a line plot by inserting the row //plot: Line plot
before the query!
In general sets in OSQL may contain duplicates.
Example:
floor(range(200)/2)
The term bag is used rather than set to indicate sets with possible duplicates.
Apply sin(x)
on the result of floor
!
Explicit bags can be create as using the notation, for example:
set :mybag = bag(1,2,2,3);
select i from Integer i where i in :mybag
As for vectors, aggregate functions over bags are applied on
entire bags, rather than on each element of the bag as, for example
range(n)
returns a bag of number and sum(Bag of Number)->Number
sums the elements of a bag of number.
Example:
sum(range(200)/2)
See Aggregate in the Topics section for more on aggregate functions.
Boolean and null values
The constant null
is used to represent unknown or missing
values. For example, the last element of the vector [1,2,null]
is
unknown.
A Boolean value null
value is regarded as false. Thus, the query
2<1
returns null
, while 2>1
return true
. The only object of
type Boolean is true
. The constant false
is null
casted as a
Boolean.
null
values in bags are regarded as missing values that are ignored
by aggregate functions.
Passing null
as argument in a function call will return null
without calling the function. For example:
sin(sqrt(-1));
An OSQL query variable bound to the value null
is regarded as
unbound and therefore null
cannot be regraded as a regular
value. Instead, to test that an expression x
is null
, use the
notany(x)
function that returns true
if x
is null
.
Often it is practical to use a default value instead of null. For this
the expression can be used that returns
the first not being null
and dlft
if all
For example:
coalesce(sqrt(-1),ln(-1),1)+1
Tests in case
statements succeed unless they return null
. For
example, the following query returns one:
case when sqrt(-1) then 1 else 0 end
To replace all null
s in a vector use
whennull(Vector v, Object dflt)->Vector
.
For example:
whennull([1,2,null,3],0)+2
The next part of the tutorial will show how to make general queries that selects collections of objects from the database.