# Number Representation

When specifying extents, positions inside of, or bounds of a container, numeric values can be represented three different ways: `fixed`, `aligned`, and `int`. `Fixed` is most precise and `int` is least precise. It is advised to use as precise specification as possible. The compiler may optimize better with more information.

## Fixed

Represent a numerical constant whose value specified at compile time.

    template <int NumberT> class fixed;

If offsets applied to index values inside a SIMD loop are known at compile time, then the compiler can use that information. For example, to maintain aligned access, if boundary is fixed and known to be aligned when accessing underlying data layout. When multiple accesses are happening near each other, the compiler will have the opportunity to detect which accesses occur in the same cache lines and potentially avoid prefetching the same cache line repeatedly. Additionally, if the start of an iteration space is known at compile time, if it's a multiple of the SIMD lane count, the compiler could skip generating a peel loop. Whenever possible, `fixed` values should be used over `aligned` or arbitrary integer values.

Although `std::integral_constant<int>` provides the same functionality, the library defines own type to provide overloaded operators and avoid collisions with any other code's interactions with `std::integral_constant<int>`.

The following table provides information about the template arguments for `fixed`.

Template Argument | Description
--- | ---
    int Number T
| The numerical value the fixed will represent.

The following table provides information about the members of `fixed`.

Member | Description
--- | ---
    static constexpr int value = NumberT
| The numerical value known at compile-time.
    constexpr operator value_type() const
| Returns: The numerical value
    constexpr value_type operator()() const;
| Returns: The numerical value

Constant expression arithmetic operators +,- (both unary and binary), * and / are defined for type `sdlt::fixed<>` and will be evaluated at compile-time.

The suffix `_fixed` is a C++11 user-defined equivalent literal. For example, `1080_fixed` is equivalent to `fixed<1080>`. Consider the readability of the two samples below.

    foo3d(fixed<1080>(), fixed<1920>());

versus

    foo3d(1080_fixed, 1920_fixed);

### Note

This content is specific to C++; it does not apply to DPC++. The `sdlt::fixed<NumberT>` type supersedes the deprecated `sdlt::fixed_offset<OffsetT>` type found in SDLT v1. It is strongly advised to use `sdlt::fixed<NumberT>`. However, in this release, a template alias is provided mapping `sdlt::fixed_offset<OffsetT>` onto `sdlt::fixed<NumberT>`.

## Aligned

Represent integer value known at compile time to be a multiple of an `IndexAlignment`.

    template <int IndexAlignmentT> class aligned;

If you can tell the compiler that you know that an integer will be a multiple of known value, then, when combined with a loop index inside a SIMD loop, the compiler can use that information to maintain aligned access when accessing underlying data layout.

Internally, the integer value is converted to a block count, where:

    block_count = value/IndexAlignmentT;

Overloaded math operations can then use that aligned block count as needed. The value() is represented by `AlignmentT*block_count` allowing the compiler to easily prove that the value() is a multiple of `AlignmentT`, which can utilize alignment optimizations.

The following table provides information about the template arguments for `aligned`.

Template Argument | Description
--- | ---
    int IndexAlignmentT
| The alignment the user is stating that the number is a multiple of. `IndexAlignmentT` must be a power of two.

The following table provides information about the types defined as members of `aligned`.

Member Type | Description
--- | ---
    typedef int value_type
| The type of the numerical value.
    typedef int block_type
| The type of the `block_count`.

The following table provides information about the members of `aligned`.

Member | Description
--- | ---
    static const int index_alignment
| The `IndexAlignmentT` value.
    aligned()
| Constructs empty (uninitialized) object
    explicit aligned(value_type)
| Constructs computing `block_count=a_value/IndexAlignmentT`.
    aligned(const aligned& a_other)
| Constructs copying `block_count` from `a_other`. `a_other` must have same `IndexAlignmentT.`
    template<int OtherAlignment>
    explicit aligned(const aligned& other)
| Constructs computing `block_count` optimized by avoiding computing other.value(). Must have `IndexAlignmentT` of a_other < `IndexAlignmentT` and other.value() be multiple of `IndexAlignmentT`.
    template<int OtherAlignment>
    aligned(const aligned& other)
| Constructs computing `block_count` with a multiply instead of divide. Must have `IndexAlignmentT` of a_other > `IndexAlignmentT`
    static aligned from_block_count(block_type block_count)
| Creates an instance of `aligned` avoiding any math by directly using supplied `block_count`
    value_type value() const
| Computes the value represented by the aligned. Returns:`aligned_block_count()*IndexAlignmentT`
    operator value_type()
| Conversion to `int`. Returns:`value()`
    block_type aligned_block_count() const
| Conversion to `int`. Returns: The block count

The following operations are supported for the `aligned` type.

Operation | Description
--- | ---
    operator *(int), commutative
| Scale value. Returns: `aligned<IndexAlignmentT >`
    operator *(fixed<V>), commutative
| Scales `IndexAlignment` by 2^M and value by K. Must have V=2^M*K (V is a multiple of a power of 2). Returns:`aligned<IndexAlignmentT*(2^M)>`
    operator *(aligned<OtherAl>)
| Scales `IndexAlignment` by `OtherAl` and `block_count` by argument. Returns:`aligned<IndexAlignmentT*OtherAl>`
    int operator/(fixed<IndexAlignmentT>)
| Returns:`aligned_block_count()`
    int operator/(fixed<-IndexAlignmentT>)
| Returns:`-aligned_block_count();`
    int operator/(fixed<V>)
| Must have `abs(V)>IndexAlignmentT && IndexAlignmentT%V==0`. Returns:`aligned_block_count()/(V/IndexAlignmentT)`
    int operator/(fixed<V>)
| Must have `abs(V) < IndexAlignmentT && V%IndexAlignmentT==0` Returns:`aligned_block_count()*(IndexAlignmentT/V)`
    aligned operator -()
| Returns: Same type aligned for negated value.
    aligned operator -(const aligned &)
                    const
| Returns: Same type aligned for value of difference.
    template<int OtherAl>
    aligned<?> operator -(const aligned<OtherAl>&) const
| Difference with other alignment. Behavior and returned alignment type depend on relation between alignments of operands. Returns: Value for difference as lower of incoming alignments
    template<int V>
    aligned<?> operator -(const fixed<V> &) const
| Difference with fixed value. Behavior and returned alignment type depend on relation between alignments of aligned<> operand and the value of V. Returns: Adjusted aligned value of a difference
    aligned operator +(const aligned &)const
| Returns: Same type aligned for value of sum
    template<int OtherAl>
    aligned<?> operator +(const aligned<OtherAl>&) const
| Sum with other alignment. Behavior and returned alignment type depend on relation between alignments of operands. Returns: Value for sum as lower of incoming alignments
    template<int V>
    aligned<?> operator +(const fixed<V> &) const
| Sum with fixed value. Behavior and returned alignment type depend on relation between alignments of aligned<> operand and the value of V. Returns: Adjusted aligned value of a sum.
    template<int OtherAl>
    aligned operator +=(const aligned<OtherAl> &) const
| Increments value for the aligned object if `IndexAlignmentT` is compatible with `OtherAl` Returns: Aligned with incremented value.
    template<int OtherAl>
    aligned operator -=(const aligned<OtherAl> &) const
| Decrements value for the aligned object if `IndexAlignmentT` is compatible with `OtherAl` Returns: Same type aligned with decremented value.
    template<int OtherAl>
    aligned operator *=(const aligned<OtherAl> &) const
| Multiplies value for the aligned object if `IndexAlignmentT` is compatible with `OtherAl`. Returns: Same type aligned with multiplied value.
    template<int OtherAl>
    aligned operator /=(const aligned<OtherAl> &) const
| Divides value for the aligned object if `IndexAlignmentT` is compatible with `OtherAl` Returns: Same type aligned with divided value.

### Note

This content is specific to C++; it does not apply to DPC++. The `sdlt::aligned<>` type supersedes the deprecated `sdlt::aligned_offset<>` type found in SDLT v1. It is strongly advised to use `sdlt::aligned<>`, however in this release a template alias is provided mapping `sdlt::aligned_offset<>` onto `sdlt::aligned<>`.

## int

Represents an arbitrary integer value. In interfaces where fixed<> and aligned<> values supported you may also use plain old integer value. It provides least information among these three and so least facilitates compiler optimizations.

Parent topic: User-Level Interface

- aligned_offset
  Represent an integer based offset whose value is a multiple of an IndexAlignment specified at compile time. `#include <sdlt/aligned_offset.h>`
- fixed_offset
  Represent an integer based offset whose value specified at compile time. `#include <sdlt/fixed_offset.h>`