================== | |

Matrix Types | |

================== | |

.. contents:: | |

:local: | |

.. _matrixtypes: | |

Clang provides a C/C++ language extension that allows users to directly express | |

fixed-size 2-dimensional matrices as language values and perform arithmetic on | |

them. | |

This feature is currently experimental, and both its design and its | |

implementation are in flux. | |

Draft Specification | |

=================== | |

Matrix Type | |

----------- | |

A matrix type is a scalar type with an underlying *element type*, a constant | |

number of *rows*, and a constant number of *columns*. Matrix types with the same | |

element type, rows, and columns are the same type. A value of a matrix type | |

includes storage for ``rows * columns`` values of the *element type*. The | |

internal layout, overall size and alignment are implementation-defined. | |

The maximum of the product of the number of rows and columns is | |

implementation-defined. If that implementation-defined limit is exceeded, the | |

program is ill-formed. | |

Currently, the element type of a matrix is only permitted to be one of the | |

following types: | |

* an integer type (as in C2x 6.2.5p19), but excluding enumerated types and ``_Bool`` | |

* the standard floating types ``float`` or ``double`` | |

* a half-precision floating point type, if one is supported on the target | |

Other types may be supported in the future. | |

Matrix Type Attribute | |

--------------------- | |

Matrix types can be declared by adding the ``matrix_type`` attribute to the | |

declaration of a *typedef* (or a C++ alias declaration). The underlying type | |

of the *typedef* must be a valid matrix element type. The | |

attribute takes two arguments, both of which must be integer constant | |

expressions that evaluate to a value greater than zero. The first specifies the | |

number of rows, and the second specifies the number of columns. The underlying | |

type of the *typedef* becomes a matrix type with the given dimensions and an | |

element type of the former underlying type. | |

If a declaration of a *typedef-name* has a ``matrix_type`` attribute, then all | |

declaration of that *typedef-name* shall have a matrix_type attribute with the | |

same element type, number of rows, and number of columns. | |

Standard Conversions | |

-------------------- | |

The standard conversions are extended as follows. Note that these conversions | |

are intentionally not listed as satisfying the constraints for assignment, | |

which is to say, they are only permitted as explicit casts, not as implicit | |

conversions. | |

A value of matrix type can be converted to another matrix type if the number of | |

rows and columns are the same and the value's elements can be converted to the | |

element type of the result type. The result is a matrix where each element is | |

the converted corresponding element. | |

A value of any real type (as in C2x 6.2.5p17) can be converted to a matrix type | |

if it can be converted to the element type of the matrix. The result is a | |

matrix where all elements are the converted original value. | |

If the number of rows or columns differ between the original and resulting | |

type, the program is ill-formed. | |

Arithmetic Conversions | |

---------------------- | |

The usual arithmetic conversions are extended as follows. | |

Insert at the start: | |

* If both operands are of matrix type, no arithmetic conversion is performed. | |

* If one operand is of matrix type and the other operand is of a real type, | |

convert the real type operand to the matrix type | |

according to the standard conversion rules. | |

Matrix Type Element Access Operator | |

----------------------------------- | |

An expression of the form ``E1 [E2] [E3]``, where ``E1`` has matrix type ``cv | |

M``, is a matrix element access expression. Let ``T`` be the element type | |

of ``M``, and let ``R`` and ``C`` be the number of rows and columns in ``M`` | |

respectively. The index expressions shall have integral or unscoped | |

enumeration type and shall not be uses of the comma operator unless | |

parenthesized. The first index expression shall evaluate to a | |

non-negative value less than ``R``, and the second index expression shall | |

evaluate to a non-negative value less than ``C``, or else the expression has | |

undefined behavior. If ``E1`` is a prvalue, the result is a prvalue with type | |

``T`` and is the value of the element at the given row and column in the matrix. | |

Otherwise, the result is a glvalue with type ``cv T`` and with the same value | |

category as ``E1`` which refers to the element at the given row and column in | |

the matrix. | |

Programs containing a single subscript expression into a matrix are ill-formed. | |

**Note**: We considered providing an expression of the form | |

``postfix-expression [expression]`` to access columns of a matrix. We think | |

that such an expression would be problematic once both column and row major | |

matrixes are supported: depending on the memory layout, either accessing columns | |

or rows can be done efficiently, but not both. Instead, we propose to provide | |

builtins to extract rows and columns from a matrix. This makes the operations | |

more explicit. | |

Matrix Type Binary Operators | |

---------------------------- | |

Given two matrixes, the ``+`` and ``-`` operators perform element-wise addition | |

and subtraction, while the ``*`` operator performs matrix multiplication. | |

``+``, ``-``, ``*``, and ``/`` can also be used with a matrix and a scalar | |

value, applying the operation to each element of the matrix. | |

Earlier versions of this extension did not support division by a scalar. | |

You can test for the availability of this feature with | |

``__has_extension(matrix_types_scalar_division)``. | |

For the expression ``M1 BIN_OP M2`` where | |

* ``BIN_OP`` is one of ``+`` or ``-``, one of ``M1`` and ``M2`` is of matrix | |

type, and the other is of matrix type or real type; or | |

* ``BIN_OP`` is ``*``, one of ``M1`` and ``M2`` is of matrix type, and the | |

other is of a real type; or | |

* ``BIN_OP`` is ``/``, ``M1`` is of matrix type, and ``M2`` is of a real type: | |

* The usual arithmetic conversions are applied to ``M1`` and ``M2``. [ Note: if ``M1`` or | |

``M2`` are of a real type, they are broadcast to matrices here. — end note ] | |

* ``M1`` and ``M2`` shall be of the same matrix type. | |

* The result is equivalent to Res in the following where col is the number of | |

columns and row is the number of rows in the matrix type: | |

.. code-block:: c++ | |

decltype(M1) Res; | |

for (int C = 0; C < col; ++C) | |

for (int R = 0; R < row; ++R) | |

Res[R][C] = M1[R][C] BIN_OP M2[R][C]; | |

Given the expression ``M1 * M2`` where ``M1`` and ``M2`` are of matrix type: | |

* The usual arithmetic conversions are applied to ``M1`` and ``M2``. | |

* The type of ``M1`` shall have the same number of columns as the type of ``M2`` has | |

rows. The element types of ``M1`` and ``M2`` shall be the same type. | |

* The resulting type, ``MTy``, is a matrix type with the common element type, | |

the number of rows of ``M1`` and the number of columns of ``M2``. | |

* The result is equivalent to ``Res`` in the following where ``EltTy`` is the | |

element type of ``MTy``, ``col`` is the number of columns, ``row`` is the | |

number of rows in ``MTy`` and ``inner`` is the number of columns of ``M1``: | |

.. code-block:: c++ | |

MTy Res; | |

for (int C = 0; C < col; ++C) { | |

for (int R = 0; R < row; ++R) { | |

EltTy Elt = 0; | |

for (int K = 0; K < inner; ++K) { | |

Elt += M1[R][K] * M2[K][C]; | |

} | |

Res[R][C] = Elt; | |

} | |

All operations on matrix types match the behavior of the element type with | |

respect to signed overflows. | |

With respect to floating-point contraction, rounding and environment rules, | |

operations on matrix types match the behavior of the elementwise operations | |

in the corresponding expansions provided above. | |

Operations on floating-point matrices have the same rounding and floating-point | |

environment behavior as ordinary floating-point operations in the expression's | |

context. For the purposes of floating-point contraction, all calculations done | |

as part of a matrix operation are considered intermediate operations, and their | |

results need not be rounded to the format of the element type until the final | |

result in the containing expression. This is subject to the normal restrictions | |

on contraction, such as ``#pragma STDC FP_CONTRACT``. | |

For the ``+=``, ``-=`` and ``*=`` operators the semantics match their expanded | |

variants. | |

Matrix Type Builtin Operations | |

------------------------------ | |

Each matrix type supports a collection of builtin expressions that look like | |

function calls but do not form an overload set. Here they are described as | |

function declarations with rules for how to construct the argument list types | |

and return type and the library description elements from | |

[library.description.structure.specifications]/3 in the C++ standard. | |

Definitions: | |

* *M*, *M1*, *M2*, *M3* - Matrix types | |

* *T* - Element type | |

* *row*, *col* - Row and column arguments respectively. | |

``M2 __builtin_matrix_transpose(M1 matrix)`` | |

**Remarks**: The return type is a cv-unqualified matrix type that has the same | |

element type as ``M1`` and has the the same number of rows as ``M1`` has columns and | |

the same number of columns as ``M1`` has rows. | |

**Returns**: A matrix ``Res`` equivalent to the code below, where ``col`` refers to the | |

number of columns of ``M``, and ``row`` to the number of rows of ``M``. | |

**Effects**: Equivalent to: | |

.. code-block:: c++ | |

M Res; | |

for (int C = 0; C < col; ++C) | |

for (int R = 0; R < row; ++R) | |

Res[C][R] = matrix[R][C]; | |

``M __builtin_matrix_column_major_load(T *ptr, size_t row, size_t col, size_t columnStride)`` | |

**Mandates**: ``row`` and ``col`` shall be integral constants greater than 0. | |

**Preconditions**: ``columnStride`` is greater than or equal to ``row``. | |

**Remarks**: The return type is a cv-unqualified matrix type with an element | |

type of the cv-unqualified version of ``T`` and a number of rows and columns equal | |

to ``row`` and ``col`` respectively. The parameter ``columnStride`` is optional | |

and if omitted ``row`` is used as ``columnStride``. | |

**Returns**: A matrix ``Res`` equivalent to: | |

.. code-block:: c++ | |

M Res; | |

for (size_t C = 0; C < col; ++C) { | |

for (size_t R = 0; R < row; ++K) | |

Res[R][C] = ptr[R]; | |

ptr += columnStride | |

} | |

``void __builtin_matrix_column_major_store(M matrix, T *ptr, size_t columnStride)`` | |

**Preconditions**: ``columnStride`` is greater than or equal to the number of rows in ``M``. | |

**Remarks**: The type ``T`` is the const-unqualified version of the matrix | |

argument’s element type. The parameter ``columnStride`` is optional and if | |

omitted, the number of rows of ``M`` is used as ``columnStride``. | |

**Effects**: Equivalent to: | |

.. code-block:: c++ | |

for (size_t C = 0; C < columns in M; ++C) { | |

for (size_t R = 0; R < rows in M; ++K) | |

ptr[R] = matrix[R][C]; | |

ptr += columnStride | |

} | |

TODOs | |

----- | |

TODO: Does it make sense to allow M::element_type, M::rows, and M::columns | |

where M is a matrix type? We don’t support this anywhere else, but it’s | |

convenient. The alternative is using template deduction to extract this | |

information. Also add spelling for C. | |

Future Work: Initialization syntax. | |

Decisions for the Implementation in Clang | |

========================================= | |

This section details decisions taken for the implementation in Clang and is not | |

part of the draft specification. | |

The elements of a value of a matrix type are laid out in column-major order | |

without padding. | |

We propose to provide a Clang option to override this behavior and allow | |

contraction of those operations (e.g. *-ffp-contract=matrix*). | |

TODO: Specify how matrix values are passed to functions. |