From 5cd2528b71cca18d83c2d7c485f31958c24aee85 Mon Sep 17 00:00:00 2001 From: Alexander Luzgarev Date: Sat, 10 Jul 2021 11:56:56 +0200 Subject: [PATCH] Fix #20 --- MatFileHandler.Tests/MatFileReaderTests.cs | 63 ++++++++++++++++++ .../test-data/good/issue20.mat | Bin 0 -> 374 bytes MatFileHandler/DimensionCalculator.cs | 44 ++++++++++++ MatFileHandler/IArray.cs | 13 ++++ MatFileHandler/MatArray.cs | 13 ++++ MatFileHandler/MatNumericalArrayOf.cs | 10 ++- MatFileHandler/MatSparseArrayOf.cs | 17 +++++ 7 files changed, 158 insertions(+), 2 deletions(-) create mode 100644 MatFileHandler.Tests/test-data/good/issue20.mat diff --git a/MatFileHandler.Tests/MatFileReaderTests.cs b/MatFileHandler.Tests/MatFileReaderTests.cs index fd35342..7675f9d 100755 --- a/MatFileHandler.Tests/MatFileReaderTests.cs +++ b/MatFileHandler.Tests/MatFileReaderTests.cs @@ -201,6 +201,19 @@ namespace MatFileHandler.Tests Assert.That((structure["y", 0, 2] as IArrayOf)?[0, 2], Is.EqualTo(3.0)); Assert.That((structure["x", 1, 2] as IArrayOf)?[0], Is.EqualTo(1.5f)); Assert.That(structure["y", 1, 2].IsEmpty, Is.True); + + Assert.That(structure["y", 0, 2].ConvertTo2dDoubleArray(), Is.EqualTo( + new double[,] + { + { 1, 2, 3 }, + { 4, 5, 6 }, + })); + Assert.That(structure["y", 0, 2].ConvertToMultidimensionalDoubleArray(), Is.EqualTo( + new double[,] + { + { 1, 2, 3 }, + { 4, 5, 6 }, + })); } /// @@ -221,6 +234,15 @@ namespace MatFileHandler.Tests Assert.That(sparseArray[0, 4], Is.EqualTo(0.0)); Assert.That(sparseArray[3, 0], Is.EqualTo(0.0)); Assert.That(sparseArray[3, 4], Is.EqualTo(0.0)); + + Assert.That(sparseArray.ConvertTo2dDoubleArray(), Is.EqualTo( + new double[,] + { + { 0, 0, 0, 0, 0 }, + { 0, 1, 2, 0, 0 }, + { 0, 3, 0, 4, 0 }, + { 0, 0, 0, 0, 0 }, + })); } /// @@ -462,6 +484,47 @@ namespace MatFileHandler.Tests Assert.That(d0, Is.Null); } + [Test] + public void Test_3DArrays() + { + var matFile = GetTests("good")["issue20.mat"]; + var obj = matFile["a3d"].Value; + var values = obj.ConvertToDoubleArray(); + Assert.That(values, Is.EqualTo(Enumerable.Range(1, 24))); + var expected = new double[3, 4, 2] + { + { + { 1, 13 }, + { 4, 16 }, + { 7, 19 }, + { 10, 22 }, + }, + { + { 2, 14 }, + { 5, 17 }, + { 8, 20 }, + { 11, 23 }, + }, + { + { 3, 15 }, + { 6, 18 }, + { 9, 21 }, + { 12, 24 }, + }, + }; + Assert.That(obj.ConvertToMultidimensionalDoubleArray(), Is.EqualTo(expected)); + Assert.That(obj.ConvertTo2dDoubleArray(), Is.EqualTo(null)); + } + + [Test] + public void Test_4DArrays() + { + var matFile = GetTests("good")["issue20.mat"]; + var obj = matFile["a4d"].Value; + Assert.That(obj.ConvertToDoubleArray(), Is.EqualTo(Enumerable.Range(1, 120))); + Assert.That(obj.ConvertTo2dDoubleArray(), Is.EqualTo(null)); + } + private static AbstractTestDataFactory GetTests(string factoryName) => new MatTestDataFactory(Path.Combine(TestDirectory, factoryName)); diff --git a/MatFileHandler.Tests/test-data/good/issue20.mat b/MatFileHandler.Tests/test-data/good/issue20.mat new file mode 100644 index 0000000000000000000000000000000000000000..7e6683dabfad17e726208d82512788ddfdf1149f GIT binary patch literal 374 zcmeZu4DoSvQZUssQ1EpO(M`+DN!3vZ$Vn_o%P-2cQV4Jk_w+L}(NS}aZCnRt%B$+8Z zYq+Fvfa{2j!x^3vF8_t(#tkGKEdaA3iM2^The=s2 x * y); } + + /// + /// Rearrange data from a flat (column-major) array into a multi-dimensional array. + /// + /// Array element type. + /// Target array dimensions. + /// Flat (column-major) data to rearrange. + /// An array of specified dimensions containing data from the original flat array, layed out according to column-major order. + public static Array UnflattenArray(this int[] dimensions, T[] data) + { + var result = Array.CreateInstance(typeof(T), dimensions); + var n = dimensions.NumberOfElements(); + var indices = new int[dimensions.Length]; + for (var i = 0; i < n; i++) + { + result.SetValue(data[i], indices); + IncrementMultiIndex(dimensions, indices); + } + + return result; + } + + private static void IncrementMultiIndex(int[] dimensions, int[] indices) + { + var currentPosition = 0; + while (true) + { + if (currentPosition >= indices.Length) + { + break; + } + indices[currentPosition]++; + if (indices[currentPosition] >= dimensions[currentPosition]) + { + indices[currentPosition] = 0; + currentPosition++; + } + else + { + break; + } + } + } } } \ No newline at end of file diff --git a/MatFileHandler/IArray.cs b/MatFileHandler/IArray.cs index a1e88b2..a0b5dd4 100755 --- a/MatFileHandler/IArray.cs +++ b/MatFileHandler/IArray.cs @@ -1,5 +1,6 @@ // Copyright 2017-2018 Alexander Luzgarev +using System; using System.Numerics; namespace MatFileHandler @@ -30,6 +31,18 @@ namespace MatFileHandler /// Array of values of the array, converted to Double, or null if the conversion is not possible. double[]? ConvertToDoubleArray(); + /// + /// Tries to convert the array to a 2-dimensional array of Double values. + /// + /// 2-dimensional array of values of the array, converted to Double, or null if the conversion is not possible (for example, when the array has more than 2 dimensions). + double[,]? ConvertTo2dDoubleArray(); + + /// + /// Tries to convert the array to a multidimensional array of Double values. + /// + /// Multidimensional array of values of the array, converted to Double, or null if the conversion is not possible. + Array? ConvertToMultidimensionalDoubleArray(); + /// /// Tries to convert the array to an array of Complex values. /// diff --git a/MatFileHandler/MatArray.cs b/MatFileHandler/MatArray.cs index ecf0e1e..ea5cfeb 100755 --- a/MatFileHandler/MatArray.cs +++ b/MatFileHandler/MatArray.cs @@ -1,5 +1,6 @@ // Copyright 2017-2018 Alexander Luzgarev +using System; using System.Numerics; namespace MatFileHandler @@ -59,6 +60,18 @@ namespace MatFileHandler return null; } + /// + public virtual double[,]? ConvertTo2dDoubleArray() + { + return ConvertToMultidimensionalDoubleArray() as double[,]; + } + + /// + public virtual Array? ConvertToMultidimensionalDoubleArray() + { + return null; + } + /// public virtual Complex[]? ConvertToComplexArray() { diff --git a/MatFileHandler/MatNumericalArrayOf.cs b/MatFileHandler/MatNumericalArrayOf.cs index 0fce0c3..762dea3 100755 --- a/MatFileHandler/MatNumericalArrayOf.cs +++ b/MatFileHandler/MatNumericalArrayOf.cs @@ -1,8 +1,6 @@ // Copyright 2017-2018 Alexander Luzgarev using System; -using System.Collections.Generic; -using System.Linq; using System.Numerics; namespace MatFileHandler @@ -59,6 +57,14 @@ namespace MatFileHandler }; } + /// + public override Array? ConvertToMultidimensionalDoubleArray() + { + var doubleData = ConvertToDoubleArray(); + var rearrangedData = Dimensions.UnflattenArray(doubleData); + return rearrangedData; + } + /// /// Tries to convert the array to an array of Complex values. /// diff --git a/MatFileHandler/MatSparseArrayOf.cs b/MatFileHandler/MatSparseArrayOf.cs index 8c60e4e..acd34d5 100755 --- a/MatFileHandler/MatSparseArrayOf.cs +++ b/MatFileHandler/MatSparseArrayOf.cs @@ -64,6 +64,23 @@ namespace MatFileHandler return data as double[] ?? data.Select(x => Convert.ToDouble(x)).ToArray(); } + /// + public override Array? ConvertToMultidimensionalDoubleArray() + { + if (Dimensions.Length != 2) + { + return null; + } + + var result = new double[Dimensions[0], Dimensions[1]]; + foreach (var pair in Data) + { + result[pair.Key.row, pair.Key.column] = Convert.ToDouble(pair.Value); + } + + return result; + } + /// /// Tries to convert the array to an array of Complex values. ///