293 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
			
		
		
	
	
			293 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
| ==================
 | ||
| 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.
 |