/* * Copyright 2019-2025 Andrey Pokidov * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; /* * Author: Andrey Pokidov * Date: 10 Feb 2019 */ namespace Geometry { public struct SPMatrix2x2 { public float r1c1, r1c2; public float r2c1, r2c2; public SPMatrix2x2() { this.r1c1 = 0.0f; this.r1c2 = 0.0f; this.r2c1 = 0.0f; this.r2c2 = 0.0f; } public SPMatrix2x2(float d1, float d2) { this.r1c1 = d1; this.r1c2 = 0.0f; this.r2c1 = 0.0f; this.r2c2 = d2; } public SPMatrix2x2(in SPMatrix2x2 matrix) { this.r1c1 = matrix.r1c1; this.r1c2 = matrix.r1c2; this.r2c1 = matrix.r2c1; this.r2c2 = matrix.r2c2; } public SPMatrix2x2(in DPMatrix2x2 matrix) { this.r1c1 = (float)matrix.r1c1; this.r1c2 = (float)matrix.r1c2; this.r2c1 = (float)matrix.r2c1; this.r2c2 = (float)matrix.r2c2; } public readonly float GetDeterminant() { return this.r1c1 * this.r2c2 - this.r1c2 * this.r2c1; } public readonly bool IsSingular() { float determinant = this.GetDeterminant(); return -SPUtility.EPSYLON <= determinant && determinant <= SPUtility.EPSYLON; } public void Reset() { this.r1c1 = 0.0f; this.r1c2 = 0.0f; this.r2c1 = 0.0f; this.r2c2 = 0.0f; } public void MakeIdentity() { this.r1c1 = 1.0f; this.r1c2 = 0.0f; this.r2c1 = 0.0f; this.r2c2 = 1.0f; } public void MakeDiagonal(float d1, float d2) { this.r1c1 = d1; this.r1c2 = 0.0f; this.r2c1 = 0.0f; this.r2c2 = d2; } public void Transpose() { (this.r1c2, this.r2c1) = (this.r2c1, this.r1c2); } public bool Invert() { float determinant = this.GetDeterminant(); if (-SPUtility.EPSYLON <= determinant && determinant <= SPUtility.EPSYLON) { return false; } float r1c1 = this.r2c2; float r1c2 = -this.r1c2; float r2c1 = -this.r2c1; float r2c2 = this.r1c1; this.r1c1 = r1c1 / determinant; this.r1c2 = r1c2 / determinant; this.r2c1 = r2c1 / determinant; this.r2c2 = r2c2 / determinant; return true; } public void MakeTransposedOf(in SPMatrix2x2 matrix) { this.r1c1 = matrix.r1c1; this.r2c2 = matrix.r2c2; (this.r1c2, this.r2c1) = (matrix.r2c1, matrix.r1c2); } public void MakeTransposedOf(in DPMatrix2x2 matrix) { this.r1c1 = (float)matrix.r1c1; this.r1c2 = (float)matrix.r2c1; this.r2c1 = (float)matrix.r1c2; this.r2c2 = (float)matrix.r2c2; } public bool MakeInvertedOf(in SPMatrix2x2 matrix) { float determinant = matrix.GetDeterminant(); if (-SPUtility.EPSYLON <= determinant && determinant <= SPUtility.EPSYLON) { return false; } float r1c1 = matrix.r2c2; float r1c2 = -matrix.r1c2; float r2c1 = -matrix.r2c1; float r2c2 = matrix.r1c1; this.r1c1 = r1c1 / determinant; this.r1c2 = r1c2 / determinant; this.r2c1 = r2c1 / determinant; this.r2c2 = r2c2 / determinant; return true; } public void SetValues(in SPMatrix2x2 matrix) { this.r1c1 = matrix.r1c1; this.r1c2 = matrix.r1c2; this.r2c1 = matrix.r2c1; this.r2c2 = matrix.r2c2; } public void SetValues(in DPMatrix2x2 matrix) { this.r1c1 = (float)matrix.r1c1; this.r1c2 = (float)matrix.r1c2; this.r2c1 = (float)matrix.r2c1; this.r2c2 = (float)matrix.r2c2; } public void SetMainDiagonal(float d1, float d2) { this.r1c1 = d1; this.r2c2 = d2; } public void SetRow1(float c1, float c2) { this.r1c1 = c1; this.r1c2 = c2; } public void SetRow2(float c1, float c2) { this.r2c1 = c1; this.r2c2 = c2; } public void SetColumn1(float r1, float r2) { this.r1c1 = r1; this.r2c1 = r2; } public void SetColumn2(float r1, float r2) { this.r1c2 = r1; this.r2c2 = r2; } public static void Add(in SPMatrix2x2 matrix1, in SPMatrix2x2 matrix2, out SPMatrix2x2 result) { result.r1c1 = matrix1.r1c1 + matrix2.r1c1; result.r1c2 = matrix1.r1c2 + matrix2.r1c2; result.r2c1 = matrix1.r2c1 + matrix2.r2c1; result.r2c2 = matrix1.r2c2 + matrix2.r2c2; } public static void Add3( in SPMatrix2x2 matrix1, in SPMatrix2x2 matrix2, in SPMatrix2x2 matrix3, out SPMatrix2x2 sum ) { sum.r1c1 = matrix1.r1c1 + matrix2.r1c1 + matrix3.r1c1; sum.r1c2 = matrix1.r1c2 + matrix2.r1c2 + matrix3.r1c2; sum.r2c1 = matrix1.r2c1 + matrix2.r2c1 + matrix3.r2c1; sum.r2c2 = matrix1.r2c2 + matrix2.r2c2 + matrix3.r2c2; } public static void Add4( in SPMatrix2x2 matrix1, in SPMatrix2x2 matrix2, in SPMatrix2x2 matrix3, in SPMatrix2x2 matrix4, out SPMatrix2x2 sum ) { sum.r1c1 = (matrix1.r1c1 + matrix2.r1c1) + (matrix3.r1c1 + matrix4.r1c1); sum.r1c2 = (matrix1.r1c2 + matrix2.r1c2) + (matrix3.r1c2 + matrix4.r1c2); sum.r2c1 = (matrix1.r2c1 + matrix2.r2c1) + (matrix3.r2c1 + matrix4.r2c1); sum.r2c2 = (matrix1.r2c2 + matrix2.r2c2) + (matrix3.r2c2 + matrix4.r2c2); } public static void Add5( in SPMatrix2x2 matrix1, in SPMatrix2x2 matrix2, in SPMatrix2x2 matrix3, in SPMatrix2x2 matrix4, in SPMatrix2x2 matrix5, out SPMatrix2x2 sum ) { sum.r1c1 = (matrix1.r1c1 + matrix2.r1c1) + (matrix3.r1c1 + matrix4.r1c1) + matrix5.r1c1; sum.r1c2 = (matrix1.r1c2 + matrix2.r1c2) + (matrix3.r1c2 + matrix4.r1c2) + matrix5.r1c2; sum.r2c1 = (matrix1.r2c1 + matrix2.r2c1) + (matrix3.r2c1 + matrix4.r2c1) + matrix5.r2c1; sum.r2c2 = (matrix1.r2c2 + matrix2.r2c2) + (matrix3.r2c2 + matrix4.r2c2) + matrix5.r2c2; } public static void Subtract(in SPMatrix2x2 minuend, in SPMatrix2x2 subtrahend, out SPMatrix2x2 difference) { difference.r1c1 = minuend.r1c1 - subtrahend.r1c1; difference.r1c2 = minuend.r1c2 - subtrahend.r1c2; difference.r2c1 = minuend.r2c1 - subtrahend.r2c1; difference.r2c2 = minuend.r2c2 - subtrahend.r2c2; } public static void GetWeightedSum2( float weight1, in SPMatrix2x2 matrix1, float weight2, in SPMatrix2x2 matrix2, out SPMatrix2x2 sum ) { sum.r1c1 = matrix1.r1c1 * weight1 + matrix2.r1c1 * weight2; sum.r1c2 = matrix1.r1c2 * weight1 + matrix2.r1c2 * weight2; sum.r2c1 = matrix1.r2c1 * weight1 + matrix2.r2c1 * weight2; sum.r2c2 = matrix1.r2c2 * weight1 + matrix2.r2c2 * weight2; } public static void GetWeightedSum3( float weight1, in SPMatrix2x2 matrix1, float weight2, in SPMatrix2x2 matrix2, float weight3, in SPMatrix2x2 matrix3, out SPMatrix2x2 sum ) { sum.r1c1 = matrix1.r1c1 * weight1 + matrix2.r1c1 * weight2 + matrix3.r1c1 * weight3; sum.r1c2 = matrix1.r1c2 * weight1 + matrix2.r1c2 * weight2 + matrix3.r1c2 * weight3; sum.r2c1 = matrix1.r2c1 * weight1 + matrix2.r2c1 * weight2 + matrix3.r2c1 * weight3; sum.r2c2 = matrix1.r2c2 * weight1 + matrix2.r2c2 * weight2 + matrix3.r2c2 * weight3; } public static void GetWeightedSum4( float weight1, in SPMatrix2x2 matrix1, float weight2, in SPMatrix2x2 matrix2, float weight3, in SPMatrix2x2 matrix3, float weight4, in SPMatrix2x2 matrix4, out SPMatrix2x2 sum ) { sum.r1c1 = (matrix1.r1c1 * weight1 + matrix2.r1c1 * weight2) + (matrix3.r1c1 * weight3 + matrix4.r1c1 * weight4); sum.r1c2 = (matrix1.r1c2 * weight1 + matrix2.r1c2 * weight2) + (matrix3.r1c2 * weight3 + matrix4.r1c2 * weight4); sum.r2c1 = (matrix1.r2c1 * weight1 + matrix2.r2c1 * weight2) + (matrix3.r2c1 * weight3 + matrix4.r2c1 * weight4); sum.r2c2 = (matrix1.r2c2 * weight1 + matrix2.r2c2 * weight2) + (matrix3.r2c2 * weight3 + matrix4.r2c2 * weight4); } public static void GetWeightedSum5( float weight1, in SPMatrix2x2 matrix1, float weight2, in SPMatrix2x2 matrix2, float weight3, in SPMatrix2x2 matrix3, float weight4, in SPMatrix2x2 matrix4, float weight5, in SPMatrix2x2 matrix5, out SPMatrix2x2 sum ) { sum.r1c1 = (matrix1.r1c1 * weight1 + matrix2.r1c1 * weight2) + (matrix3.r1c1 * weight3 + matrix4.r1c1 * weight4) + matrix5.r1c1 * weight5; sum.r1c2 = (matrix1.r1c2 * weight1 + matrix2.r1c2 * weight2) + (matrix3.r1c2 * weight3 + matrix4.r1c2 * weight4) + matrix5.r1c2 * weight5; sum.r2c1 = (matrix1.r2c1 * weight1 + matrix2.r2c1 * weight2) + (matrix3.r2c1 * weight3 + matrix4.r2c1 * weight4) + matrix5.r2c1 * weight5; sum.r2c2 = (matrix1.r2c2 * weight1 + matrix2.r2c2 * weight2) + (matrix3.r2c2 * weight3 + matrix4.r2c2 * weight4) + matrix5.r2c2 * weight5; } public static void Multiply(in SPMatrix2x2 multiplicand, float multiplier, out SPMatrix2x2 product) { product.r1c1 = multiplicand.r1c1 * multiplier; product.r1c2 = multiplicand.r1c2 * multiplier; product.r2c1 = multiplicand.r2c1 * multiplier; product.r2c2 = multiplicand.r2c2 * multiplier; } public static void Divide(in SPMatrix2x2 dividend, float divisor, out SPMatrix2x2 quotient) { quotient.r1c1 = dividend.r1c1 / divisor; quotient.r1c2 = dividend.r1c2 / divisor; quotient.r2c1 = dividend.r2c1 / divisor; quotient.r2c2 = dividend.r2c2 / divisor; } public static void GetRightProduct(in SPMatrix2x2 matrix, in SPVector2 vector, out SPVector2 result) { float x1 = matrix.r1c1 * vector.x1 + matrix.r1c2 * vector.x2; float x2 = matrix.r2c1 * vector.x1 + matrix.r2c2 * vector.x2; result.x1 = x1; result.x2 = x2; } public static void GetLeftProduct(in SPVector2 vector, in SPMatrix2x2 matrix, out SPVector2 result) { float x1 = vector.x1 * matrix.r1c1 + vector.x2 * matrix.r2c1; float x2 = vector.x1 * matrix.r1c2 + vector.x2 * matrix.r2c2; result.x1 = x1; result.x2 = x2; } public static void LoadZero(out SPMatrix2x2 matrix) { matrix.r1c1 = 0.0f; matrix.r1c2 = 0.0f; matrix.r2c1 = 0.0f; matrix.r2c2 = 0.0f; } public static void LoadIdentity(out SPMatrix2x2 matrix) { matrix.r1c1 = 1.0f; matrix.r1c2 = 0.0f; matrix.r2c1 = 0.0f; matrix.r2c2 = 1.0f; } public static void LoadDiagonal(float d1, float d2, out SPMatrix2x2 matrix) { matrix.r1c1 = d1; matrix.r1c2 = 0.0f; matrix.r2c1 = 0.0f; matrix.r2c2 = d2; } } }