| /* |
| * Copyright 2018 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include "../skcms.h" |
| #include "LinearAlgebra.h" |
| #include "PortableMath.h" |
| #include <float.h> |
| |
| bool skcms_Matrix3x3_invert(const skcms_Matrix3x3* src, skcms_Matrix3x3* dst) { |
| double a00 = src->vals[0][0], |
| a01 = src->vals[1][0], |
| a02 = src->vals[2][0], |
| a10 = src->vals[0][1], |
| a11 = src->vals[1][1], |
| a12 = src->vals[2][1], |
| a20 = src->vals[0][2], |
| a21 = src->vals[1][2], |
| a22 = src->vals[2][2]; |
| |
| 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; |
| } |
| |
| double invdet = 1.0 / determinant; |
| if (invdet > +FLT_MAX || invdet < -FLT_MAX || !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; |
| } |
| |
| skcms_Matrix3x3 skcms_Matrix3x3_concat(const skcms_Matrix3x3* A, const skcms_Matrix3x3* B) { |
| skcms_Matrix3x3 m = { { { 0,0,0 },{ 0,0,0 },{ 0,0,0 } } }; |
| for (int r = 0; r < 3; r++) |
| for (int c = 0; c < 3; c++) { |
| m.vals[r][c] = A->vals[r][0] * B->vals[0][c] |
| + A->vals[r][1] * B->vals[1][c] |
| + A->vals[r][2] * B->vals[2][c]; |
| } |
| return m; |
| } |
| |
| skcms_Vector3 skcms_MV_mul(const skcms_Matrix3x3* m, const skcms_Vector3* v) { |
| skcms_Vector3 dst = {{0,0,0}}; |
| for (int row = 0; row < 3; ++row) { |
| dst.vals[row] = m->vals[row][0] * v->vals[0] |
| + m->vals[row][1] * v->vals[1] |
| + m->vals[row][2] * v->vals[2]; |
| } |
| return dst; |
| } |