E.V.E
v2023.02.15
 
Loading...
Searching...
No Matches
Components Semantic

EVE provides a lot of function that operates on similar premises. This page gather the general behaviors EVE types and functions can exhibit.

Property of EVE types

Cardinal

For any value type, the cardinal is the number of elements it contains. This information is retrieved via the eve::cardinal type trait.

For any SIMD type T, eve::cardinal<T>::type evaluates to eve::fixed<N>, where N is the number of lanes of the underlying SIMD register.

Two types are said to be cardinal compatible if they have the same cardinal or at least one of them is a scalar type.

Element type

For any value type, its underlying element type is the type used to represent its internal values. This information is retrieved via the eve::element_type type trait.

ABI traits

SIMD type internals depend on the actual architecture and instruction set available. This information is retrieved via the eve::abi_of type trait.

  • When the type is based on a native SIMD register, the resulting types is architecture defined.
  • When the type is an aggregation of multiple SIMD registers, the resulting type is eve::aggregated_.
  • When the type uses an emulated SIMD register, the resulting type is eve::emulated_.
  • When the type elements are tuple-like, the resulting type is eve::bundle_.

Operations Classification

Generalized Element Access

EVE functions' semantics rely on a generic way to access an element of a value, be it scalar or SIMD.

To do so, we define a synthetic function get(v,i) that retrieve the ith element of a value v.

template<eve::value V, std::integral I> auto get(V const& v, I i)
{
if constexpr( eve::simd_value<V>) return v.get(i);
else return v;
}
Specifies that a type is a SIMD type. The concept simd_value<T> is satisfied if and only if T satisfi...
Definition: vectorized.hpp:33

Element-wise Operations

For any values x1, ..., xn of types T1, ..., Tn , a Callable Object f returning a value of type R is said to be Element-wise if the expression R r = f(x1, ...,xn) is semantically equivalent to:

Reductions

For any SIMD value x of type T, a Callable Object f returning a scalar value of type R is said to be a Reduction if the expression R r = f(x) is semantically equivalent to:

R r = f(get(x,0), ..., get(x,cardinal_v<T>-1));

Most reduction operations are not defined on scalar values unless their definition is required by the internal implementation.

Function Semantic

Arithmetic Functions

For any values x1, ..., xn of types T1, ..., Tn so that the expression using C = eve::common_compatible_t<T1,...,Tn> is valid, a Callable Object f is said to be an Arithmetic Function if the expression C r = f(x1, ...,xn) is semantically equivalent to:

  • if C models eve::simd_value:
    C r = [](auto i, auto) { return f(get(C(x1),i), ..., get(C(xn),i)); };
  • if C models eve::scalar_value:
    C r = f(C(x1), ..., C(xn));

In a less formal way, EVE Arithmetic Functions generalizes the notion of native C++ arithmetic operations. By construction, a large majority of Arithmetic Functions are de facto Element-wise Operations.

Logical Functions

EVE Logical Functions are Arithmetic Functions that can only be applied to logical values L1, ..., Ln as long as they are all cardinal-compatible. By construction, a large majority of glossary_bitwise are de facto Element-wise Operations.

Constant Functions

General Principles

EVE constant generator are Callable Object that takes a single argument of type eve::as. This argument provides the information about the type used to generate the constant. E.g:

auto z = eve::zero(as<int>()); // equivalent to auto z = static_cast<int>(0);
auto vp = eve::half(as<wide<float>>()); // equivalent to auto vp = wide<float>(0.5);
constexpr auto half
Computes the constant .
Definition: half.hpp:66
constexpr auto zero
Computes the constant 0.
Definition: zero.hpp:78

Precision handling

Some constants are exactly representable in IEEE754 types. However, some mathematical constants can be under-represented on a given type while simultaneously be over-represented on other. For example, \(\pi\) in float is greater than its mathematical value. Meanwhile \(\pi\) in double is less than its mathematical value.

The constant implementation is so that, for any constant generator g:

  • g(eve::as<T>())returns the nearest representable value of the mathematical constant
  • eve::downward(g)(eve::as<T>())returns a value no lesser than 0.5 ULP from the mathematical constant
  • eve::upward(g)(eve::as<T>())returns a value no greater than 0.5 ULP from the mathematical constant

For all constants, eve::downward(g)(eve::as<T>()) <= g(eve::as<T>()) <= eve::upward(g)(eve::as<T>()) is always verified.

We encourage user facing issue with reproducible computation to use those decorators to make all constant generation stable across types.