Рефакторинг матриц в dlib

На днях состоялось грандиозное обновление пакета линейной алгебры dlib.math. Изменения коснулись, главным образом, реализации матриц. Если раньше матрицы 2×2, 3×3 и 4×4 имели каждая отдельную независимую реализацию, то теперь все они являются частными случаями обобщенной квадратной матрицы Matrix!(T,N) (где T – тип элементов, N – размерность). Она содержит все необходимые общие методы для матриц любого размера (нахождение определителя, нахождение обратной матрицы, нахождение матрицы миноров и алгебраических дополнений и т.д.), оптимизированные, где это возможно, для размерностей 2, 3 и 4. Таким образом, нынешние специализации Matrix2x2f, Matrix3x3f и Matrix4x4f практически идентичны их прежним аналогам.

Новая реализация создана с учетом обратной совместимости, но все-таки есть несколько критичных изменений:

1. Больше нет шаблонов Matrix2x2!(T), Matrix3x3!(T), Matrix4x4!(T). Используйте вместо них Matrix!(T,2), Matrix!(T,3) и Matrix!(T,4). При этом псевдонимы на специализации типа Matrix2x2f и Matrix4x4d сохранены;

2. Нет доступа к элементам матриц 4×4 через поля m*, t* и h*. Возможен только доступ через поля a*. Это справедливо для матриц любого размера:

a11 a12 a13 a14 .. a1N
a21 a22 a23 a24 .. a2N
a31 a32 a33 a34 .. a3N
a41 a42 a43 a44 .. a4N
 :   :   :   :  .
aN1 aN2 aN3 aN4  ' aNN

2. Все аффинные преобразования (функции rotationMatrix, translationMatrix и др.) и утилитарные функции для матриц вынесены в отдельный модуль dlib.math.affine. Там же находятся функции right, up, forward, translation, scaling, которые раньше были опрелены как методы в Matrix4x4!(T). Благодаря UFCS, их и теперь можно использовать как методы – однако все они теперь представляют собой свойства только для чтения. Пока они определены только для Matrix!(T,4), но в будущем функции базиса (right, up, forwartd) будут доступны и для Matrix!(T,3).

3. В целях обратной совместимости сохраняются модули dlib.math.matrix2x2, dlib.math.matrix3x3, dlib.math.matrix4x4, но они помечены как deprecated. Вместо них импортируйте dlib.math.matrix (и dlib.math.affine, если вам нужны аффинные преобразования)

2. Не рекомендуется использовать identityMatrix3x3!(T) и identityMatrix4x4!(T). Единичные матрицы создаются при помощи статического метода identity: например, Matrix3x3f.identity.

3. Не рекомендуется трансформировать векторы методом transform. Вместо этого лучше использовать умножение вектора на матрицу: Vector3f(1, 2, 3) * myMatrix.

4. Любые матрицы можно создавать при помощи функции-фабрики matrixf, которая автоматически определяет размерность на основе входных данных:

auto m1 = matrixf(
    8, 3, 2, 0,
    4, 0, 2, 0,
    1, 3, 3, 0,
    0, 0, 3, 1
);

Это выражение создаст матрицу типа Matrix!(float,4) и присвоит ее переменной m1.

Убедительная просьба всем пользователям dlib сообщить мне (в Issues в репозитории на GitHub, либо на почту – gecko0307@gmail.com), если будут обнаружены какие-то несостыковки и баги, связанные с данным рефакторингом матриц.