[Bf-blender-cvs] [6769acbbba7] master: BLI_math: simplify matrix multiply logic

Chris Blackbourn noreply at git.blender.org
Mon Jan 16 23:24:57 CET 2023


Commit: 6769acbbba7f0beb50dafcae3f49de9caee55787
Author: Chris Blackbourn
Date:   Tue Jan 17 11:14:52 2023 +1300
Branches: master
https://developer.blender.org/rB6769acbbba7f0beb50dafcae3f49de9caee55787

BLI_math: simplify matrix multiply logic

Improve safety and correctness of matrix multiplication by using
temporary storage if one of the inputs is also the output.

No functional changes.

Differential Revision: https://developer.blender.org/D16876
Reviewed By: Campbell Barton, Sergey Sharybin

===================================================================

M	source/blender/blenlib/BLI_math_matrix.h
M	source/blender/blenlib/intern/math_matrix.c
M	source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.cc
M	source/blender/gpencil_modifiers/intern/lineart/lineart_shadow.c

===================================================================

diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h
index 538474f58b6..1278bc90e44 100644
--- a/source/blender/blenlib/BLI_math_matrix.h
+++ b/source/blender/blenlib/BLI_math_matrix.h
@@ -83,16 +83,12 @@ void mul_m3_m4m4(float R[3][3], const float A[4][4], const float B[4][4]);
 
 /**
  * Special matrix multiplies
- * - uniq: `R <-- AB`, R is neither A nor B
  * - pre:  `R <-- AR`
  * - post: `R <-- RB`.
  */
-void mul_m3_m3m3_uniq(float R[3][3], const float A[3][3], const float B[3][3]);
 void mul_m3_m3_pre(float R[3][3], const float A[3][3]);
 void mul_m3_m3_post(float R[3][3], const float B[3][3]);
-void mul_m4_m4m4_uniq(float R[4][4], const float A[4][4], const float B[4][4]);
-void mul_m4_m4m4_db_uniq(double R[4][4], const double A[4][4], const double B[4][4]);
-void mul_m4db_m4db_m4fl_uniq(double R[4][4], const double A[4][4], const float B[4][4]);
+void mul_m4db_m4db_m4fl(double R[4][4], const double A[4][4], const float B[4][4]);
 void mul_m4_m4_pre(float R[4][4], const float A[4][4]);
 void mul_m4_m4_post(float R[4][4], const float B[4][4]);
 
diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c
index d997eae26fb..7322a9facec 100644
--- a/source/blender/blenlib/intern/math_matrix.c
+++ b/source/blender/blenlib/intern/math_matrix.c
@@ -257,22 +257,14 @@ void shuffle_m4(float R[4][4], const int index[4])
 
 void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
 {
-  if (A == R) {
-    mul_m4_m4_post(R, B);
-  }
-  else if (B == R) {
-    mul_m4_m4_pre(R, A);
-  }
-  else {
-    mul_m4_m4m4_uniq(R, A, B);
+  if (R == A || R == B) {
+    float T[4][4];
+    mul_m4_m4m4(T, A, B);
+    copy_m4_m4(R, T);
+    return;
   }
-}
-
-void mul_m4_m4m4_uniq(float R[4][4], const float A[4][4], const float B[4][4])
-{
-  BLI_assert(!ELEM(R, A, B));
 
-  /* Matrix product: `R[j][k] = A[j][i] . B[i][k]`. */
+  /* Matrix product: `R[j][k] = B[j][i] . A[i][k]`. */
 #ifdef BLI_HAVE_SSE2
   __m128 A0 = _mm_loadu_ps(A[0]);
   __m128 A1 = _mm_loadu_ps(A[1]);
@@ -313,39 +305,16 @@ void mul_m4_m4m4_uniq(float R[4][4], const float A[4][4], const float B[4][4])
 #endif
 }
 
-void mul_m4_m4m4_db_uniq(double R[4][4], const double A[4][4], const double B[4][4])
+void mul_m4db_m4db_m4fl(double R[4][4], const double A[4][4], const float B[4][4])
 {
-  BLI_assert(!ELEM(R, A, B));
-
-  /* Matrix product: `R[j][k] = A[j][i] . B[i][k]`. */
-
-  R[0][0] = B[0][0] * A[0][0] + B[0][1] * A[1][0] + B[0][2] * A[2][0] + B[0][3] * A[3][0];
-  R[0][1] = B[0][0] * A[0][1] + B[0][1] * A[1][1] + B[0][2] * A[2][1] + B[0][3] * A[3][1];
-  R[0][2] = B[0][0] * A[0][2] + B[0][1] * A[1][2] + B[0][2] * A[2][2] + B[0][3] * A[3][2];
-  R[0][3] = B[0][0] * A[0][3] + B[0][1] * A[1][3] + B[0][2] * A[2][3] + B[0][3] * A[3][3];
-
-  R[1][0] = B[1][0] * A[0][0] + B[1][1] * A[1][0] + B[1][2] * A[2][0] + B[1][3] * A[3][0];
-  R[1][1] = B[1][0] * A[0][1] + B[1][1] * A[1][1] + B[1][2] * A[2][1] + B[1][3] * A[3][1];
-  R[1][2] = B[1][0] * A[0][2] + B[1][1] * A[1][2] + B[1][2] * A[2][2] + B[1][3] * A[3][2];
-  R[1][3] = B[1][0] * A[0][3] + B[1][1] * A[1][3] + B[1][2] * A[2][3] + B[1][3] * A[3][3];
-
-  R[2][0] = B[2][0] * A[0][0] + B[2][1] * A[1][0] + B[2][2] * A[2][0] + B[2][3] * A[3][0];
-  R[2][1] = B[2][0] * A[0][1] + B[2][1] * A[1][1] + B[2][2] * A[2][1] + B[2][3] * A[3][1];
-  R[2][2] = B[2][0] * A[0][2] + B[2][1] * A[1][2] + B[2][2] * A[2][2] + B[2][3] * A[3][2];
-  R[2][3] = B[2][0] * A[0][3] + B[2][1] * A[1][3] + B[2][2] * A[2][3] + B[2][3] * A[3][3];
-
-  R[3][0] = B[3][0] * A[0][0] + B[3][1] * A[1][0] + B[3][2] * A[2][0] + B[3][3] * A[3][0];
-  R[3][1] = B[3][0] * A[0][1] + B[3][1] * A[1][1] + B[3][2] * A[2][1] + B[3][3] * A[3][1];
-  R[3][2] = B[3][0] * A[0][2] + B[3][1] * A[1][2] + B[3][2] * A[2][2] + B[3][3] * A[3][2];
-  R[3][3] = B[3][0] * A[0][3] + B[3][1] * A[1][3] + B[3][2] * A[2][3] + B[3][3] * A[3][3];
-}
-
-void mul_m4db_m4db_m4fl_uniq(double R[4][4], const double A[4][4], const float B[4][4])
-{
-  /* Remove second check since types don't match. */
-  BLI_assert(!ELEM(R, A /*, B */));
+  if (R == A) {
+    double T[4][4];
+    mul_m4db_m4db_m4fl(T, A, B);
+    copy_m4_m4_db(R, T);
+    return;
+  }
 
-  /* Matrix product: `R[j][k] = A[j][i] . B[i][k]`. */
+  /* Matrix product: `R[j][k] = B[j][i] . A[i][k]`. */
 
   R[0][0] = B[0][0] * A[0][0] + B[0][1] * A[1][0] + B[0][2] * A[2][0] + B[0][3] * A[3][0];
   R[0][1] = B[0][0] * A[0][1] + B[0][1] * A[1][1] + B[0][2] * A[2][1] + B[0][3] * A[3][1];
@@ -370,53 +339,32 @@ void mul_m4db_m4db_m4fl_uniq(double R[4][4], const double A[4][4], const float B
 
 void mul_m4_m4_pre(float R[4][4], const float A[4][4])
 {
-  BLI_assert(A != R);
-  float B[4][4];
-  copy_m4_m4(B, R);
-  mul_m4_m4m4_uniq(R, A, B);
+  mul_m4_m4m4(R, A, R);
 }
 
 void mul_m4_m4_post(float R[4][4], const float B[4][4])
 {
-  BLI_assert(B != R);
-  float A[4][4];
-  copy_m4_m4(A, R);
-  mul_m4_m4m4_uniq(R, A, B);
-}
-
-void mul_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3])
-{
-  if (A == R) {
-    mul_m3_m3_post(R, B);
-  }
-  else if (B == R) {
-    mul_m3_m3_pre(R, A);
-  }
-  else {
-    mul_m3_m3m3_uniq(R, A, B);
-  }
+  mul_m4_m4m4(R, R, B);
 }
 
 void mul_m3_m3_pre(float R[3][3], const float A[3][3])
 {
-  BLI_assert(A != R);
-  float B[3][3];
-  copy_m3_m3(B, R);
-  mul_m3_m3m3_uniq(R, A, B);
+  mul_m3_m3m3(R, A, R);
 }
 
 void mul_m3_m3_post(float R[3][3], const float B[3][3])
 {
-  BLI_assert(B != R);
-  float A[3][3];
-  copy_m3_m3(A, R);
-  mul_m3_m3m3_uniq(R, A, B);
+  mul_m3_m3m3(R, R, B);
 }
 
-void mul_m3_m3m3_uniq(float R[3][3], const float A[3][3], const float B[3][3])
+void mul_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3])
 {
-  BLI_assert(!ELEM(R, A, B));
-
+  if (R == A || R == B) {
+    float T[3][3];
+    mul_m3_m3m3(T, A, B);
+    copy_m3_m3(R, T);
+    return;
+  }
   R[0][0] = B[0][0] * A[0][0] + B[0][1] * A[1][0] + B[0][2] * A[2][0];
   R[0][1] = B[0][0] * A[0][1] + B[0][1] * A[1][1] + B[0][2] * A[2][1];
   R[0][2] = B[0][0] * A[0][2] + B[0][1] * A[1][2] + B[0][2] * A[2][2];
@@ -432,88 +380,90 @@ void mul_m3_m3m3_uniq(float R[3][3], const float A[3][3], const float B[3][3])
 
 void mul_m4_m4m3(float R[4][4], const float A[4][4], const float B[3][3])
 {
-  float B_[3][3], A_[4][4];
-
-  /* copy so it works when R is the same pointer as A or B */
-  /* TODO: avoid copying when matrices are different */
-  copy_m4_m4(A_, A);
-  copy_m3_m3(B_, B);
+  if (R == A) {
+    float T[4][4];
+    mul_m4_m4m3(T, A, B);
+    copy_m4_m4(R, T);
+    return;
+  }
 
-  R[0][0] = B_[0][0] * A_[0][0] + B_[0][1] * A_[1][0] + B_[0][2] * A_[2][0];
-  R[0][1] = B_[0][0] * A_[0][1] + B_[0][1] * A_[1][1] + B_[0][2] * A_[2][1];
-  R[0][2] = B_[0][0] * A_[0][2] + B_[0][1] * A_[1][2] + B_[0][2] * A_[2][2];
-  R[1][0] = B_[1][0] * A_[0][0] + B_[1][1] * A_[1][0] + B_[1][2] * A_[2][0];
-  R[1][1] = B_[1][0] * A_[0][1] + B_[1][1] * A_[1][1] + B_[1][2] * A_[2][1];
-  R[1][2] = B_[1][0] * A_[0][2] + B_[1][1] * A_[1][2] + B_[1][2] * A_[2][2];
-  R[2][0] = B_[2][0] * A_[0][0] + B_[2][1] * A_[1][0] + B_[2][2] * A_[2][0];
-  R[2][1] = B_[2][0] * A_[0][1] + B_[2][1] * A_[1][1] + B_[2][2] * A_[2][1];
-  R[2][2] = B_[2][0] * A_[0][2] + B_[2][1] * A_[1][2] + B_[2][2] * A_[2][2];
+  R[0][0] = B[0][0] * A[0][0] + B[0][1] * A[1][0] + B[0][2] * A[2][0];
+  R[0][1] = B[0][0] * A[0][1] + B[0][1] * A[1][1] + B[0][2] * A[2][1];
+  R[0][2] = B[0][0] * A[0][2] + B[0][1] * A[1][2] + B[0][2] * A[2][2];
+  R[1][0] = B[1][0] * A[0][0] + B[1][1] * A[1][0] + B[1][2] * A[2][0];
+  R[1][1] = B[1][0] * A[0][1] + B[1][1] * A[1][1] + B[1][2] * A[2][1];
+  R[1][2] = B[1][0] * A[0][2] + B[1][1] * A[1][2] + B[1][2] * A[2][2];
+  R[2][0] = B[2][0] * A[0][0] + B[2][1] * A[1][0] + B[2][2] * A[2][0];
+  R[2][1] = B[2][0] * A[0][1] + B[2][1] * A[1][1] + B[2][2] * A[2][1];
+  R[2][2] = B[2][0] * A[0][2] + B[2][1] * A[1][2] + B[2][2] * A[2][2];
 }
 
 void mul_m3_m3m4(float R[3][3], const float A[3][3], const float B[4][4])
 {
-  float B_[4][4], A_[3][3];
+  if (R == A) {
+    float T[3][3];
+    mul_m3_m3m4(T, A, B);
+    copy_m3_m3(R, T);
+    return;
+  }
 
-  /* copy so it works when R is the same pointer as A or B */
-  /* TODO: avoid copying when matrices are different */
-  copy_m3_m3(A_, A);
-  copy_m4_m4(B_, B);
+  /* Matrix product: `R[j][k] = B[j][i] . A[i][k]`. */
 
-  /* R[i][j] = B_[i][k] * A_[k][j] */
-  R[0][0] = B_[0][0] * A_[0][0] + B_[0][1] * A_[1][0] + B_[0][2] * A_[2][0];
-  R[0][1] = B_[0][0] * A_[0][1] + B_[0][1] * A_[1][1] + B_[0][2] * A_[2][1];
-  R[0][2] = B_[0][0] * A_[0][2] + B_[0][1] * A_[1][2] + B_[0][2] * A_[2][2];
+  R[0][0] = B[0][0] * A[0][0] + B[0][1] * A[1][0] + B[0][2] * A[2][0];
+  R[0][1] = B[0][0] * A[0][1] + B[0][1] * A[1][1] + B[0][2] * A[2][1];
+  R[0][2] = B[0][0] * A[0][2] + B[0][1] * A[1][2] + B[0][2] * A[2][2];
 
-  R[1][0] = B_[1][0] * A_[0][0] + B_[1][1] * A_[1][0] + B_[1][2] * A_[2][0];
-  R[1][1] = B_[1][0] * A_[0][1] + B_[1][1] * A_[1][1] + B_[1][2] * A_[2][1];
-  R[1][2] = B_[1][0] * A_[0][2] + B_[1][1] * A_[1][2] + B_[1][2] * A_[2][2];
+  R[1][0] = B[1][0] * A[0][0] + B[1][1] * A[1][0] + B[1][2] * A[2][0];
+  R[1][1] = B[1][0] * A[0][1] + B[1][1] * A[1][1] + B[1][2] * A[2][1];
+  R[1][2] = B[1][0] * A[0][2] + B[1][1] * A[1][2] + B[1][2] * A[2][2];
 
-  R[2][0] = B_[2][0] * A_[0][0] + B_[2][1] * A_[1][0] + B_[2][2] * A_[2][0];
-  R[2][1] = B_[2][0] * A_[0][1] + B_[2][1] * A_[1][1] + B_[2][2] * A_[2][1];
-  R[2][2] = B_[2][0] * A_[0][2] + B_[2][1] * A_[1][2] + B_[2][2] * A_[2][2];
+  R[2][0] = B[2][0] * A[0][0] + B[2][1] * A[1][0] + B[2][2] * A[2][0];
+  R[2][1] = B[2][0] * A[0][1] + B[2][1] * A[1][1] + B[2][2] * A[2][1];
+  R[2][2] = B[2][0] * A[0][2] + B[2][1] * A[1][2] + B[2][2] * A[2][2];
 }
 
 void mul_m3_m4m3(float R[3][3], const float A[4][4], const float B[3][3])
 {
-  float B_[3][3], A_[4][4];
+  if (R == B) {
+    float T[3][3];
+    mul_m3_m4m3(T, A, B);
+    copy_m3_m3(R, T);
+    return;
+  }
 
-  /* copy so it works when R is the same pointer as A or B */
-  /* TODO: avoid copying when matrices are different */
-  copy_m4_m4(A_, A);
-  copy_m3_m3(B_, B);
+  /* Matrix product: `R[j][k] = B[j][i] . A[i][k]`. 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list