// 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);
}
}