Element-wise operations¶
All tensors, no matter which number of dimensions they have, support
the many element-wise operations in Orka.Numerics.Tensors
,
using the operators provided by the Ada language.
Binary operators support operations on two tensors as well as one tensor
and one element.
Arithmetic¶
The following binary operators can be used on tensors or a tensor and
an element: +
, -
, *
, /
, **
, mod
, and rem
. Unary operators
like -
and abs
can be used on a single tensor.
Be warned that *
does not perform element-wise multiplication if used
on two tensors and **
if used on a tensor and an Integer
exponent.
Besides using operators, some of the operations can also be performed
with the functions Add
, Subtract
, Multiply
, Power
(uses a single
Integer
as the exponent), and Divide
.
The /
operator may return NaNs if the denominator is zero.
The function Divide_Or_Zero
can be used to create zeros at these places
instead.
*
and **
are also used as operators for matrices
The *
operator performs matrix multiplication if both operands
are tensors. Use the function Multiply
for element-wise multiplication.
The **
operator provides the matrix power operation if the
base is a tensor and the exponent an Integer
. Use the function Power
to raise the elements of a tensor to the power of a given Integer
.
For example, given two tensors, the elements of the second tensor can be multiplied with a number and then added to the first tensor to create a new third tensor:
Tensor_3 : constant CPU_Tensor := Tensor_1 + 2.0 * Tensor_2;
Another example showing the abs
and mod
operators:
Tensor_4 : constant CPU_Tensor := (abs Tensor_1) mod Tensor_2;
Rounding¶
To round numbers up, down, or the nearest integral value, the function
Ceil
, Floor
, or Round
can be used. To truncate the floating-point
numbers, use the function Truncate
.
Math¶
The square-root can be used obtained with the function Sqrt
.
The operation ex, where x are the elements of a tensor, can
be performed using the function Exp
. The natural logarithm with
the function Log
, and the base 10 and base 2 logarithms with Log10
and Log2
.
A tensor containing elements that are the minimum or maximum of a
pair of elements can be created with the functions Min
and Max
.
These two functions can operate on two tensors or a tensor and a single
element.
Trigonometry¶
The sine, cosine, or tangent (in radians) can be computed with the
functions Sin
, Cos
, and Tan
.
The arc sine, arc cosine, and arc tangent can be computed with the
functions Arcsin
, Arccos
, and Arctan
. Values must be
in the range -1.0 .. 1.0 for Arcsin
and Arccos
, otherwise an exception
may be raised.
The function Arctan
has two parameters and both must be greater than zero.
The function Degrees
can be used to convert elements in a tensor from
radians to degrees. Function Radians
converts elements from degrees to
radians.
Logical operations¶
Several operators like and
, or
, xor
, and not
can be used to compare
the elements of two tensors. The function And_Not
is equal to
(not Left) and Right
. The operator not
inverts the boolean values in the
tensor.
All of the operators (except for and
) require the two tensors
to be boolean tensors and the tensor they return is also a boolean tensor.
A boolean tensor can be created by using one of the comparison operators (see below).
As mentioned earlier, the left operand of the and
operator does not need to
be a boolean tensor; it can be a tensor containing floating-point elements or
even be a single element. The tensor this operator returns has the same type as the
left operand and its values will be the values of the left operand whenever the
corresponding (boolean) value of the right operand (always a tensor) is True
.
if the corresponding value is False
then the value in the returned tensor is either
0.0 or False
.
The and
operator is very useful to select elements based on the truth value
of the right tensor. For example, to select values from a tensor Tensor_Values
using the boolean tensor Is_Valid
:
Tensor_Valid_Values : constant CPU_Tensor := Tensor_Values and Is_Valid;
To increment the elements of a tensor Counter
when the corresponding boolean in
a tensor Is_Match
is True
, write:
Counter := Counter + (1.0 and Is_Match);
In these two examples, the boolean tensor of the right operand acts as a mask to select elements.
Comparing¶
Boolean tensors can be created by using Ada's comparison operators:
=
, /=
, >
, <
, >=
, and <=
. All of these operators can compare two
tensors or a tensor and a single element. The tensors involved in the comparison
must not be boolean tensor but a regular tensor.
For example, the function Binomial
iteratively updates a tensor Result
as
follows:
Result := Result + (1.0 and (Uniform (Shape) <= P));
where P
is an element and Uniform
a function that generates a tensor with
a uniform distribution. This example shows a comparison, a logical operation,
and arithmetic, all in one line of code, even though the tensors involved
might contain hundreds of thousands of elements depending on Shape
.
Additionally, the =
operator can return a Boolean
, which will be True
if
all values of the two tensors are equal, or False
otherwise:
if Tensor_1 = Tensor_2 then
Orka.OS.Put_Line ("The two tensors are equal");
end if;
The function All_Close
can be used to test if two tensors are equal
enough given a relative and absolute tolerance.
After obtaining a boolean tensor, the tensor can be used in logical operations or used as an index (see below) to return a new (smaller) tensor consisting of only the elements selected by the index.
The functions Any_True
and All_True
return True
if any or all elements
a boolean tensor are True
, and False
otherwise. In particular, Any_True
and All_True
are useful to exit a loop:
exit when not Any_True (Loop_Condition);
This is useful in algorithms where you want to update elements of a tensor iteratively and exit the loop once all elements meet or no longer meet some condition.