1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2021 Google LLC
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "src/core/SkMatrixInvert.h"
9cb93a386Sopenharmony_ci
10cb93a386Sopenharmony_ci#include "include/private/SkFloatingPoint.h"
11cb93a386Sopenharmony_ci
12cb93a386Sopenharmony_ciSkScalar SkInvert2x2Matrix(const SkScalar inMatrix[4], SkScalar outMatrix[4]) {
13cb93a386Sopenharmony_ci    double a00 = inMatrix[0];
14cb93a386Sopenharmony_ci    double a01 = inMatrix[1];
15cb93a386Sopenharmony_ci    double a10 = inMatrix[2];
16cb93a386Sopenharmony_ci    double a11 = inMatrix[3];
17cb93a386Sopenharmony_ci
18cb93a386Sopenharmony_ci    // Calculate the determinant
19cb93a386Sopenharmony_ci    double determinant = a00 * a11 - a01 * a10;
20cb93a386Sopenharmony_ci    if (outMatrix) {
21cb93a386Sopenharmony_ci        double invdet = sk_ieee_double_divide(1.0, determinant);
22cb93a386Sopenharmony_ci        outMatrix[0] =  a11 * invdet;
23cb93a386Sopenharmony_ci        outMatrix[1] = -a01 * invdet;
24cb93a386Sopenharmony_ci        outMatrix[2] = -a10 * invdet;
25cb93a386Sopenharmony_ci        outMatrix[3] =  a00 * invdet;
26cb93a386Sopenharmony_ci        // If 1/det overflows to infinity (i.e. det is denormalized) or any of the inverted matrix
27cb93a386Sopenharmony_ci        // values is non-finite, return zero to indicate a non-invertible matrix.
28cb93a386Sopenharmony_ci        if (!SkScalarsAreFinite(outMatrix, 4)) {
29cb93a386Sopenharmony_ci            determinant = 0.0f;
30cb93a386Sopenharmony_ci        }
31cb93a386Sopenharmony_ci    }
32cb93a386Sopenharmony_ci    return determinant;
33cb93a386Sopenharmony_ci}
34cb93a386Sopenharmony_ci
35cb93a386Sopenharmony_ciSkScalar SkInvert3x3Matrix(const SkScalar inMatrix[9], SkScalar outMatrix[9]) {
36cb93a386Sopenharmony_ci    double a00 = inMatrix[0];
37cb93a386Sopenharmony_ci    double a01 = inMatrix[1];
38cb93a386Sopenharmony_ci    double a02 = inMatrix[2];
39cb93a386Sopenharmony_ci    double a10 = inMatrix[3];
40cb93a386Sopenharmony_ci    double a11 = inMatrix[4];
41cb93a386Sopenharmony_ci    double a12 = inMatrix[5];
42cb93a386Sopenharmony_ci    double a20 = inMatrix[6];
43cb93a386Sopenharmony_ci    double a21 = inMatrix[7];
44cb93a386Sopenharmony_ci    double a22 = inMatrix[8];
45cb93a386Sopenharmony_ci
46cb93a386Sopenharmony_ci    double b01 =  a22 * a11 - a12 * a21;
47cb93a386Sopenharmony_ci    double b11 = -a22 * a10 + a12 * a20;
48cb93a386Sopenharmony_ci    double b21 =  a21 * a10 - a11 * a20;
49cb93a386Sopenharmony_ci
50cb93a386Sopenharmony_ci    // Calculate the determinant
51cb93a386Sopenharmony_ci    double determinant = a00 * b01 + a01 * b11 + a02 * b21;
52cb93a386Sopenharmony_ci    if (outMatrix) {
53cb93a386Sopenharmony_ci        double invdet = sk_ieee_double_divide(1.0, determinant);
54cb93a386Sopenharmony_ci        outMatrix[0] = b01 * invdet;
55cb93a386Sopenharmony_ci        outMatrix[1] = (-a22 * a01 + a02 * a21) * invdet;
56cb93a386Sopenharmony_ci        outMatrix[2] = ( a12 * a01 - a02 * a11) * invdet;
57cb93a386Sopenharmony_ci        outMatrix[3] = b11 * invdet;
58cb93a386Sopenharmony_ci        outMatrix[4] = ( a22 * a00 - a02 * a20) * invdet;
59cb93a386Sopenharmony_ci        outMatrix[5] = (-a12 * a00 + a02 * a10) * invdet;
60cb93a386Sopenharmony_ci        outMatrix[6] = b21 * invdet;
61cb93a386Sopenharmony_ci        outMatrix[7] = (-a21 * a00 + a01 * a20) * invdet;
62cb93a386Sopenharmony_ci        outMatrix[8] = ( a11 * a00 - a01 * a10) * invdet;
63cb93a386Sopenharmony_ci        // If 1/det overflows to infinity (i.e. det is denormalized) or any of the inverted matrix
64cb93a386Sopenharmony_ci        // values is non-finite, return zero to indicate a non-invertible matrix.
65cb93a386Sopenharmony_ci        if (!SkScalarsAreFinite(outMatrix, 9)) {
66cb93a386Sopenharmony_ci            determinant = 0.0f;
67cb93a386Sopenharmony_ci        }
68cb93a386Sopenharmony_ci    }
69cb93a386Sopenharmony_ci    return determinant;
70cb93a386Sopenharmony_ci}
71cb93a386Sopenharmony_ci
72cb93a386Sopenharmony_ciSkScalar SkInvert4x4Matrix(const SkScalar inMatrix[16], SkScalar outMatrix[16]) {
73cb93a386Sopenharmony_ci    double a00 = inMatrix[0];
74cb93a386Sopenharmony_ci    double a01 = inMatrix[1];
75cb93a386Sopenharmony_ci    double a02 = inMatrix[2];
76cb93a386Sopenharmony_ci    double a03 = inMatrix[3];
77cb93a386Sopenharmony_ci    double a10 = inMatrix[4];
78cb93a386Sopenharmony_ci    double a11 = inMatrix[5];
79cb93a386Sopenharmony_ci    double a12 = inMatrix[6];
80cb93a386Sopenharmony_ci    double a13 = inMatrix[7];
81cb93a386Sopenharmony_ci    double a20 = inMatrix[8];
82cb93a386Sopenharmony_ci    double a21 = inMatrix[9];
83cb93a386Sopenharmony_ci    double a22 = inMatrix[10];
84cb93a386Sopenharmony_ci    double a23 = inMatrix[11];
85cb93a386Sopenharmony_ci    double a30 = inMatrix[12];
86cb93a386Sopenharmony_ci    double a31 = inMatrix[13];
87cb93a386Sopenharmony_ci    double a32 = inMatrix[14];
88cb93a386Sopenharmony_ci    double a33 = inMatrix[15];
89cb93a386Sopenharmony_ci
90cb93a386Sopenharmony_ci    double b00 = a00 * a11 - a01 * a10;
91cb93a386Sopenharmony_ci    double b01 = a00 * a12 - a02 * a10;
92cb93a386Sopenharmony_ci    double b02 = a00 * a13 - a03 * a10;
93cb93a386Sopenharmony_ci    double b03 = a01 * a12 - a02 * a11;
94cb93a386Sopenharmony_ci    double b04 = a01 * a13 - a03 * a11;
95cb93a386Sopenharmony_ci    double b05 = a02 * a13 - a03 * a12;
96cb93a386Sopenharmony_ci    double b06 = a20 * a31 - a21 * a30;
97cb93a386Sopenharmony_ci    double b07 = a20 * a32 - a22 * a30;
98cb93a386Sopenharmony_ci    double b08 = a20 * a33 - a23 * a30;
99cb93a386Sopenharmony_ci    double b09 = a21 * a32 - a22 * a31;
100cb93a386Sopenharmony_ci    double b10 = a21 * a33 - a23 * a31;
101cb93a386Sopenharmony_ci    double b11 = a22 * a33 - a23 * a32;
102cb93a386Sopenharmony_ci
103cb93a386Sopenharmony_ci    // Calculate the determinant
104cb93a386Sopenharmony_ci    double determinant = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
105cb93a386Sopenharmony_ci    if (outMatrix) {
106cb93a386Sopenharmony_ci        double invdet = sk_ieee_double_divide(1.0, determinant);
107cb93a386Sopenharmony_ci        b00 *= invdet;
108cb93a386Sopenharmony_ci        b01 *= invdet;
109cb93a386Sopenharmony_ci        b02 *= invdet;
110cb93a386Sopenharmony_ci        b03 *= invdet;
111cb93a386Sopenharmony_ci        b04 *= invdet;
112cb93a386Sopenharmony_ci        b05 *= invdet;
113cb93a386Sopenharmony_ci        b06 *= invdet;
114cb93a386Sopenharmony_ci        b07 *= invdet;
115cb93a386Sopenharmony_ci        b08 *= invdet;
116cb93a386Sopenharmony_ci        b09 *= invdet;
117cb93a386Sopenharmony_ci        b10 *= invdet;
118cb93a386Sopenharmony_ci        b11 *= invdet;
119cb93a386Sopenharmony_ci
120cb93a386Sopenharmony_ci        outMatrix[0]  = a11 * b11 - a12 * b10 + a13 * b09;
121cb93a386Sopenharmony_ci        outMatrix[1]  = a02 * b10 - a01 * b11 - a03 * b09;
122cb93a386Sopenharmony_ci        outMatrix[2]  = a31 * b05 - a32 * b04 + a33 * b03;
123cb93a386Sopenharmony_ci        outMatrix[3]  = a22 * b04 - a21 * b05 - a23 * b03;
124cb93a386Sopenharmony_ci        outMatrix[4]  = a12 * b08 - a10 * b11 - a13 * b07;
125cb93a386Sopenharmony_ci        outMatrix[5]  = a00 * b11 - a02 * b08 + a03 * b07;
126cb93a386Sopenharmony_ci        outMatrix[6]  = a32 * b02 - a30 * b05 - a33 * b01;
127cb93a386Sopenharmony_ci        outMatrix[7]  = a20 * b05 - a22 * b02 + a23 * b01;
128cb93a386Sopenharmony_ci        outMatrix[8]  = a10 * b10 - a11 * b08 + a13 * b06;
129cb93a386Sopenharmony_ci        outMatrix[9]  = a01 * b08 - a00 * b10 - a03 * b06;
130cb93a386Sopenharmony_ci        outMatrix[10] = a30 * b04 - a31 * b02 + a33 * b00;
131cb93a386Sopenharmony_ci        outMatrix[11] = a21 * b02 - a20 * b04 - a23 * b00;
132cb93a386Sopenharmony_ci        outMatrix[12] = a11 * b07 - a10 * b09 - a12 * b06;
133cb93a386Sopenharmony_ci        outMatrix[13] = a00 * b09 - a01 * b07 + a02 * b06;
134cb93a386Sopenharmony_ci        outMatrix[14] = a31 * b01 - a30 * b03 - a32 * b00;
135cb93a386Sopenharmony_ci        outMatrix[15] = a20 * b03 - a21 * b01 + a22 * b00;
136cb93a386Sopenharmony_ci
137cb93a386Sopenharmony_ci        // If 1/det overflows to infinity (i.e. det is denormalized) or any of the inverted matrix
138cb93a386Sopenharmony_ci        // values is non-finite, return zero to indicate a non-invertible matrix.
139cb93a386Sopenharmony_ci        if (!SkScalarsAreFinite(outMatrix, 16)) {
140cb93a386Sopenharmony_ci            determinant = 0.0f;
141cb93a386Sopenharmony_ci        }
142cb93a386Sopenharmony_ci    }
143cb93a386Sopenharmony_ci    return determinant;
144cb93a386Sopenharmony_ci}
145