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