Speed up matrix operations (unit-wise, no interface is touched)

This commit is contained in:
Stephan Lenor 2023-03-25 06:06:38 +01:00 committed by Jehan
parent 82d5743e77
commit f5cc64ddd6
2 changed files with 92 additions and 92 deletions

View file

@ -221,27 +221,26 @@ gimp_matrix2_identity (GimpMatrix2 *matrix)
/** /**
* gimp_matrix2_mult: * gimp_matrix2_mult:
* @matrix1: The first input matrix. * @left: The first input matrix.
* @matrix2: The second input matrix which will be overwritten by the result. * @right: The second input matrix which will be overwritten by the result.
* *
* Multiplies two matrices and puts the result into the second one. * Multiplies two matrices and puts the result into the second one.
*/ */
void void
gimp_matrix2_mult (const GimpMatrix2 *matrix1, gimp_matrix2_mult (const GimpMatrix2 *left,
GimpMatrix2 *matrix2) GimpMatrix2 *right)
{ {
GimpMatrix2 tmp; gdouble r00 = right->coeff[0][0];
gdouble r01 = right->coeff[0][1];
tmp.coeff[0][0] = (matrix1->coeff[0][0] * matrix2->coeff[0][0] + right->coeff[0][0] = (left->coeff[0][0] * r00 +
matrix1->coeff[0][1] * matrix2->coeff[1][0]); left->coeff[0][1] * right->coeff[1][0]);
tmp.coeff[0][1] = (matrix1->coeff[0][0] * matrix2->coeff[0][1] + right->coeff[0][1] = (left->coeff[0][0] * r01 +
matrix1->coeff[0][1] * matrix2->coeff[1][1]); left->coeff[0][1] * right->coeff[1][1]);
tmp.coeff[1][0] = (matrix1->coeff[1][0] * matrix2->coeff[0][0] + right->coeff[1][0] = (left->coeff[1][0] * r00 +
matrix1->coeff[1][1] * matrix2->coeff[1][0]); left->coeff[1][1] * right->coeff[1][0]);
tmp.coeff[1][1] = (matrix1->coeff[1][0] * matrix2->coeff[0][1] + right->coeff[1][1] = (left->coeff[1][0] * r01 +
matrix1->coeff[1][1] * matrix2->coeff[1][1]); left->coeff[1][1] * right->coeff[1][1]);
*matrix2 = tmp;
} }
/** /**
@ -519,34 +518,36 @@ gimp_matrix3_transform_point (const GimpMatrix3 *matrix,
/** /**
* gimp_matrix3_mult: * gimp_matrix3_mult:
* @matrix1: The first input matrix. * @left: The first input matrix.
* @matrix2: The second input matrix which will be overwritten by the result. * @right: The second input matrix which will be overwritten by the result.
* *
* Multiplies two matrices and puts the result into the second one. * Multiplies two matrices and puts the result into the second one.
*/ */
void void
gimp_matrix3_mult (const GimpMatrix3 *matrix1, gimp_matrix3_mult (const GimpMatrix3 *left,
GimpMatrix3 *matrix2) GimpMatrix3 *right)
{ {
gint i, j; gint i;
GimpMatrix3 tmp; gdouble li0, li1, li2;
gdouble t1, t2, t3; gdouble r00 = right->coeff[0][0];
gdouble r01 = right->coeff[0][1];
gdouble r02 = right->coeff[0][2];
gdouble r10 = right->coeff[1][0];
gdouble r11 = right->coeff[1][1];
gdouble r12 = right->coeff[1][2];
gdouble r20 = right->coeff[2][0];
gdouble r21 = right->coeff[2][1];
gdouble r22 = right->coeff[2][2];
for (i = 0; i < 3; i++) for (i = 0; i < 3; i++)
{ {
t1 = matrix1->coeff[i][0]; li0 = left->coeff[i][0];
t2 = matrix1->coeff[i][1]; li1 = left->coeff[i][1];
t3 = matrix1->coeff[i][2]; li2 = left->coeff[i][2];
right->coeff[i][0] = li0 * r00 + li1 * r10 + li2 * r20;
for (j = 0; j < 3; j++) right->coeff[i][1] = li0 * r01 + li1 * r11 + li2 * r21;
{ right->coeff[i][2] = li0 * r02 + li1 * r12 + li2 * r22;
tmp.coeff[i][j] = t1 * matrix2->coeff[0][j];
tmp.coeff[i][j] += t2 * matrix2->coeff[1][j];
tmp.coeff[i][j] += t3 * matrix2->coeff[2][j];
}
} }
*matrix2 = tmp;
} }
/** /**
@ -718,19 +719,15 @@ gimp_matrix3_affine (GimpMatrix3 *matrix,
gdouble gdouble
gimp_matrix3_determinant (const GimpMatrix3 *matrix) gimp_matrix3_determinant (const GimpMatrix3 *matrix)
{ {
gdouble determinant; gdouble m01 = matrix->coeff[0][1];
gdouble m02 = matrix->coeff[0][2];
determinant = (matrix->coeff[0][0] * gdouble m11 = matrix->coeff[1][1];
(matrix->coeff[1][1] * matrix->coeff[2][2] - gdouble m12 = matrix->coeff[1][2];
matrix->coeff[1][2] * matrix->coeff[2][1])); gdouble m21 = matrix->coeff[2][1];
determinant -= (matrix->coeff[1][0] * gdouble m22 = matrix->coeff[2][2];
(matrix->coeff[0][1] * matrix->coeff[2][2] - return matrix->coeff[0][0] * (m11 * m22 - m12 * m21)
matrix->coeff[0][2] * matrix->coeff[2][1])); - matrix->coeff[1][0] * (m01 * m22 - m02 * m21)
determinant += (matrix->coeff[2][0] * + matrix->coeff[2][0] * (m01 * m12 - m02 * m11);
(matrix->coeff[0][1] * matrix->coeff[1][2] -
matrix->coeff[0][2] * matrix->coeff[1][1]));
return determinant;
} }
/** /**
@ -742,44 +739,40 @@ gimp_matrix3_determinant (const GimpMatrix3 *matrix)
void void
gimp_matrix3_invert (GimpMatrix3 *matrix) gimp_matrix3_invert (GimpMatrix3 *matrix)
{ {
GimpMatrix3 inv; gdouble det;
gdouble det; gdouble m00 = matrix->coeff[0][0];
gdouble m01 = matrix->coeff[0][1];
gdouble m02 = matrix->coeff[0][2];
gdouble m10 = matrix->coeff[1][0];
gdouble m11 = matrix->coeff[1][1];
gdouble m12 = matrix->coeff[1][2];
gdouble m20 = matrix->coeff[2][0];
gdouble m21 = matrix->coeff[2][1];
gdouble m22 = matrix->coeff[2][2];
det = gimp_matrix3_determinant (matrix); /* To avoid redundant access to the coefficients, inline the determinant
* formula.
*
* See: https://gitlab.gnome.org/GNOME/gimp/-/merge_requests/880#note_1727051
*/
det = m00 * (m11 * m22 - m12 * m21)
- m10 * (m01 * m22 - m02 * m21)
+ m20 * (m01 * m12 - m02 * m11);
if (det == 0.0) if (det == 0.0)
return; return;
det = 1.0 / det; det = 1.0 / det;
inv.coeff[0][0] = (matrix->coeff[1][1] * matrix->coeff[2][2] - matrix->coeff[0][0] = (m11 * m22 - m12 * m21) * det;
matrix->coeff[1][2] * matrix->coeff[2][1]) * det; matrix->coeff[1][0] = - (m10 * m22 - m12 * m20) * det;
matrix->coeff[2][0] = (m10 * m21 - m11 * m20) * det;
inv.coeff[1][0] = - (matrix->coeff[1][0] * matrix->coeff[2][2] - matrix->coeff[0][1] = - (m01 * m22 - m02 * m21) * det;
matrix->coeff[1][2] * matrix->coeff[2][0]) * det; matrix->coeff[1][1] = (m00 * m22 - m02 * m20) * det;
matrix->coeff[2][1] = - (m00 * m21 - m01 * m20) * det;
inv.coeff[2][0] = (matrix->coeff[1][0] * matrix->coeff[2][1] - matrix->coeff[0][2] = (m01 * m12 - m02 * m11) * det;
matrix->coeff[1][1] * matrix->coeff[2][0]) * det; matrix->coeff[1][2] = - (m00 * m12 - m02 * m10) * det;
matrix->coeff[2][2] = (m00 * m11 - m01 * m10) * det;
inv.coeff[0][1] = - (matrix->coeff[0][1] * matrix->coeff[2][2] -
matrix->coeff[0][2] * matrix->coeff[2][1]) * det;
inv.coeff[1][1] = (matrix->coeff[0][0] * matrix->coeff[2][2] -
matrix->coeff[0][2] * matrix->coeff[2][0]) * det;
inv.coeff[2][1] = - (matrix->coeff[0][0] * matrix->coeff[2][1] -
matrix->coeff[0][1] * matrix->coeff[2][0]) * det;
inv.coeff[0][2] = (matrix->coeff[0][1] * matrix->coeff[1][2] -
matrix->coeff[0][2] * matrix->coeff[1][1]) * det;
inv.coeff[1][2] = - (matrix->coeff[0][0] * matrix->coeff[1][2] -
matrix->coeff[0][2] * matrix->coeff[1][0]) * det;
inv.coeff[2][2] = (matrix->coeff[0][0] * matrix->coeff[1][1] -
matrix->coeff[0][1] * matrix->coeff[1][0]) * det;
*matrix = inv;
} }
@ -942,30 +935,37 @@ gimp_matrix4_identity (GimpMatrix4 *matrix)
/** /**
* gimp_matrix4_mult: * gimp_matrix4_mult:
* @matrix1: The first input matrix. * @left: The first input matrix.
* @matrix2: The second input matrix which will be overwritten by the result. * @right: The second input matrix which will be overwritten by the result.
* *
* Multiplies two matrices and puts the result into the second one. * Multiplies two matrices and puts the result into the second one.
* *
* Since: 2.10.16 * Since: 2.10.16
*/ */
void void
gimp_matrix4_mult (const GimpMatrix4 *matrix1, gimp_matrix4_mult (const GimpMatrix4 *left,
GimpMatrix4 *matrix2) GimpMatrix4 *right)
{ {
GimpMatrix4 result = {}; GimpMatrix4 result = {};
gint i, j, k; gint i, j;
gdouble li0, li1, li2, li3;
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
{ {
li0 = left->coeff[i][0];
li1 = left->coeff[i][1];
li2 = left->coeff[i][2];
li3 = left->coeff[i][3];
for (j = 0; j < 4; j++) for (j = 0; j < 4; j++)
{ {
for (k = 0; k < 4; k++) result.coeff[i][j] = li0 * right->coeff[0][j]
result.coeff[i][j] += matrix1->coeff[i][k] * matrix2->coeff[k][j]; + li1 * right->coeff[1][j]
+ li2 * right->coeff[2][j]
+ li3 * right->coeff[3][j];
} }
} }
*matrix2 = result; *right = result;
} }
/** /**

View file

@ -54,8 +54,8 @@ GParamSpec * gimp_param_spec_matrix2 (const gchar *name,
void gimp_matrix2_identity (GimpMatrix2 *matrix); void gimp_matrix2_identity (GimpMatrix2 *matrix);
void gimp_matrix2_mult (const GimpMatrix2 *matrix1, void gimp_matrix2_mult (const GimpMatrix2 *left,
GimpMatrix2 *matrix2); GimpMatrix2 *right);
gdouble gimp_matrix2_determinant (const GimpMatrix2 *matrix); gdouble gimp_matrix2_determinant (const GimpMatrix2 *matrix);
void gimp_matrix2_invert (GimpMatrix2 *matrix); void gimp_matrix2_invert (GimpMatrix2 *matrix);
@ -90,8 +90,8 @@ GParamSpec * gimp_param_spec_matrix3 (const gchar *name,
void gimp_matrix3_identity (GimpMatrix3 *matrix); void gimp_matrix3_identity (GimpMatrix3 *matrix);
void gimp_matrix3_mult (const GimpMatrix3 *matrix1, void gimp_matrix3_mult (const GimpMatrix3 *left,
GimpMatrix3 *matrix2); GimpMatrix3 *right);
void gimp_matrix3_translate (GimpMatrix3 *matrix, void gimp_matrix3_translate (GimpMatrix3 *matrix,
gdouble x, gdouble x,
gdouble y); gdouble y);
@ -135,8 +135,8 @@ void gimp_matrix3_transform_point (const GimpMatrix3 *matrix,
/*****************/ /*****************/
void gimp_matrix4_identity (GimpMatrix4 *matrix); void gimp_matrix4_identity (GimpMatrix4 *matrix);
void gimp_matrix4_mult (const GimpMatrix4 *matrix1, void gimp_matrix4_mult (const GimpMatrix4 *left,
GimpMatrix4 *matrix2); GimpMatrix4 *right);
void gimp_matrix4_to_deg (const GimpMatrix4 *matrix, void gimp_matrix4_to_deg (const GimpMatrix4 *matrix,
gdouble *a, gdouble *a,