# Type system

Type aliases, naming and compatibility with OpenGL and GLSL types.

### Contents

The root Magnum namespace defines a few aliases for essential types. See its documentation for more information about usage with CMake.

## Builtin types

Magnum provides typedefs for builtin integral and floating-point arithmetic types to ensure portability (e.g. Int is *always* 32bit), maintain consistency and reduce confusion (e.g. std::`int`

and `GLint`

all refer to the same type).

Magnum type | Size | Equivalent GLSL type |
---|---|---|

UnsignedByte | 8bit unsigned | |

Byte | 8bit signed | |

UnsignedShort | 16bit unsigned | |

Short | 16bit signed | |

UnsignedInt | 32bit unsigned | `uint` |

Int | 32bit signed | `int` |

UnsignedLong | 64bit unsigned | |

Long | 64bit signed | |

Half | 16bit | (none) |

Float | 32bit | `float` |

Double | 64bit | `double` |

Types not meant to be used in arithmetic (such as `bool`

or `std::size_t`

) or types which cannot be directly passed to GLSL shaders (such as `long double`

) have no typedefs.

Types from the above table are then used to define other types. All following types are aliases of corresponding types in Math namespace. No suffix after type name means Float underlying type, `ui`

means UnsignedInt underlying type, `i`

is Int underlying type and `d`

is for Double underlying type.

## Matrix/vector types

Magnum vector type | Equivalent GLSL type |
---|---|

Math:: | `bvec2` , `bvec3` , `bvec4` |

Vector2, Vector3, Color3, Vector4, Color4 | `vec2` , `vec3` , `vec4` |

Vector2ui, Vector3ui, Vector4ui | `uvec2` , `uvec3` , `uvec4` |

Vector2i, Vector3i, Vector4i | `ivec2` , `ivec3` , `ivec4` |

Vector2d, Vector3d, Vector4d | `dvec2` , `dvec3` , `dvec4` |

Color3ub, Color4ub | (none) |

Magnum matrix type | Equivalent GLSL type |
---|---|

Matrix2x2 or Matrix2x2d | `mat2` / `mat2x2` or `dmat2` / `dmat2x2` |

Matrix3 / Matrix3x3 or Matrix3d / Matrix3x3d | `mat3` / `mat3x3` or `dmat3` / `dmat3x3` |

Matrix4 / Matrix4x4 or Matrix4d / Matrix4x4d | `mat4` / `mat4x4` or `dmat4` / `dmat4x4` |

Matrix2x3 or Matrix2x3d | `mat2x3` or `dmat2x3` |

Matrix3x2 or Matrix3x2d | `mat3x2` or `dmat3x2` |

Matrix2x4 or Matrix2x4d | `mat2x4` or `dmat2x4` |

Matrix4x2 or Matrix4x2d | `mat4x2` or `dmat4x2` |

Matrix3x4 or Matrix3x4d | `mat3x4` or `dmat3x4` |

Matrix4x3 or Matrix4x3d | `mat4x3` or `dmat4x3` |

Any super- or sub-class of the same size and underlying type can be used equivalently (e.g. Math::

For easier entering of (s)RGB colors in hexadecimal format there are _

using namespace Math::Literals; Color3 a = 0x33b27f_srgbf; // {0.0331048f, 0.445201f, 0.212231f} Color4ub b = 0x33b27fcc_rgba; // {0x33, 0xb2, 0x7f, 0xcc}

## Binary representation

Scalar types with GLSL equivalent are verified to be exactly the same as corresponding `GL*`

types. Matrix and vector classes have the same binary representation as corresponding array of numeric values without any additional data or padding (e.g. `sizeof(Vector3i) == sizeof(Int[3])`

), all matrices are stored in column-major order.

This means that all scalar, matrix and vector types can be used directly for filling GPU buffers and textures without any need for data extraction or conversion. For convenience all vector and matrix classes provide data() function, which returns pointer to the internal data array.

## Special types

Magnum has special type for strongly-typed representation of angles, namely the Deg and Rad classes (or Degd and Radd with Double as underlying type). Their only purpose is to avoid common degree-vs-radian bugs (i.e. entering degree value where radians should be) and make the conversion between these two representations easier. They are just a tiny `constexpr`

wrapper around the native type and they support all meaningful numeric operations, so using them won't have any performance or usability impact in practice.

These classes are *not* implicitly constructible or convertible from/to Float or Double, you have to either construct/convert them explicitly or use custom _

using namespace Math::Literals; //Deg a = 60.0f // error, no implicit conversion from Float Deg a = 60.0_degf; // okay Float b = 3.2831853f; auto tau = Rad{b} + 3.0_radf; Radd pi = 3.141592653589793_rad; //Double c = pi; // error, no implicit conversion to Double auto c = Double(pi); // okay

They can be implicitly converted to each other, but conversion to different underlying type is *explicit* to avoid precision loss (or, on the other hand, unnecessarily high precision) during computations:

Rad d = 60.0_degf; // 1.0471976f auto e = Degd{pi}; // 180.0 //Rad f = pi; // error, no implicit conversion of underlying types auto f = Rad{pi}; // 3.141592654f

These classes are used exclusively in all functions taking and returning angles — trigonometry, angle computation, rotating transformation etc. Thanks to implicit conversion you can seamlessly use either radians or degrees without any need to care about what input the function expects:

Float a = Math::sin(1.32457_radf); Complex b = Complex::rotation(60.0_degf);

There is also a Half type for handling half-precision floating point values. By design it doesn't support any arithmetic operations as they would be done faster on single-precision, it's sole purpose is to make working with half-float values easier. It provides either explicit constructors and conversion operators from/to Float and UnsignedShort and you can also use the _

using namespace Math::Literals; Half a = 3.5_h; // 0x4300 internally

## Other types

Other types, which don't have their GLSL equivalent, are:

- QuadraticBezier2D or QuadraticBezier2Dd, QuadraticBezier3D or QuadraticBezier3Dd
- CubicBezier2D or CubicBezier2Dd, CubicBezier3D or CubicBezier3Dd
- Complex or Complexd, DualComplex or DualComplexd
- Frustum or Frustumd
- Quaternion or Quaterniond, DualQuaternion or DualQuaterniond
- Range1D / Range2D / Range3D, Range1Di / Range2Di / Range3Di or Range1Dd / Range2Dd / Range3Dd

These types can be used in GLSL either by extracting values from their underlying structure or converting them to types supported by GLSL (e.g. quaternion to matrix).

For your convenience, there is also alias for class with often used constants — Constants or Constantsd.

## Initialization

Vectors, general matrices and range types are by default zero-initialized, transformation types (square matrices, (dual) complex numbers and quaternions) are set to identity transformation. It is possible to initialize the instances differently using so-called *tags* or use the *tag* to make the choice appear explicit:

- Math::
ZeroInit zero-initializes the contents (works for all types). - Math::
IdentityInit initializes the contents to identity transformation (works only for transformation types, where it is also the default). - Math::
NoInit leaves the contents uninitialized (useful if you will overwrite the contents anyway, works for all types).

Example:

/* These are equivalent */ Vector3 a1; Vector3 a2{Math::ZeroInit}; /* These too */ Quaternion q1; Quaternion q2{Math::IdentityInit}; /* Avoid unnecessary initialization if is overwritten anyway */ Matrix4 projection{Math::NoInit}; if(orthographic) projection = Matrix4::orthographicProjection({4.0f, 3.0f}, 0.1f, 100.0f); else projection = Matrix4::perspectiveProjection(35.0_degf, 1.33f, 0.1f, 100.0f);