// Copyright (c) Meta Platforms, Inc. and affiliates. All rights reserved. using System.Collections.Generic; using System.Linq; using UnityEngine; namespace Meta.XR.Movement.FaceTracking.Samples { /// /// Sparse matrix implementation of . /// public class SparseMatrix : Matrix { private struct Data { public int Row, Column; public float Value; } private readonly Data[] _data; private readonly int _rows; private readonly int _cols; /// public override int Rows => _rows; /// public override int Cols => _cols; /// /// Constructor that can be initialized from an instance of /// . A threshold parameter is used /// to add items from the dense matrix. /// /// to copy from. /// Threshold value. public SparseMatrix(DenseMatrix m, float threshold = 1e-3f) { _cols = m.Cols; _rows = m.Rows; List listOfData = new List(); for (var row = 0; row < _rows; row++) { for (var col = 0; col < _cols; col++) { var val = m[row, col]; if (Mathf.Abs(val) > threshold) { listOfData.Add(new Data() { Row = row, Column = col, Value = val }); } } } _data = listOfData.ToArray(); } /// /// Slow linear search - only usable for tests. /// /// Row index. /// Column index. /// protected override float GetElement(int row, int col) => _data.FirstOrDefault((Data d) => d.Row == row && d.Column == col).Value; protected override void MultVectWithMatrix(float[] rowVector, float[] result) { Debug.Assert(rowVector.Length == this.Rows); Debug.Assert(result.Length == this.Cols); for (var i = 0; i < result.Length; i++) { result[i] = 0.0f; } foreach (var t in _data) { result[t.Column] += rowVector[t.Row] * t.Value; } } } }