// Copyright (c) Meta Platforms, Inc. and affiliates. All rights reserved. using System; using System.Collections.Generic; using UnityEngine; namespace Meta.XR.Movement.FaceTracking.Samples { /// /// An abstract matrix class, with a minimal interface required for /// face retargeting functionality. /// public abstract class Matrix : IEquatable { /// /// Number of rows in matrix. /// public abstract int Rows { get; } /// /// Number of columns in matrix. /// public abstract int Cols { get; } // Equality operator, used in tests only (this implementation is not efficient for sparse matrices). protected const float Eps = 1e-5f; /// /// Tests for quality between this matrix and another one. /// /// Other matrix to compare against. /// Returns true if equal; false if not. public bool Equals(Matrix m) => Equals(m, Eps); /// /// Tests for quality between this matrix and another one. /// /// Other matrix. /// Epsilon value use for equality. /// public bool Equals(Matrix m, float eps) { if (m == null || Rows != m.Rows || Cols != m.Cols) return false; for (var row = 0; row < Rows; ++row) { for (var col = 0; col < Cols; ++col) { if (Mathf.Abs(this[row, col] - m[row, col]) > eps) return false; } } return true; } /// /// Array accessor. /// /// Row. /// Column. /// public float this[int row, int col] { get => GetElement(row, col); set => SetElement(row, col, value); } protected abstract float GetElement(int row, int col); protected virtual void SetElement(int row, int col, float value) { throw new System.NotImplementedException(); } /// /// Applies matrix multiplication with row vector without allocation, since result is /// assumed to be preallocated. Implements result = rowVector * m. /// /// Row vector. /// Matrix. /// Result. public static void Mult(float[] rowVector, Matrix m, float[] result) { Debug.Assert(rowVector.Length == m.Rows); Debug.Assert(result.Length == m.Cols); m.MultVectWithMatrix(rowVector, result); } protected abstract void MultVectWithMatrix(float[] rowVector, float[] result); } }