| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using NUnit.Framework;
- namespace SharpGLTF.Transforms
- {
- [Category("Core.Transforms")]
- public class SparseWeight8Tests
- {
- [TestCase(0)]
- [TestCase(1)]
- [TestCase(0,0.0001f)]
- [TestCase(2, -2, 2, -2)]
- [TestCase(0.2f, 0.15f, 0.25f, 0.10f, 0.30f)]
- [TestCase(0, 0, 1, 0, 2, 0, 3, 4, 5, 0, 6, 0, 7, 0, 6, 0, 9, 0, 11)]
- [TestCase(9, -9, 8, -8, 7, -7, 6, -6, 5, -5, 4, -4, 3, -3, 2, -2, 1, -1)]
- [TestCase(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)]
- [TestCase(0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)]
- public void TestSparseCreation(params float[] array1)
- {
- var array2 = CreateSparseCompatibleArray(array1);
-
- var array3 = array1
- .Select((val, idx) => (idx, val))
- .Where(item => item.val != 0)
- .Reverse()
- .ToArray();
- // creation mode 1
- var sparse = SparseWeight8.Create(array1);
- Assert.That(sparse.WeightSum, Is.EqualTo(array2.Sum()));
- Assert.That(sparse.Expand(array2.Length), Is.EqualTo(array2));
- // creation mode 2
- var indexedSparse = SparseWeight8.Create(array3);
- Assert.That(indexedSparse.WeightSum, Is.EqualTo(array2.Sum()).Within(0.000001f));
- Assert.That(indexedSparse.Expand(array2.Length), Is.EqualTo(array2));
- Assert.That(SparseWeight8.AreEqual(sparse, indexedSparse));
- // sort by weights
- var sByWeights = SparseWeight8.OrderedByWeight(sparse);
- Assert.That(sByWeights.WeightSum, Is.EqualTo(array2.Sum()));
- Assert.That(sByWeights.Expand(array2.Length), Is.EqualTo(array2));
- CheckWeightOrdered(sByWeights);
- // sort by indices
- var sByIndices = SparseWeight8.OrderedByIndex(sByWeights);
- CheckIndexOrdered(sByIndices);
- Assert.That(sByIndices.WeightSum, Is.EqualTo(array2.Sum()));
- Assert.That(sByIndices.Expand(array2.Length), Is.EqualTo(array2));
-
- // equality
- Assert.That(SparseWeight8.AreEqual(sByIndices, sByWeights), Is.True);
- Assert.That(sByWeights.GetHashCode(), Is.EqualTo(sByIndices.GetHashCode()));
- // sum
- var sum = SparseWeight8.Add(sByIndices, sByWeights);
- Assert.That(sum.WeightSum, Is.EqualTo(array2.Sum() * 2));
- // complement normalization
- if (!array2.Any(item => item<0))
- {
- Assert.That(sparse.GetNormalizedWithComplement(int.MaxValue).WeightSum, Is.GreaterThanOrEqualTo(1));
- }
- }
- [Test]
- public void TestSparseCreation()
- {
- var sparse = SparseWeight8.Create
- (
- (9, 9),
- (8, 2),
- (5, 1), // we set these weights separately
- (5, 1), // to check that 5 will pass 8
- (5, 1), // in the sorted set.
- (7, 1)
- );
- Assert.That(sparse[5], Is.EqualTo(3));
- Assert.That(sparse[7], Is.EqualTo(1));
- Assert.That(sparse[8], Is.EqualTo(2));
- Assert.That(sparse[9], Is.EqualTo(9));
- }
- [Test]
- public void TestCreateSparseFromVectors()
- {
- Assert.That
- (
- SparseWeight8.Create(new System.Numerics.Vector4(0, 1, 2, 3), new System.Numerics.Vector4(1, 1, 1, 1)).Expand(4),
- Is.EqualTo(SparseWeight8.Create(1, 1, 1, 1).Expand(4))
- );
- Assert.That
- (
- SparseWeight8.Create(new System.Numerics.Vector4(0, 1, 2, 3), new System.Numerics.Vector4(1, 2, 3, 4)).Expand(4),
- Is.EqualTo(SparseWeight8.Create(1, 2, 3, 4).Expand(4))
- );
- Assert.That
- (
- SparseWeight8.Create(new System.Numerics.Vector4(0, 1, 2, 3), new System.Numerics.Vector4(4, 3, 2, 1)).Expand(4),
- Is.EqualTo(SparseWeight8.Create(4, 3, 2, 1).Expand(4))
- );
- Assert.That
- (
- SparseWeight8.Create(new System.Numerics.Vector4(0, 2, 2, 3), new System.Numerics.Vector4(4, 3, 2, 1)).Expand(4),
- Is.EqualTo(SparseWeight8.Create(4, 0, 5, 1).Expand(4))
- );
- Assert.That
- (
- SparseWeight8.Create(new System.Numerics.Vector4(1, 1, 1, 1), new System.Numerics.Vector4(1, 1, 1, 1)).Expand(4),
- Is.EqualTo(SparseWeight8.Create(0, 4, 0, 0).Expand(4))
- );
- }
- /// <summary>
- /// Creates a new array with only the 8 most relevant weights.
- /// </summary>
- /// <param name="array"></param>
- /// <returns></returns>
- static float[] CreateSparseCompatibleArray(params float[] array)
- {
- const int MAXWEIGHTS = 8;
- if (array == null) return null;
- var threshold =array
- .Select(item => Math.Abs(item))
- .OrderByDescending(item => item)
- .Take(MAXWEIGHTS)
- .Min();
- var array2 = new float[array.Length];
- var c = 0;
- for(int i=0; i < array2.Length; ++i)
- {
- var v = array[i];
- if (v == 0) continue;
- if (Math.Abs(v) >= threshold)
- {
- array2[i] = v;
- ++c;
- if (c >= MAXWEIGHTS) return array2;
- }
- }
- return array2;
- }
- static void CheckWeightOrdered(SparseWeight8 sparse)
- {
- Assert.Multiple(() =>
- {
- Assert.That(Math.Abs(sparse.Weight0), Is.GreaterThanOrEqualTo(Math.Abs(sparse.Weight1)));
- Assert.That(Math.Abs(sparse.Weight1), Is.GreaterThanOrEqualTo(Math.Abs(sparse.Weight2)));
- Assert.That(Math.Abs(sparse.Weight2), Is.GreaterThanOrEqualTo(Math.Abs(sparse.Weight3)));
- Assert.That(Math.Abs(sparse.Weight3), Is.GreaterThanOrEqualTo(Math.Abs(sparse.Weight4)));
- Assert.That(Math.Abs(sparse.Weight4), Is.GreaterThanOrEqualTo(Math.Abs(sparse.Weight5)));
- Assert.That(Math.Abs(sparse.Weight5), Is.GreaterThanOrEqualTo(Math.Abs(sparse.Weight6)));
- Assert.That(Math.Abs(sparse.Weight6), Is.GreaterThanOrEqualTo(Math.Abs(sparse.Weight7)));
- });
- }
- static void CheckIndexOrdered(SparseWeight8 sparse)
- {
- var pairs = sparse.GetIndexedWeights();
- bool zeroFound = false;
- long lastIndex = long.MinValue;
- foreach(var (index,weight) in pairs)
- {
- if (weight == 0) zeroFound = true;
- if (zeroFound)
- {
- Assert.That(index, Is.EqualTo(0));
- Assert.That(weight, Is.EqualTo(0));
- continue;
- }
- Assert.That(index, Is.GreaterThan(lastIndex));
- lastIndex = index;
- }
- }
- [Test]
- public void TestSparseNormalization()
- {
- var sparse1 = SparseWeight8
- .Create(0, 0, 0, 0, 0, 0.1f, 0.7f, 0, 0, 0, 0.1f)
- .GetNormalizedWithComplement(int.MaxValue);
-
- Assert.That(sparse1[5], Is.EqualTo(0.1f));
- Assert.That(sparse1[6], Is.EqualTo(0.7f));
- Assert.That(sparse1[10], Is.EqualTo(0.1f));
- Assert.That(sparse1[int.MaxValue], Is.EqualTo(0.1f).Within(0.0000001f));
- Assert.That(sparse1.WeightSum, Is.EqualTo(1));
- }
- [Test]
- public void TestSparseEquality()
- {
- Assert.That(SparseWeight8.AreEqual(SparseWeight8.Create(0, 1), SparseWeight8.Create(0, 1)), Is.True);
- Assert.That(SparseWeight8.AreEqual(SparseWeight8.Create(0, 1), SparseWeight8.Create(0, 1, 0.25f)), Is.False);
- Assert.That(SparseWeight8.AreEqual(SparseWeight8.Create(0, 1), SparseWeight8.Create(1, 0)), Is.False);
- // check if two "half weights" are equal to one "full weight"
- //Assert.IsTrue(SparseWeight8.AreWeightsEqual(SparseWeight8.Create((3, 5), (3, 5)), SparseWeight8.Create((3, 10))));
- }
- [Test]
- public void TestSparseWeightsLinearInterpolation1()
- {
- var x = SparseWeight8.Create(0,0,1,2); Assert.That(x.Expand(4), Is.EqualTo(new[] { 0f, 0f, 1f, 2f }));
- var y = SparseWeight8.Create(1,2,0,0); Assert.That(y.Expand(4), Is.EqualTo(new[] { 1f, 2f, 0f, 0f }));
- var z = SparseWeight8.InterpolateLinear(x, y, 0.5f);
- Assert.That(z[0], Is.EqualTo(0.5f));
- Assert.That(z[1], Is.EqualTo(1));
- Assert.That(z[2], Is.EqualTo(0.5f));
- Assert.That(z[3], Is.EqualTo(1));
- }
- [Test]
- public void TestSparseWeightsLinearInterpolation2()
- {
- var ax = new float[] { 0, 0, 0, 0, 0, 0.1f, 0.7f, 0, 0, 0, 0.1f };
- var ay = new float[] { 0, 0, 0.2f, 0, 0.1f, 0, 0, 0, 0, 0, 0, 0, 0.2f };
- var cc = Math.Min(ax.Length, ay.Length);
- var x = SparseWeight8.Create(ax); Assert.That(x.Expand(ax.Length), Is.EqualTo(ax));
- var y = SparseWeight8.Create(ay); Assert.That(y.Expand(ay.Length), Is.EqualTo(ay));
- var z = SparseWeight8.InterpolateLinear(x, y, 0.5f);
- for (int i=0; i < cc; ++i)
- {
- var w = (ax[i] + ay[i]) / 2;
- Assert.That(z[i], Is.EqualTo(w));
- }
- }
- [Test]
- public void TestSparseWeightsCubicInterpolation()
- {
- var a = SparseWeight8.Create(0, 0, 0.2f, 0, 0, 0, 1);
- var b = SparseWeight8.Create(1, 1, 0.4f, 0, 0, 1, 0);
- var t = SparseWeight8.Subtract(b, a);
- Assert.That(t[0], Is.EqualTo(1));
- Assert.That(t[1], Is.EqualTo(1));
- Assert.That(t[2], Is.EqualTo(0.2f));
- Assert.That(t[3], Is.EqualTo(0));
- Assert.That(t[4], Is.EqualTo(0));
- Assert.That(t[5], Is.EqualTo(1));
- Assert.That(t[6], Is.EqualTo(-1));
- var lr = SparseWeight8.InterpolateLinear(a, b, 0.4f);
- var cr = SparseWeight8.InterpolateCubic(a, t, b, t, 0.4f);
- Assert.That(cr[0], Is.EqualTo(lr[0]).Within(0.000001f));
- Assert.That(cr[1], Is.EqualTo(lr[1]).Within(0.000001f));
- Assert.That(cr[2], Is.EqualTo(lr[2]).Within(0.000001f));
- Assert.That(cr[3], Is.EqualTo(lr[3]).Within(0.000001f));
- Assert.That(cr[4], Is.EqualTo(lr[4]).Within(0.000001f));
- Assert.That(cr[5], Is.EqualTo(lr[5]).Within(0.000001f));
- Assert.That(cr[6], Is.EqualTo(lr[6]).Within(0.000001f));
- Assert.That(cr[7], Is.EqualTo(lr[7]).Within(0.000001f));
- }
- [Test]
- public void TestSparseWeightReduction()
- {
- var a = SparseWeight8.Create(5, 3, 2, 4, 0, 4, 2, 6, 3, 6, 1);
- var b = a.GetTrimmed(4);
- Assert.That(b.GetNonZeroWeights().Count(), Is.EqualTo(4));
-
- Assert.That(b[0], Is.EqualTo(a[0]));
- Assert.That(b[3], Is.EqualTo(a[3]));
- Assert.That(b[7], Is.EqualTo(a[7]));
- Assert.That(b[9], Is.EqualTo(a[9]));
- Assert.That(b.Weight4, Is.EqualTo(0));
- Assert.That(b.Weight5, Is.EqualTo(0));
- Assert.That(b.Weight6, Is.EqualTo(0));
- Assert.That(b.Weight7, Is.EqualTo(0));
- }
- }
- }
|