# Concepts¶

The Imath library emphasizes simplicity, ease of use, correctness and verifiability, performance, and breadth of adoption. Imath is not intended to be a comprehensive linear algebra or numerical analysis package.

Imath is not a substitute for Eigen! It’s not a full-featured linear algebra package, and it doesn’t represent vectors and matrices of arbitrary dimension. Its greatest utility is as a geometric data representation, primarily for 2D images and 3D scenes and coordinate transformations, along with an accompanying set of utility methods and functions.

## Example¶

A basic program:

#include <Imath/ImathMatrix.h>
#include <Imath/ImathVec.h>
#include <iostream>
#include <cassert>

int
main()
{
const Imath::V3f v (3.0f, 4.0f, 5.0f);

Imath::M44f M;
const Imath::V3f t(1.0f, 2.0f, 3.0f);
M.translate (t);

Imath::V3f p;
M.multVecMatrix(v, p);

std::cout << "What's your vector, Victor? " << p << std::endl;

Imath::V3f vt = v + t;
assert (p.equalWithAbsError(vt, 1e-6f));

return 0;
}


## Matrices Are Row-Major¶

Imath stores matrices in row-major layout, originally inspired by compatibility with OpenGL matrices.

A matrix described as:

$\begin{split}\begin{bmatrix} m_{00} & m_{01} & m_{02} & m_{03} \\ m_{10} & m_{11} & m_{12} & m_{13} \\ m_{20} & m_{21} & m_{22} & m_{23} \\ m_{30} & m_{31} & m_{32} & m_{33} \\ \end{bmatrix}\end{split}$

is laid out in memory as:

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

$$m_{00}$$

$$m_{01}$$

$$m_{02}$$

$$m_{03}$$

$$m_{10}$$

$$m_{11}$$

$$m_{12}$$

$$m_{13}$$

$$m_{20}$$

$$m_{21}$$

$$m_{22}$$

$$m_{23}$$

$$m_{30}$$

$$m_{31}$$

$$m_{32}$$

$$m_{33}$$

A matrix representing a homogeneous transform has a right-hand column of $$\begin{bmatrix} 0 & 0 & 0 & 1\end{bmatrix}$$ and the translation component across the bottom row.

As a result, it is best to think of Imath vectors as row-vectors, and vector-matrix multiplication with the vector on the left and matrix on the right:

$\begin{split}\begin{bmatrix} v_{0}' & v_{1}' & v_{2}' & 1' \end{bmatrix} = \begin{bmatrix} v_{0} & v_{1} & v_{2} & 1 \end{bmatrix} \begin{bmatrix} m_{00} & m_{01} & m_{02} & 0 \\ m_{10} & m_{11} & m_{12} & 0 \\ m_{20} & m_{21} & m_{22} & 0 \\ m_{30} & m_{31} & m_{32} & 1 \end{bmatrix}\end{split}$

This further implies that you should interpret local transformations as pre-multiplication:

M44f M;
M.translate (tx, ty, tz);
m.rotate (r, 0, 0);
m.scale (s);

$\begin{split}\begin{bmatrix} m_{00} & m_{01} & m_{02} & m_{03} \\ m_{10} & m_{11} & m_{12} & m_{13} \\ m_{20} & m_{21} & m_{22} & m_{23} \\ m_{30} & m_{31} & m_{32} & m_{33} \\ \end{bmatrix} = \begin{bmatrix} s & 0 & 0 & 0 \\ 0 & s & 0 & 0 \\ 0 & 0 & s & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & \cos(r) & \sin(r) & 0 \\ 0 & -\sin(r) & \cos(r) & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ tx & ty & tz & 1 \\ \end{bmatrix}\end{split}$