better matrix 3x3 invert
I didn't think hard about this... just folded through constants.
Change-Id: I994773009964e183691cf5f10861756acfe4b2ae
Reviewed-on: https://skia-review.googlesource.com/118986
Commit-Queue: Mike Klein <mtklein@chromium.org>
Reviewed-by: Brian Osman <brianosman@google.com>
diff --git a/src/LinearAlgebra.c b/src/LinearAlgebra.c
index a872613..e7e335e 100644
--- a/src/LinearAlgebra.c
+++ b/src/LinearAlgebra.c
@@ -9,16 +9,6 @@
#include "LinearAlgebra.h"
#include "PortableMath.h"
-static bool Matrix4x4_isfinite(const skcms_Matrix4x4* m) {
- for (int r = 0; r < 4; ++r)
- for (int c = 0; c < 4; ++c) {
- if (!isfinitef_(m->vals[r][c])) {
- return false;
- }
- }
- return true;
-}
-
bool skcms_Matrix4x4_invert(const skcms_Matrix4x4* src, skcms_Matrix4x4* dst) {
double a00 = (double)src->vals[0][0],
a01 = (double)src->vals[1][0],
@@ -96,28 +86,69 @@
dst->vals[2][3] = (float)( a31*b01 - a30*b03 - a32*b00 );
dst->vals[3][3] = (float)( a20*b03 - a21*b01 + a22*b00 );
- return Matrix4x4_isfinite(dst);
+ for (int r = 0; r < 4; ++r)
+ for (int c = 0; c < 4; ++c) {
+ if (!isfinitef_(dst->vals[r][c])) {
+ return false;
+ }
+ }
+ return true;
}
bool skcms_Matrix3x3_invert(const skcms_Matrix3x3* src, skcms_Matrix3x3* dst) {
- // TODO: I am being _very_ lazy.
- skcms_Matrix4x4 m = {{
- { src->vals[0][0], src->vals[0][1], src->vals[0][2], 0.0f },
- { src->vals[1][0], src->vals[1][1], src->vals[1][2], 0.0f },
- { src->vals[2][0], src->vals[2][1], src->vals[2][2], 0.0f },
- { 0.0f, 0.0f, 0.0f, 1.0f },
- }};
+ double a00 = (double)src->vals[0][0],
+ a01 = (double)src->vals[1][0],
+ a02 = (double)src->vals[2][0],
+ a10 = (double)src->vals[0][1],
+ a11 = (double)src->vals[1][1],
+ a12 = (double)src->vals[2][1],
+ a20 = (double)src->vals[0][2],
+ a21 = (double)src->vals[1][2],
+ a22 = (double)src->vals[2][2];
- skcms_Matrix4x4 inv;
- if (!skcms_Matrix4x4_invert(&m, &inv)) {
+ double b0 = a00*a11 - a01*a10,
+ b1 = a00*a12 - a02*a10,
+ b2 = a01*a12 - a02*a11,
+ b3 = a20,
+ b4 = a21,
+ b5 = a22;
+
+ double determinant = b0*b5
+ - b1*b4
+ + b2*b3;
+
+ if (determinant == 0) {
return false;
}
- *dst = (skcms_Matrix3x3){{
- { inv.vals[0][0], inv.vals[0][1], inv.vals[0][2] },
- { inv.vals[1][0], inv.vals[1][1], inv.vals[1][2] },
- { inv.vals[2][0], inv.vals[2][1], inv.vals[2][2] },
- }};
+ double invdet = 1.0 / determinant;
+ if (!isfinitef_((float)invdet)) {
+ return false;
+ }
+
+ b0 *= invdet;
+ b1 *= invdet;
+ b2 *= invdet;
+ b3 *= invdet;
+ b4 *= invdet;
+ b5 *= invdet;
+
+ dst->vals[0][0] = (float)( a11*b5 - a12*b4 );
+ dst->vals[1][0] = (float)( a02*b4 - a01*b5 );
+ dst->vals[2][0] = (float)( + b2 );
+ dst->vals[0][1] = (float)( a12*b3 - a10*b5 );
+ dst->vals[1][1] = (float)( a00*b5 - a02*b3 );
+ dst->vals[2][1] = (float)( - b1 );
+ dst->vals[0][2] = (float)( a10*b4 - a11*b3 );
+ dst->vals[1][2] = (float)( a01*b3 - a00*b4 );
+ dst->vals[2][2] = (float)( + b0 );
+
+ for (int r = 0; r < 3; ++r)
+ for (int c = 0; c < 3; ++c) {
+ if (!isfinitef_(dst->vals[r][c])) {
+ return false;
+ }
+ }
return true;
}