# Operations¶

Querying properties of objects:

• math::is_member: test wether an object of the magma type is in the magma.
• math::equal: test whether two objects are equal.
• math::not_equal: test whether two objects are not equal.
• math::approximately_equal: test whether two objects are approximately equal.
• math::compare: compare two objects with a strict weak ordering.
• math::order(): compare two objects with an ordering implied by a path operation.

Producing objects:

• math::non_member: return an object of the magma type that is not in the magma. E.g. not-a-number for floating-point types.
• math::identity(): return the identity element for a magma and operation. E.g. 1 for times on number types.
• math::annihilator(): return the annihilator for a magma and operations. E.g. 0 for times on number types.
• math::zero(): return the identity for times.
• math::one(): return the identity for plus.

Binary operations:

• math::pick: return one value or the other, depending on a condition.
• math::choose: return the most preferable of two values.
• math::times: multiply two values.
• math::divide(): divide one value by another. For some magmas, left and right division are distinguished.
• math::minus(): subtract one value from another. For some magmas, left and right subtraction are distinguished.

Unary operations:

• math::invert(): return the inverse of an element under an operation. This is not available for all magmas, even if the inverse operation is available.
• math::reverse(): return the reverse of an element under an operation.
• math::print: output the element to a stream.

Operation on operations:

• math::inverse_operation(): return the inverse of an operation. The result is also an operation. For example, inverse_operation <math::left> (math::times) returns an object of type math::callable::divide <math::left>.

• math::is::associative: whether an operation is associative.
• math::is::commutative: whether an operation is commutative.
• math::is::idempotent: whether an operation is idempotent.
• math::is::path_operation: whether an operation is a path operation, i.e. whether it returns either the left or the right argument.
• math::is::distributive: whether one operation distributions over another.
• math::is::monoid: whether the magma with operation is a monoid, i.e. whether the operation is associative and has an identity.
• math::is::semiring: whether the magma is a semiring with multiplication and addition operators.
• math::is::throw_if_undefined: whether an operation throws if it is undefined on the arguments given.

Compile-time queries about nested call expressions:

• math::has: whether a nested operation is implemented for specific parameters.
• math::result_of: the result of a nested operation.
• math::result_of_or: the result of a nested operation, with back-off in case the operation is not implemented.
• math::is::approximate: whether the result of an operation is approximate.

## Reference¶

### Compile-time helpers¶

struct math::left

Indicates left direction for operations that take an operation. This class is used only at compile-time and remains incomplete.

struct math::right

Indicates right direction for operations that take an operation. This class is used only at compile-time and remains incomplete.

struct math::either

Indicates either left or right direction for operations that take an operation. This can only be used if the direction is irrelevant. For example, for real numbers, there is no difference between left and right division. This class is used only at compile-time and remains incomplete.

template <class Magma>
struct math::magma_tag

Metafunction that assigns magma tags to types. All types that have the same magma tag are in the same magma.

Return
The magma tag.
Templates
• Magma -

The type for which the magma tag is required.

template <class Magma>
struct math::is_magma

Metafunction that indicates whether a type is in a magma.

Return
true iff Magma is in a magma, i.e. its magma tag is not not_a_magma_tag.
Templates
• Magma -

The type for which the status is required.

struct math::merge_magma

Rime merge policy for magmas.

If you would like to return one value or another based on a run-time or compile-time condition, then say

```rime::if_ <merge_magma> (condition, magma1, magma2)
```

This will automatically return the correctly general type.

This wraps operation::unify_type to form a metafunction implementing a Rime merge policy. If Left and Right are the same type, then it is returned unchanged. Otherwise, some conversion is necessary, so operation::unify_type is called with the decayed types to find the common type.

template <class Operations, class Magma>
struct math::generalise_type

Convert a magma type to a type in the same magma that can contain the result of any combination of a number of binary operations applied to it.

For example, a single_sequence under plus will generalise to optional_sequence; under times (or under both) it will generalise to a sequence.

Templates
• Operations -

A meta::vector of binary operations, usually from namespace callable.

• Magma -

The magma type to be generalised.

### Operations on magmas¶

const auto is_member

Some magmas have values that are not in the magma, like not-a-number values in standard floating-point types.

Return
Whether value is a member of the magma.

Parameters
• value. -

const auto equal

Return
Whether left and right are equal. This should normally correspond to operator==.
Parameters
• left -

• right -

const auto not_equal

Return
Whether left and right are not equal. This should normally correspond to operator!=.
Parameters
• left -

• right -

const auto approximately_equal

Return
Whether left and right are approximately equal.
Parameters
• left -

• right -

To support composite magmas (such as math::lexicographical), different comparison operations are available. math::compare(), if implemented, gives a strict weak ordering, and is often equaivalent to operator<. order <...> also implements a comparison, which may be related to compare, but this is not necessary. order <choose>, if defined, returns true if the left value is better, in some sense, than the right value. If it is defined, then math::choose() will return the better of two values.

Some magmas, cost, for example, implement the same behaviour with the operation plus. order <plus> then compares two values; plus itself returns the best (in this case, lowest-cost) of two.

const auto compare

Return whether magma1 comes before magma2 in a strict weak ordering. This returns false for both orders of arguments iff equal returns true.

Parameters
• magma1 -

• magma2 -

template <class Operation, class Magma1, class Magma2>
auto order(Magma1 && magma1, Magma2 && magma2)

Return whether operation Operation will return magma1, or magma2. This operation is only available if Operation applies a strict weak ordering and returns either magma1 or magma2.

Templates
• Operation -

The operation that returns either either magma1 or magma2.

Parameters
• magma1 -

• magma2 -

#### Producing a value¶

template <class Magma>
std::result_of< callable::non_member< Magma >)>::type non_member()

Return
A non-member of the same magma as Magma. If is_member is applied to this value, it returns false. This operation is not always supplied. For floating-point values, NaN is returned.
Templates
• Magma -

A type that is in a magma that the return type should be in. Note that the return type is not necesssarily that type.

template <class Magma, class Operation>
std::result_of< callable::identity< Magma >Operation)>::type identity(Operation const & operation)

Return
The identity with respect to Operation of the same magma as Magma. In calling this, it is possible to indicate the operation as the second type argument, or as the value argument. (Or both, redundantly.) Thus, identity <float, callable::times>() and identity <float> (times) return the exact same value.
Templates
• Magma -

A type that is in a magma that the return type should be in. Note that the return type is not necessarily that type.

• Operation -

The callable type that represents the operation.

Parameters
• operation -

(optional if Operation is given as a template argument) A callable that represents the operation.

template <class Magma, class Operation>
std::result_of< callable::annihilator< Magma >Operation)>::type annihilator(Operation const & operation)

Return
The annihilator with respect to Operation of the same magma as Magma. In calling this, it is possible to indicate the operation as the second type argument, or as the value argument. (Or both, redundantly.) Thus, annihilator <float, callable::times>() and annihilator <float> (times) return the exact same value.
Templates
• Magma -

A type that is in a magma that the return type should be in. Note that the return type is not necessarily that type.

• Operation -

The callable type that represents the operation.

Parameters
• operation -

(optional if Operation is given as a template argument) A callable that represents the operation.

template <class Magma>
std::result_of< callable::zero< Magma >)>::type zero()

Return
Generalised zero, i.e. the identity with respect to the operation math::plus. Equivalent to identity <callable::plus, Magma>().
Templates
• Magma -

A type that is in a magma that the return type should be in. Note that the return type is not necessarily that type.

template <class Magma>
std::result_of< callable::one< Magma >)>::type one()

Return
Generalised one, i.e. the identity with respect to the operation math::times. Equivalent to identity <callable::times, Magma>().
Templates
• Magma -

A type that is in a magma that the return type should be in. Note that the return type is not necessarily that type.

#### Binary operations¶

const auto pick

Return
magma1 iff condition is true; magma2 otherwise. When necessary, this selects a return type that is general enough to represent either argument.
Parameters
• condition -

A boolean, which can be a compile-time or a run-time value.

• magma1 -

• magma2 -

const auto choose

Return
The most preferable out of magma1 and magma2.
Parameters
• magma1 -

• magma2 -

const auto times

Return
The product of magma1 and magma2.
Parameters
• magma1 -

• magma2 -

const auto plus

Return
The sum of magma1 and magma2.
Parameters
• magma1 -

• magma2 -

template <class Direction, class Dividend, class Divisor>
auto divide(Dividend && dividend, Divisor && divisor)

Return
The division of dividend and divisor. This can be performed in two directions, but note that the order of the arguments does not change. Left division is the inverse of multiplication on the left: divide <left> (times (a, b), a) == b. Right division is the inverse of multiplication on the right: divide <right> (times (a, b), b) == a. If multiplication is commutative, then left division is the same as right division. Then, Direction can be left out, or given as math::either.
Templates
• Direction -

The direction of the division.

Parameters
• dividend -

Also known as numerator.

• divisor -

Also known as denominator.

template <class Direction, class Minuend, class Subtrahend>
auto minus(Minuend && minuend, Subtrahend && subtrahend)

Return
The difference of minuend and subtrahend. This can be performed in two directions, but note that the order of the arguments does not change. Left subtraction is the inverse of addition on the left: minus <left> (plus (a, b), a) == b. Right subtraction is the inverse of addition on the right: minus <right> (plus (a, b), b) == a. If plus is commutative, then left subtraction is the same as right subtraction. Then, Direction can be left out, or given as math::either.
Templates
• Direction -

The direction of the subtraction.

Parameters
• minuend -

The object that the subtrahend will be subtracted from.

• subtrahend -

The object that will be subtracted from the minuend.

#### Unary operations¶

template <class Direction, class Operation, class Magma>
auto invert(Operation const & operation, Magma const & magma)

Return
The inverse element of magma with respect to the operation. The operation can be given as a type argument, or as a value argument.
Templates
• Direction -

(optional: the default is math::either) The direction of the inverse. A left inverse (indicated with math::left) means that, say, math::inverse <left, callable::plus> (a) + a is equal to the additive identity.

• Operation -

The operation that the inverse is with respect to.

Parameters
• operation -

(optional if Operation is given as a template argument) The operation that the inverse is with respect to.

• magma -

The value to be inverted.

template <class Operation, class Magma>
auto reverse(Operation const & operation, Magma const & magma)

Compute the reverse of a value. It is required that operation (reverse (a), reverse (b)) == reverse (operation (a, b)). The return type may be in a different magma. For example, this may reverse the elements of a left sequence semiring and return them as a right sequence semiring. However, it is required that reverse (reverse (a)) == a and that the result type of applying reverse twice returns a type in the same magma.

For commutative operations, the implementation may just return the magma passed in without any changes.

The operation can be given as a type argument, or as a value argument.

Return
The reverse of an element of magma with respect to the operation.
Templates
• Operation -

The operation that the inverse is with respect to.

Parameters
• operation -

(optional if Operation is given as a template argument) The operation that the inverse is with respect to.

• magma -

The value to be inverted.

auto const print

Output a human-readable representation of the magma to a stream.

Return
void.
Parameters
• stream -

The output stream to write to.

• magma -

The value to output the representation of.

### Operations on operations¶

The following are operations on operations.

#### Run-time¶

template <class Direction, class Operation>
auto inverse_operation(Operation const & operation)

Return the inverse of the operation. For example, inverse_operation (times) will return an object of type callable::divide<>. The operation can be given as a type argument, or as a value argument.

Templates
• Direction -

(optional: the default is math::either.) The direction of the inverse. For example, in a sequence semiring, in which math::times concatenates two sequences, left division and right division are different.

• Operation -

The callable type that represents the operation.

Parameters
• operation -

(optional if Operation is given as a template argument) A callable that represents the operation.

template <class... Arguments>
struct math::is::associative

Whether an operation on a magma is associative. That is, whether in an expression that applies the same operation a number of times, like 1+2+3, changing the position of the brackets does not change the result.

It is possible that the operation is approximate but it is still approximately associative. In that case, this will evaluate to true.

It is possible to instantiate this with the standard type argument syntax, documented below, or with one argument in a cute syntax, one of: Operation (Magma1, Magma2); Operation (Magma1, Operation (Magma2, Magma3)); Operation (Operation (Magma1, Magma2), Magma3).

Templates
• Operation -

The operation, normally a type in namespace math::callable.

• Magma -

A type that belongs to the magma of interest.

template <class... Arguments>
struct math::is::commutative

Whether an operation on a magma is commutative. That is, whether the operands of the operation can be exchanged without changing the result.

It is possible that the operation is approximate but it is still approximately associative. In that case, this will evaluate to true.

It is possible to instantiate this with the standard type argument syntax, documented below, or with one argument in a cute syntax: Operation (Magma1, Magma2).

Templates
• Operation -

The operation, normally a type in namespace math::callable.

• Magma -

A type that belongs to the magma of interest.

template <class... Arguments>
struct math::is::idempotent

Whether an operation on a magma is idempotent. That is, whether the operation applied on the same value, it returns that value again. For example, if the operation returns the maximum of two elements, it is idempotent because max (a, a) == a.

It is possible to instantiate this with the standard type argument syntax, documented below, or with one argument in a cute syntax: Operation (Magma1, Magma2).

Templates
• Operation -

The operation, normally a type in namespace math::callable.

• Magma -

A type that belongs to the magma of interest.

template <class... Arguments>
struct math::is::path_operation

Whether an operation on a magma is a path operation. That is, whether the operation returns either the one or the other operand.

This implies idempotent <Magma, Operation>.

It is possible to instantiate this with the standard type argument syntax, documented below, or with one argument in a cute syntax: Operation (Magma1, Magma2).

Templates
• Operation -

The operation, normally a type in namespace math::callable.

• Magma -

A type that belongs to the magma of interest.

template <class... Arguments>
struct math::is::distributive

Whether an operation on a magma distributes over another operation on the same magma. For example, a semiring requires that a * (b + c) == (a * b) + (a * c). This is left distributivity; the mirror image is right distributivity.

It is possible to instantiate this with the standard type argument syntax, documented below, or with one argument in a cute syntax: OuterOperation (Magma1, InnerOperation (Magma2, Magma3)) (for left distributivity) or OuterOperation (InnerOperation (Magma1, Magma2), Magma3) (for right distributivity).

Templates
• Direction -

The direction of the distributivity: math::left, math::right, or math::either.

• OuterOperation -

The outer operation: in the example, times.

• InnerOperation -

The inner operation: in the example, plus.

• Magma -

A type that belongs to the magma of interest.

template <class Operation, class Magma>
struct math::is::monoid

Indicate whether a magma is a monoid. A monoid is a magma with an associative operation and an identity.

Templates
• Operation -

The operation, normally a type in namespace math::callable.

• Magma -

A type that belongs to the magma of interest.

template <class... Arguments>
struct math::is::semiring

Indicate whether a magma is a semiring. This describes a number of properties related to the magma’s behaviour under two operations, normally multiplication and addition.

Templates
• Direction -

The direction of interest. math::either makes this check whether Magma is a normal semiring. math::left or math::right can be used to check whether Magma is a left of right semiring.

• Multiplication -

The “multiply” operation, normally math::callable::times.

• Magma -

A type that belongs to the magma of interest.

#### Compile-time queries about nested call expressions¶

These are convenient ways of querying the availability or the results of an expression composed of magma operations. Internally, this uses the nested callable protocol for function objects.

template <class Expression>
struct math::has

Compile-time constant that returns whether a nested call expression has been implemented for a particular set of parameters.

Templates
• Expression -

The nested call expression of which the return type is sought.

struct math::result_of

Find the result of a nested call expression.

Templates
• Expression -

The nested call expression of which the return type is sought.

template <class... Arguments>
struct math::result_of_or

Find the result of a nested call expression, or the second argument. If no second argument is given, do not yield any type (useful to disable a function overload using SFINAE).

Templates
• Expression -

The nested call expression of which the return type is sought.

• Otherwise -

(optional) The type that should be returned if has <Expression> evaluates to false. If this is not given, then type will not be defined.

template <class Expression>
struct math::is::approximate

Compile-time constant that returns whether an operation is approximate for a particular set of parameters.

Templates
• Expression -

The nested call expression. If any single operation in the expression is approximate, the whole expression is assumed to be approximate. (This is the conservative approach.)

### Exception classes¶

The following types of exception can be thrown:

class math::magma_not_convertible

Exception that is thrown by the explicit constructor of a magma if the value passed in cannot be contained by the magma type to be constructed.

class math::operation_error

Exception that indicates an error while performing an inverse operation.

class math::operation_undefined

Exception that indicates that an inverse operation is not defined for the two values that it is called with.

class math::inverse_of_annihilator

Exception that indicates that the inverse of an annihilator was required. For example, an inverse operation was called with an annihilator as its second argument. Division by zero is an example of this.

class math::divide_by_zero

Exception that indicates that divide was called with (generalised) zero as its second argument.