diff --git a/src/TMG-Framework/Construct/ConstructTimePeriodFromTimes.cs b/src/TMG-Framework/Construct/ConstructTimePeriodFromTimes.cs
index ec91489..82f9103 100644
--- a/src/TMG-Framework/Construct/ConstructTimePeriodFromTimes.cs
+++ b/src/TMG-Framework/Construct/ConstructTimePeriodFromTimes.cs
@@ -16,26 +16,23 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
You should have received a copy of the GNU General Public License
along with TMG-Framework for XTMF2. If not, see .
*/
-using System;
-using System.Collections.Generic;
-using System.Text;
+
using XTMF2;
-namespace TMG.Construct
+namespace TMG.Construct;
+
+[Module(Name = "Construct Time Period from Times", Description = "Given the start and end times construct a time period.",
+ DocumentationLink = "http://tmg.utoronto.ca/doc/2.0")]
+public sealed class ConstructTimePeriodFromTimes : BaseFunction
{
- [Module(Name = "Construct Time Period from Times", Description = "Given the start and end times construct a time period.",
- DocumentationLink = "http://tmg.utoronto.ca/doc/2.0")]
- public sealed class ConstructTimePeriodFromTimes : BaseFunction
- {
- [Parameter(Index = 0, Name = "Start Time", Required = true, Description = "The time to use as the starting point of the time period (Inclusive).")]
- public IFunction StartTime = null!;
+ [Parameter(Index = 0, Name = "Start Time", Required = true, Description = "The time to use as the starting point of the time period (Inclusive).")]
+ public IFunction StartTime = null!;
- [Parameter(Index = 1, Name = "End Time", Required = true, Description = "The time to use as the ending point of the time period (Exclusive).")]
- public IFunction EndTime = null!;
+ [Parameter(Index = 1, Name = "End Time", Required = true, Description = "The time to use as the ending point of the time period (Exclusive).")]
+ public IFunction EndTime = null!;
- public override TimePeriod Invoke()
- {
- return new TimePeriod(StartTime.Invoke(), EndTime.Invoke());
- }
+ public override TimePeriod Invoke()
+ {
+ return new TimePeriod(StartTime.Invoke(), EndTime.Invoke());
}
}
diff --git a/src/TMG-Framework/Convert/ConvertTimesToTimePeriod.cs b/src/TMG-Framework/Convert/ConvertTimesToTimePeriod.cs
index 2ba463b..4eb93a1 100644
--- a/src/TMG-Framework/Convert/ConvertTimesToTimePeriod.cs
+++ b/src/TMG-Framework/Convert/ConvertTimesToTimePeriod.cs
@@ -16,13 +16,11 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
You should have received a copy of the GNU General Public License
along with TMG-Framework for XTMF2. If not, see .
*/
-using System;
-using System.Collections.Generic;
-using System.Text;
+
using XTMF2;
-namespace TMG.Convert
-{
+namespace TMG.Convert;
+
[Module(Name = "Convert Times to Time Period", Description = "Takes in a start and end time to generate a time period.",
DocumentationLink = "http://tmg.utoronto.ca/doc/2.0")]
public sealed class ConvertTimesToTimePeriod : BaseFunction<(Time start, Time end), TimePeriod>
@@ -32,4 +30,3 @@ public override TimePeriod Invoke((Time start, Time end) context)
return new TimePeriod(context.start, context.end);
}
}
-}
diff --git a/src/TMG-Framework/Data/Categories.cs b/src/TMG-Framework/Data/Categories.cs
index a5bf743..f1a6236 100644
--- a/src/TMG-Framework/Data/Categories.cs
+++ b/src/TMG-Framework/Data/Categories.cs
@@ -16,128 +16,122 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
You should have received a copy of the GNU General Public License
along with TMG-Framework for XTMF2. If not, see .
*/
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.Linq;
using static TMG.Utilities.ExceptionHelper;
using System.Collections;
-using System.Diagnostics.CodeAnalysis;
-namespace TMG
+namespace TMG;
+
+///
+///
+///
+public sealed class Categories : IEnumerable
{
///
- ///
+ /// Get the number of elements in the categories.
///
- public sealed class Categories : IEnumerable
- {
- ///
- /// Get the number of elements in the categories.
- ///
- public int Count => _elements.Count;
+ public int Count => _elements.Count;
- ///
- /// TODO: Update the representation later on to something more efficient
- ///
- private readonly List _elements;
+ ///
+ /// TODO: Update the representation later on to something more efficient
+ ///
+ private readonly List _elements;
- ///
- /// Create a Categories instance from a list of elements
- ///
- /// The list of elements to use, values will be sorted, any duplicates will return in failure.
- /// The error message if creation fails
- /// True if creation succeeds, false otherwise
- public static bool CreateCategories(List elements,
- [NotNullWhen(true)] out Categories? categories,
- [NotNullWhen(false)] ref string? error)
+ ///
+ /// Create a Categories instance from a list of elements
+ ///
+ /// The list of elements to use, values will be sorted, any duplicates will return in failure.
+ /// The error message if creation fails
+ /// True if creation succeeds, false otherwise
+ public static bool CreateCategories(List elements,
+ [NotNullWhen(true)] out Categories? categories,
+ [NotNullWhen(false)] ref string? error)
+ {
+ elements = elements?.ToList() ?? throw new ArgumentNullException(nameof(elements));
+ elements.Sort();
+ for (int i = 1; i < elements.Count; i++)
{
- elements = elements?.ToList() ?? throw new ArgumentNullException(nameof(elements));
- elements.Sort();
- for (int i = 1; i < elements.Count; i++)
+ if (elements[i - 1] == elements[i])
{
- if(elements[i - 1] == elements[i])
- {
- error = $"Found a duplicate category {elements[i]}!";
- categories = null;
- return false;
- }
+ error = $"Found a duplicate category {elements[i]}!";
+ categories = null;
+ return false;
}
- categories = new Categories(elements);
- return true;
}
+ categories = new Categories(elements);
+ return true;
+ }
- ///
- /// Create a Categories instance from a list of elements
- ///
- /// The list of elements to use, values will be sorted, any duplicates will return in failure.
- /// The error message if creation fails
- /// True if creation succeeds, false otherwise
- public static bool CreateCategories(Span elements,
- [NotNullWhen(true)] out Categories? categories,
- [NotNullWhen(false)] ref string? error)
+ ///
+ /// Create a Categories instance from a list of elements
+ ///
+ /// The list of elements to use, values will be sorted, any duplicates will return in failure.
+ /// The error message if creation fails
+ /// True if creation succeeds, false otherwise
+ public static bool CreateCategories(Span elements,
+ [NotNullWhen(true)] out Categories? categories,
+ [NotNullWhen(false)] ref string? error)
+ {
+ var list = new List(elements.ToArray());
+ list.Sort();
+ for (int i = 1; i < list.Count; i++)
{
- var list = new List(elements.ToArray());
- list.Sort();
- for (int i = 1; i < list.Count; i++)
+ if (list[i - 1] == list[i])
{
- if(list[i - 1] == list[i])
- {
- error = $"Found a duplicate category {list[i]}!";
- categories = null;
- return false;
- }
+ error = $"Found a duplicate category {list[i]}!";
+ categories = null;
+ return false;
}
- categories = new Categories(list);
- return true;
}
+ categories = new Categories(list);
+ return true;
+ }
- ///
- /// Create a Categories instance from a list of elements
- ///
- /// The sorted list of elements to use
- private Categories(List elements)
+ ///
+ /// Create a Categories instance from a list of elements
+ ///
+ /// The sorted list of elements to use
+ private Categories(List elements)
+ {
+ if (elements == null)
{
- if(elements == null)
- {
- ThrowParameterNull(nameof(elements));
- }
- _elements = elements;
+ ThrowParameterNull(nameof(elements));
}
+ _elements = elements;
+ }
- ///
- /// Gives the flat index of the specified sparse index, or less than 0 if the sparse index is not in the map.
- ///
- /// The sparse index to look up
- /// Gives the flat index of the specified sparse index, or less than 0 if the sparse index is not in the map.
- public int GetFlatIndex(CategoryIndex sparseIndex)
- {
- return _elements.BinarySearch(sparseIndex);
- }
+ ///
+ /// Gives the flat index of the specified sparse index, or less than 0 if the sparse index is not in the map.
+ ///
+ /// The sparse index to look up
+ /// Gives the flat index of the specified sparse index, or less than 0 if the sparse index is not in the map.
+ public int GetFlatIndex(CategoryIndex sparseIndex)
+ {
+ return _elements.BinarySearch(sparseIndex);
+ }
- ///
- ///
- ///
- ///
- ///
- public CategoryIndex GetSparseIndex(int flatIndex)
+ ///
+ ///
+ ///
+ ///
+ ///
+ public CategoryIndex GetSparseIndex(int flatIndex)
+ {
+ if (flatIndex < 0 || flatIndex >= _elements.Count)
{
- if(flatIndex < 0 || flatIndex >= _elements.Count)
- {
- ThrowOutOfRangeException(nameof(flatIndex));
- }
- return _elements[flatIndex];
+ ThrowOutOfRangeException(nameof(flatIndex));
}
+ return _elements[flatIndex];
+ }
- ///
- public IEnumerator GetEnumerator()
- {
- return _elements.GetEnumerator();
- }
+ ///
+ public IEnumerator GetEnumerator()
+ {
+ return _elements.GetEnumerator();
+ }
- ///
- IEnumerator IEnumerable.GetEnumerator()
- {
- return ((IEnumerable)_elements).GetEnumerator();
- }
+ ///
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return ((IEnumerable)_elements).GetEnumerator();
}
}
diff --git a/src/TMG-Framework/Data/CategoryIndex.cs b/src/TMG-Framework/Data/CategoryIndex.cs
index f500047..517c495 100644
--- a/src/TMG-Framework/Data/CategoryIndex.cs
+++ b/src/TMG-Framework/Data/CategoryIndex.cs
@@ -16,107 +16,103 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
You should have received a copy of the GNU General Public License
along with TMG-Framework for XTMF2. If not, see .
*/
-using System;
-using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
-using System.Text;
-namespace TMG
+namespace TMG;
+
+///
+/// Represents an index into an object of Categories.
+///
+public readonly struct CategoryIndex : IEquatable, IComparable, IEqualityComparer
{
- ///
- /// Represents an index into an object of Categories.
- ///
- public readonly struct CategoryIndex : IEquatable, IComparable, IEqualityComparer
- {
- private readonly int _Value;
+ private readonly int _Value;
- public CategoryIndex(int value)
- {
- _Value = value;
- }
+ public CategoryIndex(int value)
+ {
+ _Value = value;
+ }
- ///
- /// Test if the value is a valid reference to the category
- ///
- public bool Exists => _Value >= 0;
+ ///
+ /// Test if the value is a valid reference to the category
+ ///
+ public bool Exists => _Value >= 0;
- public static implicit operator int(CategoryIndex index) => index._Value;
+ public static implicit operator int(CategoryIndex index) => index._Value;
- public static implicit operator CategoryIndex(int index) => new(index);
+ public static implicit operator CategoryIndex(int index) => new(index);
- public static bool TryParse(string s, out CategoryIndex result)
+ public static bool TryParse(string s, out CategoryIndex result)
+ {
+ if (!int.TryParse(s, out int temp))
{
- if (!int.TryParse(s, out int temp))
- {
- result = temp;
- return true;
- }
- result = -1;
- return false;
+ result = temp;
+ return true;
}
+ result = -1;
+ return false;
+ }
- public bool Equals(CategoryIndex x, CategoryIndex y)
- {
- return x._Value == y._Value;
- }
+ public bool Equals(CategoryIndex x, CategoryIndex y)
+ {
+ return x._Value == y._Value;
+ }
- public int GetHashCode([DisallowNull] CategoryIndex obj)
- {
- return obj._Value.GetHashCode();
- }
+ public int GetHashCode([DisallowNull] CategoryIndex obj)
+ {
+ return obj._Value.GetHashCode();
+ }
- public int CompareTo(CategoryIndex other)
- {
- return _Value.CompareTo(other._Value);
- }
+ public int CompareTo(CategoryIndex other)
+ {
+ return _Value.CompareTo(other._Value);
+ }
- public bool Equals(CategoryIndex other)
- {
- return _Value == other._Value;
- }
+ public bool Equals(CategoryIndex other)
+ {
+ return _Value == other._Value;
+ }
- public override bool Equals(object? obj)
+ public override bool Equals(object? obj)
+ {
+ if (obj is CategoryIndex other)
{
- if (obj is CategoryIndex other)
- {
- return Equals(other);
- }
- return false;
+ return Equals(other);
}
+ return false;
+ }
- public override int GetHashCode()
- {
- return _Value.GetHashCode();
- }
+ public override int GetHashCode()
+ {
+ return _Value.GetHashCode();
+ }
- public static bool operator ==(CategoryIndex left, CategoryIndex right)
- {
- return left._Value == right._Value;
- }
+ public static bool operator ==(CategoryIndex left, CategoryIndex right)
+ {
+ return left._Value == right._Value;
+ }
- public static bool operator !=(CategoryIndex left, CategoryIndex right)
- {
- return left._Value != right._Value;
- }
+ public static bool operator !=(CategoryIndex left, CategoryIndex right)
+ {
+ return left._Value != right._Value;
+ }
- public static bool operator <(CategoryIndex left, CategoryIndex right)
- {
- return left._Value < right._Value;
- }
+ public static bool operator <(CategoryIndex left, CategoryIndex right)
+ {
+ return left._Value < right._Value;
+ }
- public static bool operator <=(CategoryIndex left, CategoryIndex right)
- {
- return left._Value <= right._Value;
- }
+ public static bool operator <=(CategoryIndex left, CategoryIndex right)
+ {
+ return left._Value <= right._Value;
+ }
- public static bool operator >(CategoryIndex left, CategoryIndex right)
- {
- return left._Value > right._Value;
- }
+ public static bool operator >(CategoryIndex left, CategoryIndex right)
+ {
+ return left._Value > right._Value;
+ }
- public static bool operator >=(CategoryIndex left, CategoryIndex right)
- {
- return left._Value >= right._Value;
- }
+ public static bool operator >=(CategoryIndex left, CategoryIndex right)
+ {
+ return left._Value >= right._Value;
}
}
+
diff --git a/src/TMG-Framework/Data/CategoryMap.cs b/src/TMG-Framework/Data/CategoryMap.cs
index cd96643..b725a54 100644
--- a/src/TMG-Framework/Data/CategoryMap.cs
+++ b/src/TMG-Framework/Data/CategoryMap.cs
@@ -16,174 +16,168 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
You should have received a copy of the GNU General Public License
along with TMG-Framework for XTMF2. If not, see .
*/
-using System;
-using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
-using System.Linq;
-using System.Text;
using static TMG.Utilities.ExceptionHelper;
-namespace TMG
+namespace TMG;
+
+///
+/// Provides a mapping between categories and provides a method for aggregating
+/// data from the base categories to the destination categories.
+///
+public sealed class CategoryMap
{
///
- /// Provides a mapping between categories and provides a method for aggregating
- /// data from the base categories to the destination categories.
+ /// The categories to start with.
+ ///
+ public Categories Base { get; }
+
+ ///
+ /// The categories to converge the base into.
+ ///
+ public Categories Destination { get; }
+
+ ///
+ /// The mapping between the two category types.
///
- public sealed class CategoryMap
+ private readonly List<(int originFlatIndex, int destinationFlatIndex)> _baseToDestination;
+
+ public static bool CreateCategoryMap(Categories baseCategories, Categories destinationCategories,
+ List<(int originFlatIndex, int destinationFlatIndex)> baseToDestination,
+ [NotNullWhen(true)] out CategoryMap? map,
+ [NotNullWhen(false)] ref string? error)
{
- ///
- /// The categories to start with.
- ///
- public Categories Base { get; }
-
- ///
- /// The categories to converge the base into.
- ///
- public Categories Destination { get; }
-
- ///
- /// The mapping between the two category types.
- ///
- private readonly List<(int originFlatIndex, int destinationFlatIndex)> _baseToDestination;
-
- public static bool CreateCategoryMap(Categories baseCategories, Categories destinationCategories,
- List<(int originFlatIndex, int destinationFlatIndex)> baseToDestination,
- [NotNullWhen(true) ] out CategoryMap? map,
- [NotNullWhen(false)] ref string? error)
+ if (baseCategories == null)
{
- if (baseCategories == null)
- {
- ThrowParameterNull(nameof(baseCategories));
- }
- if (destinationCategories == null)
- {
- ThrowParameterNull(nameof(destinationCategories));
- }
- if (baseToDestination == null)
- {
- ThrowParameterNull(nameof(baseToDestination));
- }
- if (ValidateMapping(baseCategories, destinationCategories, baseToDestination, ref error))
- {
- map = new CategoryMap(baseCategories, destinationCategories, baseToDestination);
- return true;
- }
- map = null;
- return false;
+ ThrowParameterNull(nameof(baseCategories));
}
-
- ///
- /// Given two categories create the mapping between the two.
- ///
- /// The larger set of categories.
- /// The different set of categories the base will be mapped to.
- /// The individual linking records from base to destination categories.
- private CategoryMap(Categories baseCategories, Categories destinationCategories,
- List<(int originFlatIndex, int destinationFlatIndex)> baseToDestination)
+ if (destinationCategories == null)
{
- if (baseCategories == null)
- {
- ThrowParameterNull(nameof(baseCategories));
- }
- if (destinationCategories == null)
- {
- ThrowParameterNull(nameof(destinationCategories));
- }
- if (baseToDestination == null)
- {
- ThrowParameterNull(nameof(baseToDestination));
- }
- Base = baseCategories;
- Destination = destinationCategories;
- _baseToDestination = baseToDestination;
+ ThrowParameterNull(nameof(destinationCategories));
}
-
- private static bool FailWith([NotNullWhen(false)] ref string? error, string message)
+ if (baseToDestination == null)
{
- error = message;
- return false;
+ ThrowParameterNull(nameof(baseToDestination));
}
-
- ///
- /// Ensure that all of the indexes exist in the base and destination categories.
- ///
- ///
- private static bool ValidateMapping(Categories baseCategories, Categories destinationCategories,
- List<(int originFlatIndex, int destinationFlatIndex)> baseToDestination,
- [NotNullWhen(false)] ref string? error)
+ if (ValidateMapping(baseCategories, destinationCategories, baseToDestination, ref error))
{
- if (baseCategories == null)
- {
- return FailWith(ref error, "baseCategories was null!");
- }
- if (destinationCategories == null)
- {
- return FailWith(ref error, "destinationCategories was null!");
- }
- if (baseToDestination == null)
- {
- return FailWith(ref error, "baseToDestination was null!");
- }
- foreach (var (originFlatIndex, destinationFlatIndex) in baseToDestination)
- {
- if (originFlatIndex < 0 || originFlatIndex >= baseCategories.Count)
- return FailWith(ref error, $"The base categories does not contain a flat index of {originFlatIndex}!");
- if (destinationFlatIndex < 0 || destinationFlatIndex >= destinationCategories.Count)
- return FailWith(ref error, $"The destination categories does not contain a flat index of {destinationFlatIndex}!");
- }
+ map = new CategoryMap(baseCategories, destinationCategories, baseToDestination);
return true;
}
+ map = null;
+ return false;
+ }
-
- ///
- /// Aggregate the baseVector data into the destination category system.
- ///
- /// The vector to aggregate
- ///
- ///
- ///
- public bool AggregateToDestination(Vector baseVector,
- [NotNullWhen(true)] out Vector? ret,
- [NotNullWhen(false)] ref string? error)
+ ///
+ /// Given two categories create the mapping between the two.
+ ///
+ /// The larger set of categories.
+ /// The different set of categories the base will be mapped to.
+ /// The individual linking records from base to destination categories.
+ private CategoryMap(Categories baseCategories, Categories destinationCategories,
+ List<(int originFlatIndex, int destinationFlatIndex)> baseToDestination)
+ {
+ if (baseCategories == null)
{
- ret = null;
- if (baseVector is null)
- {
- return FailWith(ref error, "baseVector was null!");
- }
- if (baseVector.Categories != Base)
- {
- return FailWith(ref error, "Invalid Base Categories");
- }
- ret = new Vector(Destination);
- var b = baseVector.Data;
- var r = ret.Data;
- foreach (var (originFlatIndex, destinationFlatIndex) in _baseToDestination)
- {
- r[destinationFlatIndex] += b[originFlatIndex];
- }
- return true;
+ ThrowParameterNull(nameof(baseCategories));
+ }
+ if (destinationCategories == null)
+ {
+ ThrowParameterNull(nameof(destinationCategories));
+ }
+ if (baseToDestination == null)
+ {
+ ThrowParameterNull(nameof(baseToDestination));
}
+ Base = baseCategories;
+ Destination = destinationCategories;
+ _baseToDestination = baseToDestination;
+ }
+
+ private static bool FailWith([NotNullWhen(false)] ref string? error, string message)
+ {
+ error = message;
+ return false;
+ }
- ///
- /// Creates a reverse index of destination category indexes relating them to the list of Base category indexes that they map.
- ///
- /// A reverse index dictionary mapping Destination elements to a list of base category indexes that represent them.
- public Dictionary> CreateReverseIndex()
+ ///
+ /// Ensure that all of the indexes exist in the base and destination categories.
+ ///
+ ///
+ private static bool ValidateMapping(Categories baseCategories, Categories destinationCategories,
+ List<(int originFlatIndex, int destinationFlatIndex)> baseToDestination,
+ [NotNullWhen(false)] ref string? error)
+ {
+ if (baseCategories == null)
+ {
+ return FailWith(ref error, "baseCategories was null!");
+ }
+ if (destinationCategories == null)
+ {
+ return FailWith(ref error, "destinationCategories was null!");
+ }
+ if (baseToDestination == null)
+ {
+ return FailWith(ref error, "baseToDestination was null!");
+ }
+ foreach (var (originFlatIndex, destinationFlatIndex) in baseToDestination)
{
- return _baseToDestination
- .GroupBy(record => record.destinationFlatIndex)
- .ToDictionary(group => (CategoryIndex)group.Key, group => group.Select(record => (CategoryIndex)record.originFlatIndex).ToList());
+ if (originFlatIndex < 0 || originFlatIndex >= baseCategories.Count)
+ return FailWith(ref error, $"The base categories does not contain a flat index of {originFlatIndex}!");
+ if (destinationFlatIndex < 0 || destinationFlatIndex >= destinationCategories.Count)
+ return FailWith(ref error, $"The destination categories does not contain a flat index of {destinationFlatIndex}!");
}
+ return true;
+ }
+
- ///
- /// Creates an index of base category to destination category indexes.
- ///
- /// A dictionary containing the mapping between base CategoryIndex to destination CategoryIndex.
- public Dictionary CreateIndex()
+ ///
+ /// Aggregate the baseVector data into the destination category system.
+ ///
+ /// The vector to aggregate
+ ///
+ ///
+ ///
+ public bool AggregateToDestination(Vector baseVector,
+ [NotNullWhen(true)] out Vector? ret,
+ [NotNullWhen(false)] ref string? error)
+ {
+ ret = null;
+ if (baseVector is null)
+ {
+ return FailWith(ref error, "baseVector was null!");
+ }
+ if (baseVector.Categories != Base)
+ {
+ return FailWith(ref error, "Invalid Base Categories");
+ }
+ ret = new Vector(Destination);
+ var b = baseVector.Data;
+ var r = ret.Data;
+ foreach (var (originFlatIndex, destinationFlatIndex) in _baseToDestination)
{
- return _baseToDestination
- .ToDictionary(record => (CategoryIndex)record.originFlatIndex, record => (CategoryIndex)record.destinationFlatIndex);
+ r[destinationFlatIndex] += b[originFlatIndex];
}
+ return true;
+ }
+
+ ///
+ /// Creates a reverse index of destination category indexes relating them to the list of Base category indexes that they map.
+ ///
+ /// A reverse index dictionary mapping Destination elements to a list of base category indexes that represent them.
+ public Dictionary> CreateReverseIndex()
+ {
+ return _baseToDestination
+ .GroupBy(record => record.destinationFlatIndex)
+ .ToDictionary(group => (CategoryIndex)group.Key, group => group.Select(record => (CategoryIndex)record.originFlatIndex).ToList());
+ }
+
+ ///
+ /// Creates an index of base category to destination category indexes.
+ ///
+ /// A dictionary containing the mapping between base CategoryIndex to destination CategoryIndex.
+ public Dictionary CreateIndex()
+ {
+ return _baseToDestination
+ .ToDictionary(record => (CategoryIndex)record.originFlatIndex, record => (CategoryIndex)record.destinationFlatIndex);
}
}
diff --git a/src/TMG-Framework/Data/Matrix.cs b/src/TMG-Framework/Data/Matrix.cs
index bbe6923..a421160 100644
--- a/src/TMG-Framework/Data/Matrix.cs
+++ b/src/TMG-Framework/Data/Matrix.cs
@@ -16,245 +16,238 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
You should have received a copy of the GNU General Public License
along with TMG-Framework for XTMF2. If not, see .
*/
-using System;
using System.Buffers;
-using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
-using System.Runtime.CompilerServices;
-using System.Text;
-using System.Threading;
using static TMG.Utilities.ExceptionHelper;
-namespace TMG
+namespace TMG;
+
+///
+/// A 2D representation with categories for rows and columns
+///
+public sealed class Matrix : IDisposable
{
///
- /// A 2D representation with categories for rows and columns
+ /// The categories for the rows.
///
- public sealed class Matrix : IDisposable
- {
- ///
- /// The categories for the rows.
- ///
- public Categories RowCategories { get; }
+ public Categories RowCategories { get; }
- ///
- /// The categories for the columns.
- ///
- public Categories ColumnCategories { get; }
+ ///
+ /// The categories for the columns.
+ ///
+ public Categories ColumnCategories { get; }
- ///
- /// The backend storage for the matrix
- ///
- public Span Data => _backingMemory is null ? ThrowAlreadyDisposed() : _backingMemory.Value.Span;
+ ///
+ /// The backend storage for the matrix
+ ///
+ public Span Data => _backingMemory is null ? ThrowAlreadyDisposed() : _backingMemory.Value.Span;
- [DoesNotReturn]
- private Span ThrowAlreadyDisposed()
- {
- throw new ObjectDisposedException(nameof(Matrix));
- }
+ [DoesNotReturn]
+ private Span ThrowAlreadyDisposed()
+ {
+ throw new ObjectDisposedException(nameof(Matrix));
+ }
- private Memory? _backingMemory;
+ private Memory? _backingMemory;
- ///
- /// Used as a quick lookup for the number of columns per row.
- ///
- private readonly int _rowSpan;
+ ///
+ /// Used as a quick lookup for the number of columns per row.
+ ///
+ private readonly int _rowSpan;
- private IMemoryOwner? _allocator;
+ private IMemoryOwner? _allocator;
- ///
- /// Create a new matrix with the given row and column categories.
- ///
- /// The categories for the rows.
- /// The categories for the columns.
- public Matrix(Categories rowCategories, Categories columnCategories) : this(rowCategories, columnCategories, null) { }
+ ///
+ /// Create a new matrix with the given row and column categories.
+ ///
+ /// The categories for the rows.
+ /// The categories for the columns.
+ public Matrix(Categories rowCategories, Categories columnCategories) : this(rowCategories, columnCategories, null) { }
- ///
- /// Get the number of columns in this matrix.
- ///
- public int NumberOfColumns => ColumnCategories.Count;
+ ///
+ /// Get the number of columns in this matrix.
+ ///
+ public int NumberOfColumns => ColumnCategories.Count;
- ///
- /// Get the number of rows in this matrix.
- ///
- public int NumberOfRows => RowCategories.Count;
+ ///
+ /// Get the number of rows in this matrix.
+ ///
+ public int NumberOfRows => RowCategories.Count;
- ///
- /// Create a new matrix with the given row and column categories.
- ///
- /// The categories for the rows.
- /// The categories for the columns.
- /// The memory pool to use for the matrix data.
- public Matrix(Categories rowCategories, Categories columnCategories, MemoryPool? allocator)
- {
- RowCategories = rowCategories ?? ThrowParameterNull(nameof(rowCategories));
- ColumnCategories = columnCategories ?? ThrowParameterNull(nameof(columnCategories));
- _rowSpan = ColumnCategories.Count;
- var size = RowCategories.Count * ColumnCategories.Count;
- _backingMemory = allocator is null ?
- new float[size].AsMemory()
- : (_allocator = allocator.Rent(size)).Memory[..size];
- }
+ ///
+ /// Create a new matrix with the given row and column categories.
+ ///
+ /// The categories for the rows.
+ /// The categories for the columns.
+ /// The memory pool to use for the matrix data.
+ public Matrix(Categories rowCategories, Categories columnCategories, MemoryPool? allocator)
+ {
+ RowCategories = rowCategories ?? ThrowParameterNull(nameof(rowCategories));
+ ColumnCategories = columnCategories ?? ThrowParameterNull(nameof(columnCategories));
+ _rowSpan = ColumnCategories.Count;
+ var size = RowCategories.Count * ColumnCategories.Count;
+ _backingMemory = allocator is null ?
+ new float[size].AsMemory()
+ : (_allocator = allocator.Rent(size)).Memory[..size];
+ }
- ///
- /// Create a new matrix using the dimensions from the given vector.
- ///
- /// The vector to get the dimensions from.
- public Matrix(Vector vector) : this(vector, null) { }
+ ///
+ /// Create a new matrix using the dimensions from the given vector.
+ ///
+ /// The vector to get the dimensions from.
+ public Matrix(Vector vector) : this(vector, null) { }
- public Matrix(Vector vector, MemoryPool? allocator)
+ public Matrix(Vector vector, MemoryPool? allocator)
+ {
+ if (vector is null)
{
- if (vector is null)
- {
- ThrowParameterNull(nameof(vector));
- }
- ColumnCategories = RowCategories = vector.Categories;
- _rowSpan = ColumnCategories.Count;
- var size = RowCategories.Count * ColumnCategories.Count;
- _backingMemory = allocator is null ?
- new float[size].AsMemory() :
- (_allocator = allocator.Rent(size)).Memory[..size];
+ ThrowParameterNull(nameof(vector));
}
+ ColumnCategories = RowCategories = vector.Categories;
+ _rowSpan = ColumnCategories.Count;
+ var size = RowCategories.Count * ColumnCategories.Count;
+ _backingMemory = allocator is null ?
+ new float[size].AsMemory() :
+ (_allocator = allocator.Rent(size)).Memory[..size];
+ }
- ///
- /// Create a new matrix with the dimensions from the provided
- /// matrix.
- ///
- /// The matrix to copy the dimensions from.
- public Matrix(Matrix matrix) : this(matrix, null) {}
-
- ///
- /// Create a new matrix with the dimensions from the provided
- ///
- /// The matrix to copy the dimensions from.
- /// The memory pool to use for the matrix data.
- public Matrix(Matrix matrix, MemoryPool? allocator)
- {
- if (matrix is null)
- {
- ThrowParameterNull(nameof(matrix));
- }
- RowCategories = matrix.RowCategories;
- ColumnCategories = matrix.ColumnCategories;
- _rowSpan = matrix._rowSpan;
- var size = RowCategories.Count * ColumnCategories.Count;
- _backingMemory = allocator is null ?
- new float[size].AsMemory() :
- (_allocator = allocator.Rent(size)).Memory[..size];
- }
+ ///
+ /// Create a new matrix with the dimensions from the provided
+ /// matrix.
+ ///
+ /// The matrix to copy the dimensions from.
+ public Matrix(Matrix matrix) : this(matrix, null) { }
- ///
- /// Get the row and column for a given flat index into the backend data
- ///
- /// The flat index in the data to get the sparse row and column for.
- /// The row and column in sparse space for this flat index.
- [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
- public (CategoryIndex Row, CategoryIndex Column) GetSparseIndex(int flatIndex)
+ ///
+ /// Create a new matrix with the dimensions from the provided
+ ///
+ /// The matrix to copy the dimensions from.
+ /// The memory pool to use for the matrix data.
+ public Matrix(Matrix matrix, MemoryPool? allocator)
+ {
+ if (matrix is null)
{
- return (RowCategories.GetSparseIndex(flatIndex / _rowSpan), RowCategories.GetSparseIndex(flatIndex % _rowSpan));
+ ThrowParameterNull(nameof(matrix));
}
+ RowCategories = matrix.RowCategories;
+ ColumnCategories = matrix.ColumnCategories;
+ _rowSpan = matrix._rowSpan;
+ var size = RowCategories.Count * ColumnCategories.Count;
+ _backingMemory = allocator is null ?
+ new float[size].AsMemory() :
+ (_allocator = allocator.Rent(size)).Memory[..size];
+ }
- ///
- /// Get the index in data given the flat row and columns
- ///
- /// The row to lookup
- /// The column to lookup
- /// The index in data for this data.
- [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
- public int GetFlatIndex(int flatRow, int flatColumn)
- {
- return _rowSpan * flatRow + flatColumn;
- }
+ ///
+ /// Get the row and column for a given flat index into the backend data
+ ///
+ /// The flat index in the data to get the sparse row and column for.
+ /// The row and column in sparse space for this flat index.
+ [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
+ public (CategoryIndex Row, CategoryIndex Column) GetSparseIndex(int flatIndex)
+ {
+ return (RowCategories.GetSparseIndex(flatIndex / _rowSpan), RowCategories.GetSparseIndex(flatIndex % _rowSpan));
+ }
- ///
- /// Get the index in the data for the starting point of a given row
- ///
- /// The flat index of the row to get
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
- public int GetFlatRowIndex(int flatRow)
- {
- return _rowSpan * flatRow;
- }
+ ///
+ /// Get the index in data given the flat row and columns
+ ///
+ /// The row to lookup
+ /// The column to lookup
+ /// The index in data for this data.
+ [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
+ public int GetFlatIndex(int flatRow, int flatColumn)
+ {
+ return _rowSpan * flatRow + flatColumn;
+ }
- ///
- /// Get the index int he data for the starting point given a sparse row
- ///
- /// The sparse row index to lookup
- /// The index in data for the start of this row
- [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
- public int GetSparseRowIndex(CategoryIndex sparseRow)
- {
- var index = RowCategories.GetFlatIndex(sparseRow);
- return index >= 0 ? index * _rowSpan : -1;
- }
+ ///
+ /// Get the index in the data for the starting point of a given row
+ ///
+ /// The flat index of the row to get
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
+ public int GetFlatRowIndex(int flatRow)
+ {
+ return _rowSpan * flatRow;
+ }
- ///
- /// Get a reference to a row in the matrix.
- ///
- /// The 0 indexed row number to get access to.
- /// A reference to the row.
- [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
- public Span GetRow(int flatRowIndex)
- {
- if ((flatRowIndex < 0) | (flatRowIndex > RowCategories.Count))
- {
- ThrowOutOfRangeException(nameof(flatRowIndex));
- }
- flatRowIndex = GetFlatRowIndex(flatRowIndex);
- return Data.Slice(flatRowIndex, _rowSpan);
- }
+ ///
+ /// Get the index int he data for the starting point given a sparse row
+ ///
+ /// The sparse row index to lookup
+ /// The index in data for the start of this row
+ [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
+ public int GetSparseRowIndex(CategoryIndex sparseRow)
+ {
+ var index = RowCategories.GetFlatIndex(sparseRow);
+ return index >= 0 ? index * _rowSpan : -1;
+ }
- [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
- public ref float GetFromSparseIndexes(int rowIndex, int columnIndex)
+ ///
+ /// Get a reference to a row in the matrix.
+ ///
+ /// The 0 indexed row number to get access to.
+ /// A reference to the row.
+ [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
+ public Span GetRow(int flatRowIndex)
+ {
+ if ((flatRowIndex < 0) | (flatRowIndex > RowCategories.Count))
{
- var o = RowCategories.GetFlatIndex(rowIndex);
- var d = ColumnCategories.GetFlatIndex(columnIndex);
- if(o < 0)
- {
- InvalidRow(rowIndex);
- }
- if(d < 0)
- {
- InvalidColumns(columnIndex);
- }
- return ref Data[GetFlatIndex(o,d)];
+ ThrowOutOfRangeException(nameof(flatRowIndex));
}
+ flatRowIndex = GetFlatRowIndex(flatRowIndex);
+ return Data.Slice(flatRowIndex, _rowSpan);
+ }
- ///
- /// Create a copy of this matrix.
- ///
- /// Creates a deep copy of the matrix.
- public Matrix Clone()
+ [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
+ public ref float GetFromSparseIndexes(int rowIndex, int columnIndex)
+ {
+ var o = RowCategories.GetFlatIndex(rowIndex);
+ var d = ColumnCategories.GetFlatIndex(columnIndex);
+ if (o < 0)
{
- var ret = new Matrix(this);
- Data.CopyTo(ret.Data);
- return ret;
+ InvalidRow(rowIndex);
}
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private void InvalidColumns(int columnIndex)
+ if (d < 0)
{
- throw new ArgumentOutOfRangeException($"Invalid column index {columnIndex}!");
+ InvalidColumns(columnIndex);
}
+ return ref Data[GetFlatIndex(o, d)];
+ }
- [MethodImpl(MethodImplOptions.NoInlining)]
- private void InvalidRow(int rowIndex)
- {
- throw new ArgumentOutOfRangeException($"Invalid row index {rowIndex}!");
- }
+ ///
+ /// Create a copy of this matrix.
+ ///
+ /// Creates a deep copy of the matrix.
+ public Matrix Clone()
+ {
+ var ret = new Matrix(this);
+ Data.CopyTo(ret.Data);
+ return ret;
+ }
- ~Matrix()
- {
- Dispose();
- }
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private void InvalidColumns(int columnIndex)
+ {
+ throw new ArgumentOutOfRangeException($"Invalid column index {columnIndex}!");
+ }
- public void Dispose()
- {
- _backingMemory = null;
- Thread.MemoryBarrier();
- _allocator?.Dispose();
- _allocator = null;
- }
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private void InvalidRow(int rowIndex)
+ {
+ throw new ArgumentOutOfRangeException($"Invalid row index {rowIndex}!");
+ }
+
+ ~Matrix()
+ {
+ Dispose();
+ }
+
+ public void Dispose()
+ {
+ _backingMemory = null;
+ Thread.MemoryBarrier();
+ _allocator?.Dispose();
+ _allocator = null;
}
}
diff --git a/src/TMG-Framework/Data/Range.cs b/src/TMG-Framework/Data/Range.cs
index a24e783..269180f 100644
--- a/src/TMG-Framework/Data/Range.cs
+++ b/src/TMG-Framework/Data/Range.cs
@@ -16,109 +16,106 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
You should have received a copy of the GNU General Public License
along with XTMF. If not, see .
*/
-using System;
-using System.Collections.Generic;
-namespace TMG
+namespace TMG;
+
+public readonly struct Range
{
- public readonly struct Range
- {
- public readonly int Start;
- public readonly int Stop;
+ public readonly int Start;
+ public readonly int Stop;
- public Range(int start, int stop)
- {
- Start = start;
- Stop = stop;
- }
+ public Range(int start, int stop)
+ {
+ Start = start;
+ Stop = stop;
+ }
- public static bool operator !=(Range first, Range other)
- {
- return (first.Start != other.Start) | (first.Stop != other.Stop);
- }
+ public static bool operator !=(Range first, Range other)
+ {
+ return (first.Start != other.Start) | (first.Stop != other.Stop);
+ }
- public static bool operator ==(Range first, Range other)
- {
- return (first.Start == other.Start) & (first.Stop == other.Stop);
- }
+ public static bool operator ==(Range first, Range other)
+ {
+ return (first.Start == other.Start) & (first.Stop == other.Stop);
+ }
- public override bool Equals(object? obj)
+ public override bool Equals(object? obj)
+ {
+ if (obj is Range other)
{
- if (obj is Range other)
- {
- return this == other;
- }
- return false;
+ return this == other;
}
+ return false;
+ }
- public override int GetHashCode()
- {
- return Start.GetHashCode() * Stop.GetHashCode();
- }
+ public override int GetHashCode()
+ {
+ return Start.GetHashCode() * Stop.GetHashCode();
+ }
- ///
- /// Checks if a given value is inside the range defined by [Start, Stop)
- ///
- /// The int value to check.
- /// True IFF i is greater than or equal to Start and i is less than Stop.
- public bool Contains(int i)
- {
- return (i >= Start) & (i < Stop);
- }
+ ///
+ /// Checks if a given value is inside the range defined by [Start, Stop)
+ ///
+ /// The int value to check.
+ /// True IFF i is greater than or equal to Start and i is less than Stop.
+ public bool Contains(int i)
+ {
+ return (i >= Start) & (i < Stop);
+ }
- ///
- /// Checks if a given value is inside the range defined by (Start, Stop)
- ///
- /// The int value to check
- /// True IFF i is less than Start and i is less than Stop.
- public bool ContainsExcusive(int i)
- {
- return (i > Start) & (i < Stop);
- }
+ ///
+ /// Checks if a given value is inside the range defined by (Start, Stop)
+ ///
+ /// The int value to check
+ /// True IFF i is less than Start and i is less than Stop.
+ public bool ContainsExcusive(int i)
+ {
+ return (i > Start) & (i < Stop);
+ }
- ///
- /// Checks if a given value is inside the range defined by (Start, Stop)
- ///
- /// The value to check for
- /// True if the value is contained within the range
- public bool ContainsExcusive(float valueToFind)
- {
- return (valueToFind > Start) & (valueToFind < Stop);
- }
+ ///
+ /// Checks if a given value is inside the range defined by (Start, Stop)
+ ///
+ /// The value to check for
+ /// True if the value is contained within the range
+ public bool ContainsExcusive(float valueToFind)
+ {
+ return (valueToFind > Start) & (valueToFind < Stop);
+ }
- ///
- /// Checks if a given value is inside the range defined by [Start, Stop]
- ///
- /// The int value to check
- /// True IFF i is greater than or equal to Start and i is less than or equal to Stop.
- public bool ContainsInclusive(int i)
- {
- return (i >= Start) & (i <= Stop);
- }
+ ///
+ /// Checks if a given value is inside the range defined by [Start, Stop]
+ ///
+ /// The int value to check
+ /// True IFF i is greater than or equal to Start and i is less than or equal to Stop.
+ public bool ContainsInclusive(int i)
+ {
+ return (i >= Start) & (i <= Stop);
+ }
- ///
- /// Checks if a given value is inside the range defined by [Start, Stop]
- ///
- /// The value to check for
- /// True if the value is contained within the range
- public bool ContainsInclusive(float valueToFind)
- {
- return (valueToFind >= Start) & (valueToFind <= Stop);
- }
+ ///
+ /// Checks if a given value is inside the range defined by [Start, Stop]
+ ///
+ /// The value to check for
+ /// True if the value is contained within the range
+ public bool ContainsInclusive(float valueToFind)
+ {
+ return (valueToFind >= Start) & (valueToFind <= Stop);
+ }
- ///
- /// Checks if another Range overlaps this one.
- ///
- /// The other range to check against.
- ///
- public bool Overlaps(Range other)
- {
- return ContainsInclusive(other.Start) || ContainsInclusive(other.Stop);
- }
+ ///
+ /// Checks if another Range overlaps this one.
+ ///
+ /// The other range to check against.
+ ///
+ public bool Overlaps(Range other)
+ {
+ return ContainsInclusive(other.Start) || ContainsInclusive(other.Stop);
+ }
- public override string ToString()
- {
- return String.Format("{0}-{1}", Start, Stop);
- }
+ public override string ToString()
+ {
+ return String.Format("{0}-{1}", Start, Stop);
}
-}
\ No newline at end of file
+}
diff --git a/src/TMG-Framework/Data/RangeSet.cs b/src/TMG-Framework/Data/RangeSet.cs
index 1d5aaee..c2f98c0 100644
--- a/src/TMG-Framework/Data/RangeSet.cs
+++ b/src/TMG-Framework/Data/RangeSet.cs
@@ -16,365 +16,360 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
You should have received a copy of the GNU General Public License
along with XTMF. If not, see .
*/
-using System;
-using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
-using System.Text;
using static System.Char;
using static System.String;
using static TMG.Utilities.ExceptionHelper;
-namespace TMG
+namespace TMG;
+
+public sealed class RangeSet : IList
{
- public sealed class RangeSet : IList
+ private readonly Range[] SetRanges;
+
+ public RangeSet(List tempRange)
{
- private readonly Range[] SetRanges;
+ SetRanges = tempRange.ToArray();
+ }
- public RangeSet(List tempRange)
+ ///
+ /// Creates a new RangeSet with inclusive values from the given integer set
+ ///
+ /// The numbers to use to generate the ranges
+ public RangeSet(IList numbers)
+ {
+ if (numbers == null)
{
- SetRanges = tempRange.ToArray();
+ ThrowParameterNull(nameof(numbers));
}
-
- ///
- /// Creates a new RangeSet with inclusive values from the given integer set
- ///
- /// The numbers to use to generate the ranges
- public RangeSet(IList numbers)
+ var array = new int[numbers.Count];
+ numbers.CopyTo(array, 0);
+ Array.Sort(array);
+ var tempRange = new List();
+ var start = 0;
+ for (var i = 1; i < array.Length; i++)
{
- if (numbers == null)
- {
- ThrowParameterNull(nameof(numbers));
- }
- var array = new int[numbers.Count];
- numbers.CopyTo(array, 0);
- Array.Sort(array);
- var tempRange = new List();
- var start = 0;
- for (var i = 1; i < array.Length; i++)
+ if (array[i] > array[i - 1] + 1)
{
- if (array[i] > array[i - 1] + 1)
- {
- tempRange.Add(new Range(array[start], array[i - 1]));
- start = i;
- }
+ tempRange.Add(new Range(array[start], array[i - 1]));
+ start = i;
}
- // and in the end
- tempRange.Add(new Range(array[start], array[array.Length - 1]));
- SetRanges = tempRange.ToArray();
}
+ // and in the end
+ tempRange.Add(new Range(array[start], array[array.Length - 1]));
+ SetRanges = tempRange.ToArray();
+ }
- public int Count => SetRanges.Length;
+ public int Count => SetRanges.Length;
- public bool IsReadOnly => false;
+ public bool IsReadOnly => false;
- public Range this[int index]
- {
- get => SetRanges[index];
- set => SetRanges[index] = value;
- }
+ public Range this[int index]
+ {
+ get => SetRanges[index];
+ set => SetRanges[index] = value;
+ }
- public static bool TryParse(string rangeString, [NotNullWhen(true)] out RangeSet? output)
+ public static bool TryParse(string rangeString, [NotNullWhen(true)] out RangeSet? output)
+ {
+ string? error = null;
+ return TryParse(ref error, rangeString, out output);
+ }
+
+ public static bool TryParse([NotNullWhen(false)] ref string? error,
+ string rangeString,
+ [NotNullWhen(true)] out RangeSet? output)
+ {
+ var tempRange = new List();
+ var length = rangeString.Length;
+ var str = rangeString.ToCharArray();
+ var index = 0;
+ var start = 0;
+ var end = 0;
+ output = null;
+ //Phase == 0 -> index
+ //Phase == 1 -> start
+ //Phase == 2 -> end
+ var phase = 0;
+ var lastPlus = false;
+ var tallyingInZero = false;
+ if (IsNullOrWhiteSpace(rangeString))
{
- string? error = null;
- return TryParse(ref error, rangeString, out output);
+ output = new RangeSet(tempRange);
+ return true;
}
-
- public static bool TryParse([NotNullWhen(false)] ref string? error,
- string rangeString,
- [NotNullWhen(true)] out RangeSet? output)
+ for (var i = 0; i < length; i++)
{
- var tempRange = new List();
- var length = rangeString.Length;
- var str = rangeString.ToCharArray();
- var index = 0;
- var start = 0;
- var end = 0;
- output = null;
- //Phase == 0 -> index
- //Phase == 1 -> start
- //Phase == 2 -> end
- var phase = 0;
- var lastPlus = false;
- var tallyingInZero = false;
- if (IsNullOrWhiteSpace(rangeString))
- {
- output = new RangeSet(tempRange);
- return true;
- }
- for (var i = 0; i < length; i++)
+ var c = str[i];
+ if (IsWhiteSpace(c) || IsLetter(c)) continue;
+ lastPlus = false;
+ switch (phase)
{
- var c = str[i];
- if (IsWhiteSpace(c) || IsLetter(c)) continue;
- lastPlus = false;
- switch (phase)
- {
- case 0:
- if (IsNumber(c))
+ case 0:
+ if (IsNumber(c))
+ {
+ index = ((index << 3) + (index << 1)) + (c - '0');
+ tallyingInZero = true;
+ }
+ else switch (c)
{
- index = ((index << 3) + (index << 1)) + (c - '0');
- tallyingInZero = true;
- }
- else switch (c)
- {
- case ',':
- tempRange.Add(new Range(index, index));
- index = 0;
- start = 0;
- end = 0;
- break;
- case '-':
- if (!tallyingInZero)
- {
- error = "No number was inserted before a range!";
- return false;
- }
- start = index;
- end = 0;
- phase = 2;
- break;
- case '+':
- if (!tallyingInZero)
- {
- error = "No number was inserted before a range!";
- return false;
- }
- end = int.MaxValue;
- tempRange.Add(new Range(start, end));
- index = 0;
- start = 0;
- phase = 0;
- tallyingInZero = false;
- lastPlus = true;
- break;
- default:
- error = "Unrecognized symbol " + c;
+ case ',':
+ tempRange.Add(new Range(index, index));
+ index = 0;
+ start = 0;
+ end = 0;
+ break;
+ case '-':
+ if (!tallyingInZero)
+ {
+ error = "No number was inserted before a range!";
return false;
- }
- break;
- case 1:
- if (IsNumber(c))
- {
- start = ((start << 3) + (start << 1)) + (c - '0');
- }
- else switch (c)
- {
- case '+':
- end = int.MaxValue;
- tempRange.Add(new Range(start, end));
- index = 0;
- start = 0;
- phase = 0;
- tallyingInZero = false;
- lastPlus = true;
- break;
- case '-':
- end = 0;
- phase = 2;
- break;
- }
- break;
- case 2:
- if (IsNumber(c))
- {
- end = ((end << 3) + (end << 1)) + (c - '0');
+ }
+ start = index;
+ end = 0;
+ phase = 2;
+ break;
+ case '+':
+ if (!tallyingInZero)
+ {
+ error = "No number was inserted before a range!";
+ return false;
+ }
+ end = int.MaxValue;
+ tempRange.Add(new Range(start, end));
+ index = 0;
+ start = 0;
+ phase = 0;
+ tallyingInZero = false;
+ lastPlus = true;
+ break;
+ default:
+ error = "Unrecognized symbol " + c;
+ return false;
}
- else if (c == ',')
+ break;
+ case 1:
+ if (IsNumber(c))
+ {
+ start = ((start << 3) + (start << 1)) + (c - '0');
+ }
+ else switch (c)
{
- tempRange.Add(new Range(start, end));
- index = 0;
- phase = 0;
- start = 0;
- end = 0;
- tallyingInZero = false;
+ case '+':
+ end = int.MaxValue;
+ tempRange.Add(new Range(start, end));
+ index = 0;
+ start = 0;
+ phase = 0;
+ tallyingInZero = false;
+ lastPlus = true;
+ break;
+ case '-':
+ end = 0;
+ phase = 2;
+ break;
}
- break;
- }
- }
- if (phase == 2)
- {
- tempRange.Add(new Range(start, end));
- }
- else if (phase == 0 && tallyingInZero)
- {
- tempRange.Add(new Range(index, index));
- }
- else if (!lastPlus)
- {
- error = "Ended while reading a " + (phase == 0 ? "range's index!" : "range's start value!");
- return false;
+ break;
+ case 2:
+ if (IsNumber(c))
+ {
+ end = ((end << 3) + (end << 1)) + (c - '0');
+ }
+ else if (c == ',')
+ {
+ tempRange.Add(new Range(start, end));
+ index = 0;
+ phase = 0;
+ start = 0;
+ end = 0;
+ tallyingInZero = false;
+ }
+ break;
}
- output = new RangeSet(tempRange);
- return true;
}
+ if (phase == 2)
+ {
+ tempRange.Add(new Range(start, end));
+ }
+ else if (phase == 0 && tallyingInZero)
+ {
+ tempRange.Add(new Range(index, index));
+ }
+ else if (!lastPlus)
+ {
+ error = "Ended while reading a " + (phase == 0 ? "range's index!" : "range's start value!");
+ return false;
+ }
+ output = new RangeSet(tempRange);
+ return true;
+ }
- public void Add(Range item) => throw new InvalidOperationException("Unable to add items");
+ public void Add(Range item) => throw new InvalidOperationException("Unable to add items");
- public void Clear() => throw new InvalidOperationException("Unable to remove items");
+ public void Clear() => throw new InvalidOperationException("Unable to remove items");
- public bool Contains(Range item) => IndexOf(item) != -1;
+ public bool Contains(Range item) => IndexOf(item) != -1;
- public bool Contains(float value) => IndexOf(value) != -1;
+ public bool Contains(float value) => IndexOf(value) != -1;
- public bool Contains(int number)
+ public bool Contains(int number)
+ {
+ for (var i = 0; i < SetRanges.Length; i++)
{
- for (var i = 0; i < SetRanges.Length; i++)
+ if ((number >= SetRanges[i].Start) && (number <= SetRanges[i].Stop))
{
- if ((number >= SetRanges[i].Start) && (number <= SetRanges[i].Stop))
- {
- return true;
- }
+ return true;
}
- return false;
}
+ return false;
+ }
- public void CopyTo(Range[] array, int arrayIndex)
+ public void CopyTo(Range[] array, int arrayIndex)
+ {
+ for (var i = 0; i < SetRanges.Length; i++)
{
- for (var i = 0; i < SetRanges.Length; i++)
- {
- array[arrayIndex + i] = SetRanges[i];
- }
+ array[arrayIndex + i] = SetRanges[i];
}
+ }
- public override bool Equals(object? obj)
+ public override bool Equals(object? obj)
+ {
+ var other = obj as RangeSet;
+ if (other?.Count != Count) return false;
+ for (var i = 0; i < SetRanges.Length; i++)
{
- var other = obj as RangeSet;
- if (other?.Count != Count) return false;
- for (var i = 0; i < SetRanges.Length; i++)
+ if (!(SetRanges[i] == other[i]))
{
- if (!(SetRanges[i] == other[i]))
- {
- return false;
- }
+ return false;
}
- return true;
}
+ return true;
+ }
- public IEnumerator GetEnumerator() => ((ICollection)SetRanges).GetEnumerator();
+ public IEnumerator GetEnumerator() => ((ICollection)SetRanges).GetEnumerator();
- public override int GetHashCode()
+ public override int GetHashCode()
+ {
+ var hash = 0;
+ for (var i = 0; i < SetRanges.Length; i++)
{
- var hash = 0;
- for (var i = 0; i < SetRanges.Length; i++)
- {
- hash += SetRanges.GetHashCode();
- }
- return hash;
+ hash += SetRanges.GetHashCode();
}
+ return hash;
+ }
- public int IndexOf(Range item)
+ public int IndexOf(Range item)
+ {
+ for (var i = 0; i < SetRanges.Length; i++)
{
- for (var i = 0; i < SetRanges.Length; i++)
+ if (SetRanges[i] == item)
{
- if (SetRanges[i] == item)
- {
- return i;
- }
+ return i;
}
- return -1;
}
+ return -1;
+ }
- ///
- /// Gives the index in the range set where this integer is first contained.
- ///
- /// The integer to find
- /// -1 if not found, otherwise the index of the Range in the rangeset that first contains this integer
- public int IndexOf(int integerToFind)
+ ///
+ /// Gives the index in the range set where this integer is first contained.
+ ///
+ /// The integer to find
+ /// -1 if not found, otherwise the index of the Range in the rangeset that first contains this integer
+ public int IndexOf(int integerToFind)
+ {
+ for (var i = 0; i < SetRanges.Length; i++)
{
- for (var i = 0; i < SetRanges.Length; i++)
+ if (SetRanges[i].ContainsInclusive(integerToFind))
{
- if (SetRanges[i].ContainsInclusive(integerToFind))
- {
- return i;
- }
+ return i;
}
- return -1;
}
+ return -1;
+ }
- ///
- /// Gives the index in the range set where this integer is first contained.
- ///
- /// The floating point value to find.
- /// The index of the range that contains the value, -1 otherwise.
- public int IndexOf(float valueToFind)
+ ///
+ /// Gives the index in the range set where this integer is first contained.
+ ///
+ /// The floating point value to find.
+ /// The index of the range that contains the value, -1 otherwise.
+ public int IndexOf(float valueToFind)
+ {
+ for (var i = 0; i < SetRanges.Length; i++)
{
- for (var i = 0; i < SetRanges.Length; i++)
+ if (SetRanges[i].ContainsInclusive(valueToFind))
{
- if (SetRanges[i].ContainsInclusive(valueToFind))
- {
- return i;
- }
+ return i;
}
- return -1;
}
+ return -1;
+ }
- public void Insert(int index, Range item)
- {
- this[index] = item;
- }
+ public void Insert(int index, Range item)
+ {
+ this[index] = item;
+ }
- public bool Overlaps(Range other)
+ public bool Overlaps(Range other)
+ {
+ for (var i = 0; i < SetRanges.Length; i++)
{
- for (var i = 0; i < SetRanges.Length; i++)
+ if (SetRanges[i].Contains(other.Start) || SetRanges[i].Contains(other.Stop))
{
- if (SetRanges[i].Contains(other.Start) || SetRanges[i].Contains(other.Stop))
- {
- return true;
- }
+ return true;
}
- return false;
}
+ return false;
+ }
- public bool Overlaps(RangeSet other)
+ public bool Overlaps(RangeSet other)
+ {
+ for (var i = 0; i < SetRanges.Length; i++)
{
- for (var i = 0; i < SetRanges.Length; i++)
+ for (var j = 0; j < other.SetRanges.Length; j++)
{
- for (var j = 0; j < other.SetRanges.Length; j++)
+ if (SetRanges[i].Contains(other.SetRanges[j].Start) || SetRanges[i].Contains(other.SetRanges[j].Stop))
{
- if (SetRanges[i].Contains(other.SetRanges[j].Start) || SetRanges[i].Contains(other.SetRanges[j].Stop))
- {
- return true;
- }
+ return true;
}
}
- return false;
}
+ return false;
+ }
- public bool Remove(Range item) => throw new InvalidOperationException("Unable to remove items");
+ public bool Remove(Range item) => throw new InvalidOperationException("Unable to remove items");
- public void RemoveAt(int index) => throw new InvalidOperationException("Unable to remove items");
+ public void RemoveAt(int index) => throw new InvalidOperationException("Unable to remove items");
- System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => SetRanges.GetEnumerator();
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => SetRanges.GetEnumerator();
- public override string ToString()
+ public override string ToString()
+ {
+ var builder = new StringBuilder();
+ var first = true;
+ if (SetRanges.Length == 0)
{
- var builder = new StringBuilder();
- var first = true;
- if (SetRanges.Length == 0)
- {
- // do nothing we already have a blank builder
- }
- else
+ // do nothing we already have a blank builder
+ }
+ else
+ {
+ foreach (var res in SetRanges)
{
- foreach (var res in SetRanges)
+ if (!first)
{
- if (!first)
- {
- builder.Append(',');
- }
- if (res.Start != res.Stop)
- {
- builder.Append(res.Start);
- builder.Append('-');
- builder.Append(res.Stop);
- }
- else
- {
- builder.Append(res.Start);
- }
- first = false;
+ builder.Append(',');
+ }
+ if (res.Start != res.Stop)
+ {
+ builder.Append(res.Start);
+ builder.Append('-');
+ builder.Append(res.Stop);
+ }
+ else
+ {
+ builder.Append(res.Start);
}
+ first = false;
}
- return builder.ToString();
}
+ return builder.ToString();
}
-}
\ No newline at end of file
+}
diff --git a/src/TMG-Framework/Data/RangeSetSet.cs b/src/TMG-Framework/Data/RangeSetSet.cs
index c99094a..336b556 100644
--- a/src/TMG-Framework/Data/RangeSetSet.cs
+++ b/src/TMG-Framework/Data/RangeSetSet.cs
@@ -16,227 +16,222 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
You should have received a copy of the GNU General Public License
along with XTMF. If not, see .
*/
-using System;
-using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
-using System.Text;
using static TMG.Utilities.ExceptionHelper;
-namespace TMG
+namespace TMG;
+
+public sealed class RangeSetSet : IList
{
- public sealed class RangeSetSet : IList
+ private readonly RangeSet[] RangeSets;
+
+ public RangeSetSet(List tempRange)
{
- private readonly RangeSet[] RangeSets;
+ RangeSets = tempRange.ToArray();
+ }
- public RangeSetSet(List tempRange)
- {
- RangeSets = tempRange.ToArray();
- }
+ public int Count => RangeSets.Length;
- public int Count => RangeSets.Length;
+ public bool IsReadOnly => false;
- public bool IsReadOnly => false;
+ public RangeSet this[int index]
+ {
+ get => RangeSets[index];
+ set => RangeSets[index] = value;
+ }
- public RangeSet this[int index]
- {
- get => RangeSets[index];
- set => RangeSets[index] = value;
- }
+ public static bool TryParse(string rangeString, [NotNullWhen(true)] out RangeSetSet? output)
+ {
+ string? error = null;
+ return TryParse(ref error, rangeString, out output);
+ }
- public static bool TryParse(string rangeString, [NotNullWhen(true)] out RangeSetSet? output)
+ public static bool TryParse([NotNullWhen(false)] ref string? error,
+ string rangeString,
+ [NotNullWhen(true)] out RangeSetSet? output)
+ {
+ if (rangeString == null)
{
- string? error = null;
- return TryParse(ref error, rangeString, out output);
+ ThrowParameterNull(nameof(rangeString));
}
- public static bool TryParse([NotNullWhen(false)] ref string? error,
- string rangeString,
- [NotNullWhen(true)] out RangeSetSet? output)
+ var rangeSets = new List();
+ output = null;
+ var strLength = rangeString.Length;
+ int startPos;
+ for (startPos = 0; startPos < strLength; startPos++)
{
- if (rangeString == null)
- {
- ThrowParameterNull(nameof(rangeString));
- }
-
- var rangeSets = new List();
- output = null;
- var strLength = rangeString.Length;
- int startPos;
- for (startPos = 0; startPos < strLength; startPos++)
+ if (rangeString[startPos] == '{')
{
- if (rangeString[startPos] == '{')
+ var success = false;
+ for (var endPos = startPos + 1; endPos < strLength; endPos++)
{
- var success = false;
- for (var endPos = startPos + 1; endPos < strLength; endPos++)
+ if (rangeString[endPos] == '}')
{
- if (rangeString[endPos] == '}')
+ if (!RangeSet.TryParse(ref error, rangeString.Substring(startPos + 1, endPos - startPos - 1), out RangeSet? temp))
{
- if (!RangeSet.TryParse(ref error, rangeString.Substring(startPos + 1, endPos - startPos - 1), out RangeSet? temp))
- {
- return false;
- }
- rangeSets.Add(temp);
- startPos = endPos; // the increment will make sure we don't re explore this
- success = true;
- break;
+ return false;
}
- }
- if (!success)
- {
- error = "There was an unmatched '{' at position " + startPos;
- return false;
+ rangeSets.Add(temp);
+ startPos = endPos; // the increment will make sure we don't re explore this
+ success = true;
+ break;
}
}
- }
- // in case it is a set of 1 element
- if (rangeSets.Count == 0)
- {
- if (!RangeSet.TryParse(ref error, rangeString, out RangeSet? temp))
+ if (!success)
{
+ error = "There was an unmatched '{' at position " + startPos;
return false;
}
- rangeSets.Add(temp);
}
- output = new RangeSetSet(rangeSets);
- return true;
}
+ // in case it is a set of 1 element
+ if (rangeSets.Count == 0)
+ {
+ if (!RangeSet.TryParse(ref error, rangeString, out RangeSet? temp))
+ {
+ return false;
+ }
+ rangeSets.Add(temp);
+ }
+ output = new RangeSetSet(rangeSets);
+ return true;
+ }
- ///
- /// Not Supported
- ///
- ///
- public void Add(RangeSet item) => throw new NotSupportedException();
+ ///
+ /// Not Supported
+ ///
+ ///
+ public void Add(RangeSet item) => throw new NotSupportedException();
- ///
- /// Not Supported
- ///
- public void Clear() => throw new NotSupportedException();
+ ///
+ /// Not Supported
+ ///
+ public void Clear() => throw new NotSupportedException();
- public bool Contains(RangeSet item) => IndexOf(item) != -1;
+ public bool Contains(RangeSet item) => IndexOf(item) != -1;
- public void CopyTo(RangeSet[] array, int arrayIndex)
+ public void CopyTo(RangeSet[] array, int arrayIndex)
+ {
+ var localRangeSets = RangeSets;
+ if (localRangeSets.Length + arrayIndex >= array.Length)
{
- var localRangeSets = RangeSets;
- if (localRangeSets.Length + arrayIndex >= array.Length)
- {
- throw new ArgumentException("The given array is not long enough to support copying starting at index " + arrayIndex);
- }
- if (arrayIndex < 0)
- {
- throw new ArgumentOutOfRangeException("arrayIndex", "This argument must be greater than or equal to zero!");
- }
- for (var i = 0; i < localRangeSets.Length; i++)
- {
- array[i + arrayIndex] = localRangeSets[i];
- }
+ throw new ArgumentException("The given array is not long enough to support copying starting at index " + arrayIndex);
+ }
+ if (arrayIndex < 0)
+ {
+ throw new ArgumentOutOfRangeException("arrayIndex", "This argument must be greater than or equal to zero!");
+ }
+ for (var i = 0; i < localRangeSets.Length; i++)
+ {
+ array[i + arrayIndex] = localRangeSets[i];
}
+ }
- public override bool Equals(object? obj)
+ public override bool Equals(object? obj)
+ {
+ var other = obj as RangeSetSet;
+ if (Count != other?.Count) return false;
+ for (var i = 0; i < RangeSets.Length; i++)
{
- var other = obj as RangeSetSet;
- if (Count != other?.Count) return false;
- for (var i = 0; i < RangeSets.Length; i++)
+ if (!RangeSets[i].Equals(other.RangeSets[i]))
{
- if (!RangeSets[i].Equals(other.RangeSets[i]))
- {
- return false;
- }
+ return false;
}
- return true;
}
+ return true;
+ }
- public IEnumerator GetEnumerator() => ((ICollection)RangeSets).GetEnumerator();
+ public IEnumerator GetEnumerator() => ((ICollection)RangeSets).GetEnumerator();
- public override int GetHashCode()
+ public override int GetHashCode()
+ {
+ var hash = 0;
+ for (var i = 0; i < RangeSets.Length; i++)
{
- var hash = 0;
- for (var i = 0; i < RangeSets.Length; i++)
- {
- hash += RangeSets[i].GetHashCode();
- }
- return hash;
+ hash += RangeSets[i].GetHashCode();
}
+ return hash;
+ }
- public int IndexOf(RangeSet item)
+ public int IndexOf(RangeSet item)
+ {
+ if (item == null)
{
- if (item == null)
- {
- ThrowParameterNull(nameof(item));
- }
- for (var i = 0; i < RangeSets.Length; i++)
+ ThrowParameterNull(nameof(item));
+ }
+ for (var i = 0; i < RangeSets.Length; i++)
+ {
+ if (item.Equals(RangeSets[i]))
{
- if (item.Equals(RangeSets[i]))
- {
- return i;
- }
+ return i;
}
- return -1;
}
+ return -1;
+ }
- public int IndexOf(int numberToFind)
+ public int IndexOf(int numberToFind)
+ {
+ for (var i = 0; i < RangeSets.Length; i++)
{
- for (var i = 0; i < RangeSets.Length; i++)
+ if (RangeSets[i].Contains(numberToFind))
{
- if (RangeSets[i].Contains(numberToFind))
- {
- return i;
- }
+ return i;
}
- return -1;
}
+ return -1;
+ }
- ///
- /// Returns the first set that contains a range that contains the value.
- ///
- /// The value to seek
- /// The index of the set that first contains the value, -1 otherwise.
- public int IndexOf(float value)
+ ///
+ /// Returns the first set that contains a range that contains the value.
+ ///
+ /// The value to seek
+ /// The index of the set that first contains the value, -1 otherwise.
+ public int IndexOf(float value)
+ {
+ for (var i = 0; i < RangeSets.Length; i++)
{
- for (var i = 0; i < RangeSets.Length; i++)
+ if (RangeSets[i].Contains(value))
{
- if (RangeSets[i].Contains(value))
- {
- return i;
- }
+ return i;
}
- return -1;
}
+ return -1;
+ }
- ///
- /// Not Supported
- ///
- ///
- ///
- public void Insert(int index, RangeSet item) => throw new NotSupportedException();
+ ///
+ /// Not Supported
+ ///
+ ///
+ ///
+ public void Insert(int index, RangeSet item) => throw new NotSupportedException();
- public bool Remove(RangeSet item) => throw new NotSupportedException();
+ public bool Remove(RangeSet item) => throw new NotSupportedException();
- ///
- /// Not Supported
- ///
- public void RemoveAt(int index) => throw new NotSupportedException();
+ ///
+ /// Not Supported
+ ///
+ public void RemoveAt(int index) => throw new NotSupportedException();
- System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
- {
- return RangeSets.GetEnumerator();
- }
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+ {
+ return RangeSets.GetEnumerator();
+ }
- public override string ToString()
+ public override string ToString()
+ {
+ var builder = new StringBuilder();
+ var first = true;
+ for (var i = 0; i < RangeSets.Length; i++)
{
- var builder = new StringBuilder();
- var first = true;
- for (var i = 0; i < RangeSets.Length; i++)
+ if (!first)
{
- if (!first)
- {
- builder.Append(',');
- }
- first = false;
- builder.Append('{');
- builder.Append(RangeSets[i]);
- builder.Append('}');
+ builder.Append(',');
}
- return builder.ToString();
+ first = false;
+ builder.Append('{');
+ builder.Append(RangeSets[i]);
+ builder.Append('}');
}
+ return builder.ToString();
}
-}
\ No newline at end of file
+}
diff --git a/src/TMG-Framework/Data/Time.cs b/src/TMG-Framework/Data/Time.cs
index 1fe76a6..ef7a94f 100644
--- a/src/TMG-Framework/Data/Time.cs
+++ b/src/TMG-Framework/Data/Time.cs
@@ -16,524 +16,494 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
You should have received a copy of the GNU General Public License
along with XTMF. If not, see .
*/
-using System;
-using System.Diagnostics.CodeAnalysis;
-using System.Runtime.CompilerServices;
-using XTMF2;
-namespace TMG
+
+namespace TMG;
+
+///
+/// Simple Time Struct for holding simple time data.
+///
+public struct Time : IComparable
{
///
- /// Simple Time Struct for holding simple time data.
+ /// Our internal representation, to the millisecond
///
- public struct Time : IComparable
- {
- public static Time EndOfDay = new Time() { Hours = 28 };
+ private long _internalTime;
- public static Time OneQuantum;
-
- public static Time StartOfDay = new Time() { Hours = 4 };
+ ///
+ /// Converts the given float time in format HH.MM to
+ /// this class representation
+ ///
+ ///
+ public Time(float time)
+ {
+ var hours = (long)time;
+ var minutes = (long)(Math.Round((time - (long)time) * 100));
+ _internalTime = (hours * 3600000L + minutes * 60000L);
+ }
- ///
- /// Our internal representation, to the millisecond
- ///
- private long _internalTime;
+ public Time(DateTime time)
+ {
+ var hours = time.Hour;
+ var minutes = time.Minute;
+ var seconds = time.Second;
+ var milliseconds = time.Millisecond;
+ var hourToMilliseconds = hours * 3600000L;
+ var minuteToMilliseconds = minutes * 60000L;
+ var secondToMilliseconds = seconds * 1000L;
+ _internalTime = (hourToMilliseconds + minuteToMilliseconds) + (secondToMilliseconds + milliseconds);
+ }
- ///
- /// Converts the given float time in format HH.MM to
- /// this class representation
- ///
- ///
- public Time(float time)
+ ///
+ /// Creates a TashaTime given the string representation
+ /// Example 4:25:00 4 hours 25 minutes and 0 seconds
+ ///
+ ///
+ public Time(string time)
+ {
+ if (!TryParse(time, out this))
{
- var hours = (long)time;
- var minutes = (long)(Math.Round((time - (long)time) * 100));
- _internalTime = (hours * 3600000L + minutes * 60000L);
+ throw new XTMFRuntimeException(null, "Unable to create a XTMF.Time from " + time);
}
+ }
- public Time(DateTime time)
- {
- _internalTime = ((60 * (60 * time.Hour) + time.Minute) + time.Second) * 1000 + time.Millisecond;
- }
+ public static Time OneHour { get; } = new Time() { Hours = 1 };
- ///
- /// Creates a TashaTime given the string representation
- /// Example 4:25:00 4 hours 25 minutes and 0 seconds
- ///
- ///
- public Time(string time)
- {
- if (!TryParse(time, out this))
- {
- throw new XTMFRuntimeException(null, "Unable to create a XTMF.Time from " + time);
- }
- }
+ public static Time Zero { get; } = new Time();
- public static Time OneHour { get; } = new Time() { Hours = 1 };
+ ///
+ /// The number of Hours this Time Object represents
+ ///
+ public int Hours
+ {
+ get => (int)(_internalTime / 3600000L);
+ set => _internalTime = (_internalTime % 3600000L + (value * 3600000L));
+ }
- public static Time Zero { get; } = new Time();
+ ///
+ ///
+ ///
+ public int Minutes
+ {
+ get => (int)((_internalTime / 60000L) % 60L);
+ set => _internalTime = _internalTime - ((_internalTime / 60000L) % 60L) + (value * 60000L);
+ }
- ///
- /// The number of Hours this Time Object represents
- ///
- public int Hours
+ ///
+ /// The number of seconds this Time Object Represents
+ ///
+ public int Seconds
+ {
+ get => (int)((_internalTime / 1000L) % 60L);
+ set
{
- get => (int)(_internalTime / 3600000L);
- set => _internalTime = (_internalTime % 3600000L + (value * 3600000L));
+ var temp = _internalTime / 1000L;
+ _internalTime = ((temp - temp % 60L) + value) * 1000L;
}
+ }
- ///
- ///
- ///
- public int Minutes
- {
- get => (int)((_internalTime / 60000L) % 60L);
- set => _internalTime = _internalTime - ((_internalTime / 60000L) % 60L) + (value * 60000L);
- }
+ public static Time FromMinutes(float result) => new Time() { _internalTime = (long)(result * 60000.0f) };
- ///
- /// The number of seconds this Time Object Represents
- ///
- public int Seconds
- {
- get => (int)((_internalTime / 1000L) % 60L);
- set
- {
- var temp = _internalTime / 1000L;
- _internalTime = ((temp - temp % 60L) + value) * 1000L;
- }
- }
+ public static implicit operator DateTime(Time t) => new DateTime(0, 0, 0, t.Hours, t.Minutes, t.Seconds, 0);
- public static Time FromMinutes(float result) => new Time() { _internalTime = (long)(result * 60000.0f) };
+ public static implicit operator Time(DateTime t) => new Time(t);
- public static implicit operator DateTime(Time t) => new DateTime(0, 0, 0, t.Hours, t.Minutes, t.Seconds, 0);
+ public static bool Intersection(Time start1, Time end1, Time start2, Time end2) => !((end1._internalTime < start2._internalTime)
+ | (end2._internalTime < start1._internalTime));
- public static implicit operator Time(DateTime t) => new Time(t);
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool Intersection(Time start1, Time end1, Time start2, Time end2, out Time intersection)
+ {
+ var intersectionStart = Math.Max(start1._internalTime, start2._internalTime);
+ var intersectionEnd = Math.Min(end1._internalTime, end2._internalTime);
+ var intersectionDuration = intersectionEnd - intersectionStart;
+ var mask = ~(intersectionDuration >> 63);
- public static bool Intersection(Time start1, Time end1, Time start2, Time end2) => !((end1._internalTime < start2._internalTime)
- | (end2._internalTime < start1._internalTime));
+ intersection._internalTime = intersectionDuration & mask;
+ return mask != 0L;
+ }
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool Intersection(Time start1, Time end1, Time start2, Time end2, out Time intersection)
- {
- if ((end1._internalTime < start2._internalTime)
- | (end2._internalTime < start1._internalTime))
- {
- intersection = new Time();
- return false;
- }
- // passenger is first
- if (start1._internalTime <= start2._internalTime)
- {
- intersection._internalTime =
- (end1._internalTime >= end2._internalTime) ? end2._internalTime - start2._internalTime : end1._internalTime - start2._internalTime;
- return true;
- }
- else
- {
- // passenger is second
- intersection._internalTime =
- (end1._internalTime >= end2._internalTime) ? end2._internalTime - start1._internalTime : end1._internalTime - start1._internalTime;
- return true;
- }
- }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool Intersection(Time start1, Time end1, Time start2, Time end2, out Time intersectionStart, out Time intersectionEnd)
+ {
+ var start = Math.Max(start1._internalTime, start2._internalTime);
+ var end = Math.Min(end1._internalTime, end2._internalTime);
+ var mask = ~((end - start) >> 63);
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool Intersection(Time start1, Time end1, Time start2, Time end2, out Time intersectionStart, out Time intersectionEnd)
- {
- if (end1._internalTime < start2._internalTime
- || end2._internalTime < start1._internalTime)
- {
- intersectionStart = new Time();
- intersectionEnd = new Time();
- return false;
- }
- // passenger is first
- if (start1._internalTime <= start2._internalTime)
- {
- intersectionStart._internalTime = start2._internalTime;
- intersectionEnd._internalTime = (end1._internalTime >= end2._internalTime) ? end2._internalTime : end1._internalTime;
- return true;
- }
- else
- {
- // passenger is second
- intersectionStart._internalTime = start1._internalTime;
- intersectionEnd._internalTime = (end1._internalTime >= end2._internalTime) ? end2._internalTime : end1._internalTime;
- return true;
- }
- }
+ intersectionStart._internalTime = start & mask;
+ intersectionEnd._internalTime = end & mask;
+ return mask != 0L;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static Time operator -(Time t1, Time t2) => new Time() { _internalTime = t1._internalTime - t2._internalTime };
+
+ public static Time operator -(Time t1) => new Time() { _internalTime = -t1._internalTime };
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static bool operator !=(Time t1, Time t2) => t1._internalTime != t2._internalTime;
- ///
- ///
- ///
- ///
- ///
- ///
- public static Time operator -(Time t1, Time t2) => new Time() { _internalTime = t1._internalTime - t2._internalTime };
-
- public static Time operator -(Time t1) => new Time() { _internalTime = -t1._internalTime };
-
- ///
- ///
- ///
- ///
- ///
- ///
- public static bool operator !=(Time t1, Time t2) => t1._internalTime != t2._internalTime;
-
- ///
- ///
- ///
- ///
- ///
- ///
- public static Time operator *(float percent, Time time) => new Time() { _internalTime = (long)(Math.Round(percent * time._internalTime)) };
-
- ///
- ///
- ///
- ///
- ///
- ///
- public static float operator /(Time t1, Time t2)
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static Time operator *(float percent, Time time) => new Time() { _internalTime = (long)(Math.Round(percent * time._internalTime)) };
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static float operator /(Time t1, Time t2)
+ {
+ if (t2 == Zero)
{
- if (t2 == Zero)
- {
- throw new DivideByZeroException();
- }
- return (float)t1._internalTime / t2._internalTime;
+ throw new DivideByZeroException();
}
+ return (float)t1._internalTime / t2._internalTime;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Time operator +(Time t1, Time t2) => new Time() { _internalTime = t1._internalTime + t2._internalTime };
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool operator <(Time t1, Time t2) => t1._internalTime < t2._internalTime;
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool operator <=(Time t1, Time t2) => t1._internalTime <= t2._internalTime;
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool operator ==(Time t1, Time t2) => t1._internalTime == t2._internalTime;
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool operator >(Time t1, Time t2) => t1._internalTime > t2._internalTime;
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool operator >=(Time t1, Time t2) => t1._internalTime >= t2._internalTime;
+
+ public static bool TryParse(string timeString, out Time time)
+ {
+ string? error = null;
+ return TryParse(ref error, timeString, out time);
+ }
- ///
- ///
- ///
- ///
- ///
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Time operator +(Time t1, Time t2) => new Time() { _internalTime = t1._internalTime + t2._internalTime };
-
- ///
- ///
- ///
- ///
- ///
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool operator <(Time t1, Time t2) => t1._internalTime < t2._internalTime;
-
- ///
- ///
- ///
- ///
- ///
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool operator <=(Time t1, Time t2) => t1._internalTime <= t2._internalTime;
-
- ///
- ///
- ///
- ///
- ///
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool operator ==(Time t1, Time t2) => t1._internalTime == t2._internalTime;
-
- ///
- ///
- ///
- ///
- ///
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool operator >(Time t1, Time t2) => t1._internalTime > t2._internalTime;
-
- ///
- ///
- ///
- ///
- ///
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool operator >=(Time t1, Time t2) => t1._internalTime >= t2._internalTime;
-
- public static bool TryParse(string timeString, out Time time)
+ public static bool TryParse(
+ [NotNullWhen(false)] ref string? error, string timeString, out Time time)
+ {
+ time = new Time();
+ if (String.IsNullOrWhiteSpace(timeString))
{
- string? error = null;
- return TryParse(ref error, timeString, out time);
+ error = "Time string is null or whitespace!";
+ return false;
}
-
- public static bool TryParse(
- [NotNullWhen(false)]ref string? error, string timeString, out Time time)
+ int seconds = 0, minutes = 0, hours = 0;
+ int state = 0;
+ int currentTime = 0;
+ int currentNumber = 0;
+ for (int i = 0; i < timeString.Length; ++i)
{
- time = new Time();
- if (String.IsNullOrWhiteSpace(timeString))
+ char c = timeString[i];
+ if (Char.IsWhiteSpace(c))
{
- error = "Time string is null or whitespace!";
- return false;
+ continue;
}
- int seconds = 0, minutes = 0, hours = 0;
- int state = 0;
- int currentTime = 0;
- int currentNumber = 0;
- for (int i = 0; i < timeString.Length; ++i)
+ switch (state)
{
- char c = timeString[i];
- if (Char.IsWhiteSpace(c))
- {
- continue;
- }
- switch (state)
- {
- // Initial State
- case 0:
+ // Initial State
+ case 0:
+ {
+ if ((c >= '0') & (c <= '9'))
{
- if ((c >= '0') & (c <= '9'))
- {
- currentNumber *= 10;
- currentNumber += (c - '0');
- state = 1;
- continue;
- }
- else
+ currentNumber *= 10;
+ currentNumber += (c - '0');
+ state = 1;
+ continue;
+ }
+ else
+ {
+ error = "Expected a number but found '" + c + "' instead!";
+ }
+ }
+ return false;
+ // Collect number
+ case 1:
+ {
+ if ((c >= '0') & (c <= '9'))
+ {
+ currentNumber *= 10;
+ currentNumber += (c - '0');
+ }
+ else if (c == ':')
+ {
+ switch (currentTime)
{
- error = "Expected a number but found '" + c + "' instead!";
+ case 0:
+ hours = currentNumber;
+ break;
+
+ case 1:
+ minutes = currentNumber;
+ break;
+
+ case 2:
+ seconds = currentNumber;
+ break;
+
+ default:
+ error = "Invalid Time level!";
+ return false;
}
+ currentNumber = 0;
+ currentTime++;
+ state = 0;
}
- return false;
- // Collect number
- case 1:
+ else if ((c == 'h') | (c == 'H'))
{
- if ((c >= '0') & (c <= '9'))
+ if (currentTime <= 0)
{
- currentNumber *= 10;
- currentNumber += (c - '0');
+ hours = currentNumber;
+ currentTime = 1;
+ currentNumber = 0;
+ state = 2;
}
- else if (c == ':')
+ else
{
- switch (currentTime)
- {
- case 0:
- hours = currentNumber;
- break;
-
- case 1:
- minutes = currentNumber;
- break;
-
- case 2:
- seconds = currentNumber;
- break;
-
- default:
- error = "Invalid Time level!";
- return false;
- }
- currentNumber = 0;
- currentTime++;
- state = 0;
+ error = "Invalid place to enter hours!";
+ return false;
}
- else if ((c == 'h') | (c == 'H'))
+ }
+ else if ((c == 'm') | (c == 'M'))
+ {
+ if (currentTime <= 1)
{
- if (currentTime <= 0)
- {
- hours = currentNumber;
- currentTime = 1;
- currentNumber = 0;
- state = 2;
- }
- else
- {
- error = "Invalid place to enter hours!";
- return false;
- }
+ minutes = currentNumber;
+ currentTime = 2;
+ currentNumber = 0;
+ state = 2;
}
- else if ((c == 'm') | (c == 'M'))
+ else
{
- if (currentTime <= 1)
- {
- minutes = currentNumber;
- currentTime = 2;
- currentNumber = 0;
- state = 2;
- }
- else
- {
- error = "Invalid place to enter minutes!";
- return false;
- }
+ error = "Invalid place to enter minutes!";
+ return false;
}
- else if ((c == 's') | (c == 'S'))
+ }
+ else if ((c == 's') | (c == 'S'))
+ {
+ if (currentTime <= 2)
{
- if (currentTime <= 2)
- {
- seconds = currentNumber;
- currentTime = 3;
- currentNumber = 0;
- state = 2;
- }
- else
- {
- error = "Invalid place to enter seconds!";
- return false;
- }
+ seconds = currentNumber;
+ currentTime = 3;
+ currentNumber = 0;
+ state = 2;
}
- else if ((c == 'a') | (c == 'A'))
+ else
{
- if (hours == 12)
- {
- hours -= 12;
- }
- state = 4;
+ error = "Invalid place to enter seconds!";
+ return false;
}
- else if ((c == 'p') | (c == 'P'))
+ }
+ else if ((c == 'a') | (c == 'A'))
+ {
+ if (hours == 12)
{
- if (hours != 12)
- {
- hours += 12;
- }
- state = 4;
+ hours -= 12;
}
- else
+ state = 4;
+ }
+ else if ((c == 'p') | (c == 'P'))
+ {
+ if (hours != 12)
{
- error = "Unexpected symbol '" + c + "'";
- return false;
+ hours += 12;
}
+ state = 4;
+ }
+ else
+ {
+ error = "Unexpected symbol '" + c + "'";
+ return false;
}
- break;
+ }
+ break;
- case 2:
+ case 2:
+ {
+ if (!Char.IsLetter(c))
{
- if (!Char.IsLetter(c))
+ if ((c >= '0') & (c <= '9'))
{
- if ((c >= '0') & (c <= '9'))
- {
- currentNumber = (c - '0');
- state = 1;
- }
+ currentNumber = (c - '0');
+ state = 1;
}
}
- break;
- // We received an A or a P, we need to find an M next or fail
- case 4:
+ }
+ break;
+ // We received an A or a P, we need to find an M next or fail
+ case 4:
+ {
+ if ((c == 'm' | c == 'M'))
{
- if ((c == 'm' | c == 'M'))
+ switch (currentTime)
{
- switch (currentTime)
- {
- case 0:
- hours = currentNumber;
- break;
-
- case 1:
- minutes = currentNumber;
- break;
-
- case 2:
- seconds = currentNumber;
- break;
-
- case 3:
- // do nothing in this case, we have had all of the data already entered
- if (currentNumber != 0)
- {
- error = "Too many time entries have been found!";
- return false;
- }
- break;
-
- default:
- error = "Unexpected time state found!";
+ case 0:
+ hours = currentNumber;
+ break;
+
+ case 1:
+ minutes = currentNumber;
+ break;
+
+ case 2:
+ seconds = currentNumber;
+ break;
+
+ case 3:
+ // do nothing in this case, we have had all of the data already entered
+ if (currentNumber != 0)
+ {
+ error = "Too many time entries have been found!";
return false;
- }
- state = 0;
- }
- else
- {
- error = "We were expecting a 'm' but found '" + c + "' instead!";
- return false;
+ }
+ break;
+
+ default:
+ error = "Unexpected time state found!";
+ return false;
}
+ state = 0;
}
- break;
- default:
- error = "Unexpected state found!";
- return false;
- }
- }
- if (state == 1)
- {
- switch (currentTime)
- {
- case 0:
- hours = currentNumber;
- break;
-
- case 1:
- minutes = currentNumber;
- break;
-
- case 2:
- seconds = currentNumber;
- break;
-
- case 3:
- // do nothing in this case, we have had all of the data already entered
- if (currentNumber != 0)
+ else
{
- error = "Too many time entries have been found!";
+ error = "We were expecting a 'm' but found '" + c + "' instead!";
return false;
}
- break;
- default:
- error = "Unexpected time state found!";
- return false;
- }
+ }
+ break;
+ default:
+ error = "Unexpected state found!";
+ return false;
}
- time._internalTime = (long)(hours * 3600 + minutes * 60 + seconds) * 1000;
- return true;
}
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public int CompareTo(Time other)
+ if (state == 1)
{
- return _internalTime < other._internalTime ? -1 : (_internalTime == other._internalTime ? 0 : 1);
+ switch (currentTime)
+ {
+ case 0:
+ hours = currentNumber;
+ break;
+
+ case 1:
+ minutes = currentNumber;
+ break;
+
+ case 2:
+ seconds = currentNumber;
+ break;
+
+ case 3:
+ // do nothing in this case, we have had all of the data already entered
+ if (currentNumber != 0)
+ {
+ error = "Too many time entries have been found!";
+ return false;
+ }
+ break;
+ default:
+ error = "Unexpected time state found!";
+ return false;
+ }
}
+ time._internalTime = (long)(hours * 3600 + minutes * 60 + seconds) * 1000;
+ return true;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public int CompareTo(Time other)
+ {
+ return _internalTime.CompareTo(other._internalTime);
+ }
- public override bool Equals(object? obj)
+ public override bool Equals(object? obj)
+ {
+ if (obj is Time other)
{
- if (obj is Time other)
- {
- return _internalTime == other._internalTime;
- }
- return base.Equals(obj);
+ return _internalTime == other._internalTime;
}
+ return base.Equals(obj);
+ }
- public override int GetHashCode() => base.GetHashCode();
+ public override int GetHashCode() => base.GetHashCode();
- ///
- ///
- ///
- ///
- public float ToFloat() => Hours + (Minutes * 0.01f) + (Seconds * 0.0001f);
+ ///
+ ///
+ ///
+ ///
+ public float ToFloat() => Hours + (Minutes * 0.01f) + (Seconds * 0.0001f);
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public float ToMinutes() => _internalTime * 1.6666666666666666666666666666667e-5f;
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public float ToMinutes() => _internalTime * 1.6666666666666666666666666666667e-5f;
- ///
- ///
- ///
- ///
- override public string ToString()
+ ///
+ ///
+ ///
+ ///
+ override public string ToString()
+ {
+ if ((_internalTime / 1000) % 60 == 0)
{
- if ((_internalTime / 1000) % 60 == 0)
- {
- return String.Format("{0}:{1:00}", Hours, Minutes);
- }
- else
- {
- return String.Format("{0}:{1:00}:{2:00}", Hours, Minutes, Seconds);
- }
+ return String.Format("{0}:{1:00}", Hours, Minutes);
+ }
+ else
+ {
+ return String.Format("{0}:{1:00}:{2:00}", Hours, Minutes, Seconds);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/TMG-Framework/Data/TimePeriod.cs b/src/TMG-Framework/Data/TimePeriod.cs
index b1ece79..0ede168 100644
--- a/src/TMG-Framework/Data/TimePeriod.cs
+++ b/src/TMG-Framework/Data/TimePeriod.cs
@@ -16,43 +16,39 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
You should have received a copy of the GNU General Public License
along with TMG-Framework for XTMF2. If not, see .
*/
-using System;
-using System.Collections.Generic;
-using System.Text;
-namespace TMG
+namespace TMG;
+
+///
+/// This class represents an identified range of time [Start, End).
+///
+public struct TimePeriod
{
///
- /// This class represents an identified range of time [Start, End).
+ /// The start of the time period
+ ///
+ public Time Start { get; private set; }
+
+ ///
+ /// The end of the time period
+ ///
+ public Time End { get; private set; }
+
+ ///
+ /// Construct a time period from the given times.
///
- public struct TimePeriod
+ /// The start time of the time period.(Inclusive)
+ /// THe end time of the time period. (Exclusive)
+ public TimePeriod(Time start, Time end)
{
- ///
- /// The start of the time period
- ///
- public Time Start { get; private set; }
-
- ///
- /// The end of the time period
- ///
- public Time End { get; private set; }
-
- ///
- /// Construct a time period from the given times.
- ///
- /// The start time of the time period.(Inclusive)
- /// THe end time of the time period. (Exclusive)
- public TimePeriod(Time start, Time end)
- {
- Start = start;
- End = end;
- }
-
- ///
- /// Is the given time within this time period.
- ///
- /// The time to test for.
- /// True if it is in the time period, false otherwise.
- public bool Contains(Time time) => (Start <= time) & (time < End);
+ Start = start;
+ End = end;
}
+
+ ///
+ /// Is the given time within this time period.
+ ///
+ /// The time to test for.
+ /// True if it is in the time period, false otherwise.
+ public bool Contains(Time time) => (Start <= time) & (time < End);
}
diff --git a/src/TMG-Framework/Data/Vector.cs b/src/TMG-Framework/Data/Vector.cs
index 10d753b..4fbd10d 100644
--- a/src/TMG-Framework/Data/Vector.cs
+++ b/src/TMG-Framework/Data/Vector.cs
@@ -16,118 +16,117 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
You should have received a copy of the GNU General Public License
along with TMG-Framework for XTMF2. If not, see .
*/
-using System;
+
using System.Buffers;
-using System.Threading;
using static TMG.Utilities.ExceptionHelper;
-namespace TMG
+namespace TMG;
+
+///
+/// Represents a single dimension floating point data storage with a given shape.
+///
+public sealed class Vector : IDisposable
{
///
- /// Represents a single dimension floating point data storage with a given shape.
+ /// The categories that shape this vector.
///
- public sealed class Vector : IDisposable
- {
- ///
- /// The categories that shape this vector.
- ///
- public Categories Categories { get; }
+ public Categories Categories { get; }
- ///
- /// The backing data for this vector.
- ///
- public Span Data => _backingMemory is null ? ThrowAlreadyDisposed() : _backingMemory.Value.Span;
+ ///
+ /// The backing data for this vector.
+ ///
+ public Span Data => _backingMemory is null ? ThrowAlreadyDisposed() : _backingMemory.Value.Span;
- private Span ThrowAlreadyDisposed()
- {
- throw new ObjectDisposedException(nameof(Vector));
- }
+ private Span ThrowAlreadyDisposed()
+ {
+ throw new ObjectDisposedException(nameof(Vector));
+ }
- public void Dispose()
- {
- _backingMemory = default;
- Thread.MemoryBarrier();
- _allocator?.Dispose();
- _allocator = null;
- }
+ public void Dispose()
+ {
+ _backingMemory = default;
+ Thread.MemoryBarrier();
+ _allocator?.Dispose();
+ _allocator = null;
+ }
- ~Vector()
- {
- Dispose();
- }
+ ~Vector()
+ {
+ Dispose();
+ }
- private Memory? _backingMemory;
+ private Memory? _backingMemory;
- private IMemoryOwner? _allocator;
+ private IMemoryOwner? _allocator;
+
+ ///
+ /// Create a new vector given the shape of the categories.
+ ///
+ /// The categories to shape the vector around.
+ public Vector(Categories categories) : this(categories, null) { }
- ///
- /// Create a new vector given the shape of the categories.
- ///
- /// The categories to shape the vector around.
- public Vector(Categories categories) : this (categories, null) {}
-
- ///
- /// Create a new vector given the shape of the categories and an optional memory allocator.
- ///
- /// The categories to shape the vector around.
- /// The memory pool to use for the vector data.
- public Vector(Categories categories, MemoryPool? allocator)
+ ///
+ /// Create a new vector given the shape of the categories and an optional memory allocator.
+ ///
+ /// The categories to shape the vector around.
+ /// The memory pool to use for the vector data.
+ public Vector(Categories categories, MemoryPool? allocator)
+ {
+ if (categories == null)
{
- if(categories == null)
- {
- ThrowParameterNull(nameof(categories));
- }
- Categories = categories;
- _allocator = allocator?.Rent(Categories.Count);
- _backingMemory = _allocator?.Memory ?? new float[Categories.Count];
+ ThrowParameterNull(nameof(categories));
}
+ Categories = categories;
+ _allocator = allocator?.Rent(Categories.Count);
+ _backingMemory = _allocator?.Memory ?? new float[Categories.Count];
+ }
+
+ ///
+ /// Create a new vector given the shape of the given vector.
+ /// This will not create a clone of the given vector.
+ ///
+ /// The vector to use to create the shape from.
+ public Vector(Vector vector) : this(vector, null) { }
- ///
- /// Create a new vector given the shape of the given vector.
- /// This will not create a clone of the given vector.
- ///
- /// The vector to use to create the shape from.
- public Vector(Vector vector) : this(vector, null) { }
-
- ///
- /// Create a new vector given the shape of the given vector and an optional memory allocator.
- ///
- /// The vector to use to create the shape from.
- /// The memory pool to use for the vector data.
- public Vector(Vector vector, MemoryPool? allocator)
+ ///
+ /// Create a new vector given the shape of the given vector and an optional memory allocator.
+ ///
+ /// The vector to use to create the shape from.
+ /// The memory pool to use for the vector data.
+ public Vector(Vector vector, MemoryPool? allocator)
+ {
+ if (vector == null)
{
- if(vector == null)
- {
- ThrowParameterNull(nameof(vector));
- }
- Categories = vector.Categories;
- _allocator = allocator?.Rent(Categories.Count);
- _backingMemory = _allocator?.Memory ?? new float[Categories.Count];
+ ThrowParameterNull(nameof(vector));
}
+ Categories = vector.Categories;
+ _allocator = allocator?.Rent(Categories.Count);
+ _backingMemory = _allocator?.Memory ?? new float[Categories.Count];
+ }
- public float this[CategoryIndex sparseIndex]
+ public float this[CategoryIndex sparseIndex]
+ {
+ get
{
- get
- {
- var index = Categories.GetFlatIndex(sparseIndex);
- return index >= 0 ? Data[index] : 0.0f;
- }
- set
+ var index = Categories.GetFlatIndex(sparseIndex);
+ return index >= 0 ? Data[index] : 0.0f;
+ }
+ set
+ {
+ var index = Categories.GetFlatIndex(sparseIndex);
+ if (index >= 0)
{
- var index = Categories.GetFlatIndex(sparseIndex);
- if (index >= 0)
- {
- Data[index] = value;
- }
- ThrowOutOfRangeException(nameof(sparseIndex));
+ Data[index] = value;
}
+ ThrowOutOfRangeException(nameof(sparseIndex));
}
-
- ///
- /// The number of records contained in this vector.
- ///
- /// The number of elements.
- public int Count => _backingMemory?.Length ?? 0;
}
+
+ ///
+ /// The number of records contained in this vector.
+ ///
+ /// The number of elements.
+ public int Count => _backingMemory?.Length ?? 0;
}
+
diff --git a/src/TMG-Framework/FileOperations/CopyFile.cs b/src/TMG-Framework/FileOperations/CopyFile.cs
index 92e40a5..069186d 100644
--- a/src/TMG-Framework/FileOperations/CopyFile.cs
+++ b/src/TMG-Framework/FileOperations/CopyFile.cs
@@ -16,95 +16,89 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
You should have received a copy of the GNU General Public License
along with TMG-Framework for XTMF2. If not, see .
*/
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.IO;
-using XTMF2;
-namespace TMG.FileOperations
+namespace TMG.FileOperations;
+
+[Module(Name = "Copy File", Description = "Copies a file (or directory) between two places with the option to delete after being copied.",
+ DocumentationLink = "http://tmg.utoronto.ca/doc/2.0")]
+public class CopyFile : BaseAction
{
- [Module(Name = "Copy File", Description = "Copies a file (or directory) between two places with the option to delete after being copied.",
- DocumentationLink = "http://tmg.utoronto.ca/doc/2.0")]
- public class CopyFile : BaseAction
- {
- [Parameter(DefaultValue = "", Name = "Origin", Index = 0, Description = "The path to the file/directory to copy.")]
- public IFunction Origin = null!;
+ [Parameter(DefaultValue = "", Name = "Origin", Index = 0, Description = "The path to the file/directory to copy.")]
+ public IFunction Origin = null!;
- [Parameter(DefaultValue = "", Name = "Destination", Index = 1, Description = "The path to the file/directory to copy into.")]
- public IFunction Destination = null!;
+ [Parameter(DefaultValue = "", Name = "Destination", Index = 1, Description = "The path to the file/directory to copy into.")]
+ public IFunction Destination = null!;
- [Parameter(DefaultValue = "False", Name = "Move", Index = 2, Description = "Should the origin be erased after the file is copied?")]
- public IFunction Move = null!;
+ [Parameter(DefaultValue = "False", Name = "Move", Index = 2, Description = "Should the origin be erased after the file is copied?")]
+ public IFunction Move = null!;
- public override void Invoke()
+ public override void Invoke()
+ {
+ var oInfo = new FileInfo(Origin.Invoke());
+ var dInfo = new FileInfo(Destination.Invoke());
+ var move = Move.Invoke();
+ if (!oInfo.Exists)
{
- var oInfo = new FileInfo(Origin.Invoke());
- var dInfo = new FileInfo(Destination.Invoke());
- var move = Move.Invoke();
- if(!oInfo.Exists)
+ throw new XTMFRuntimeException(this, $"There is no file at the path {oInfo.FullName}!");
+ }
+ var originIsDir = oInfo.Attributes.HasFlag(FileAttributes.Directory);
+ var destIsDir = dInfo.Attributes.HasFlag(FileAttributes.Directory);
+ if (originIsDir)
+ {
+ if (!destIsDir)
{
- throw new XTMFRuntimeException(this, $"There is no file at the path {oInfo.FullName}!");
+ throw new XTMFRuntimeException(this, $"The path {dInfo.FullName} is not a directory where are the source {oInfo.FullName} is!");
}
- var originIsDir = oInfo.Attributes.HasFlag(FileAttributes.Directory);
- var destIsDir = dInfo.Attributes.HasFlag(FileAttributes.Directory);
- if (originIsDir)
+ // copy the directories
+ DirectoryCopy(oInfo.FullName, dInfo.FullName);
+ Directory.Delete(oInfo.FullName);
+ }
+ else
+ {
+ if (destIsDir)
{
- if(!destIsDir)
- {
- throw new XTMFRuntimeException(this, $"The path {dInfo.FullName} is not a directory where are the source {oInfo.FullName} is!");
- }
- // copy the directories
- DirectoryCopy(oInfo.FullName, dInfo.FullName);
- Directory.Delete(oInfo.FullName);
+ oInfo.CopyTo(dInfo.FullName, true);
}
else
{
- if(destIsDir)
- {
- oInfo.CopyTo(dInfo.FullName, true);
- }
- else
- {
- var directory = dInfo.Directory ??
- throw new XTMFRuntimeException(this, $"The path {dInfo.FullName} does not have a valid parent directory!");
- oInfo.CopyTo(directory.FullName, true);
- }
+ var directory = dInfo.Directory ??
+ throw new XTMFRuntimeException(this, $"The path {dInfo.FullName} does not have a valid parent directory!");
+ oInfo.CopyTo(directory.FullName, true);
}
}
+ }
- private static void DirectoryCopy(string sourceDirectory, string destinationDirectory)
+ private static void DirectoryCopy(string sourceDirectory, string destinationDirectory)
+ {
+ // Get the subdirectories for the specified directory.
+ DirectoryInfo dir = new DirectoryInfo(sourceDirectory);
+ DirectoryInfo[] dirs = dir.GetDirectories();
+ if (!dir.Exists)
{
- // Get the subdirectories for the specified directory.
- DirectoryInfo dir = new DirectoryInfo(sourceDirectory);
- DirectoryInfo[] dirs = dir.GetDirectories();
- if (!dir.Exists)
- {
- throw new DirectoryNotFoundException(
- "Source directory does not exist or could not be found: "
- + sourceDirectory);
- }
+ throw new DirectoryNotFoundException(
+ "Source directory does not exist or could not be found: "
+ + sourceDirectory);
+ }
- // If the destination directory doesn't exist, create it.
- if (!Directory.Exists(destinationDirectory))
- {
- Directory.CreateDirectory(destinationDirectory);
- }
+ // If the destination directory doesn't exist, create it.
+ if (!Directory.Exists(destinationDirectory))
+ {
+ Directory.CreateDirectory(destinationDirectory);
+ }
- // Get the files in the directory and copy them to the new location.
- FileInfo[] files = dir.GetFiles();
- foreach (FileInfo file in files)
- {
- string temppath = Path.Combine(destinationDirectory, file.Name);
- file.CopyTo(temppath, true);
- }
+ // Get the files in the directory and copy them to the new location.
+ FileInfo[] files = dir.GetFiles();
+ foreach (FileInfo file in files)
+ {
+ string temppath = Path.Combine(destinationDirectory, file.Name);
+ file.CopyTo(temppath, true);
+ }
- // If copying subdirectories, copy them and their contents to new location.
- foreach (DirectoryInfo subdir in dirs)
- {
- string temppath = Path.Combine(destinationDirectory, subdir.Name);
- DirectoryCopy(subdir.FullName, temppath);
- }
+ // If copying subdirectories, copy them and their contents to new location.
+ foreach (DirectoryInfo subdir in dirs)
+ {
+ string temppath = Path.Combine(destinationDirectory, subdir.Name);
+ DirectoryCopy(subdir.FullName, temppath);
}
}
}
diff --git a/src/TMG-Framework/FileOperations/DeleteFile.cs b/src/TMG-Framework/FileOperations/DeleteFile.cs
index 8390d2a..cd68078 100644
--- a/src/TMG-Framework/FileOperations/DeleteFile.cs
+++ b/src/TMG-Framework/FileOperations/DeleteFile.cs
@@ -16,36 +16,30 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
You should have received a copy of the GNU General Public License
along with TMG-Framework for XTMF2. If not, see .
*/
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.IO;
-using XTMF2;
-namespace TMG.FileOperations
+namespace TMG.FileOperations;
+
+[Module(Name = "Delete File", Description = "Delete a file (or directory).",
+ DocumentationLink = "http://tmg.utoronto.ca/doc/2.0")]
+public sealed class DeleteFile : BaseAction
{
- [Module(Name = "Delete File", Description = "Delete a file (or directory).",
- DocumentationLink = "http://tmg.utoronto.ca/doc/2.0")]
- public sealed class DeleteFile : BaseAction
- {
- [Parameter(DefaultValue = "", Name = "To Delete", Index = 0, Description = "The path to delete.")]
- public IFunction ToDelete = null!;
+ [Parameter(DefaultValue = "", Name = "To Delete", Index = 0, Description = "The path to delete.")]
+ public IFunction ToDelete = null!;
- public override void Invoke()
+ public override void Invoke()
+ {
+ var info = new FileInfo(ToDelete.Invoke());
+ if (!info.Exists)
+ {
+ throw new XTMFRuntimeException(this, $"The file does not exist {info.FullName}!");
+ }
+ if (info.Attributes.HasFlag(FileAttributes.Directory))
+ {
+ new DirectoryInfo(info.FullName).Delete(true);
+ }
+ else
{
- var info = new FileInfo(ToDelete.Invoke());
- if(!info.Exists)
- {
- throw new XTMFRuntimeException(this, $"The file does not exist {info.FullName}!");
- }
- if (info.Attributes.HasFlag(FileAttributes.Directory))
- {
- new DirectoryInfo(info.FullName).Delete(true);
- }
- else
- {
- info.Delete();
- }
+ info.Delete();
}
}
}
diff --git a/src/TMG-Framework/GlobalUsings.cs b/src/TMG-Framework/GlobalUsings.cs
new file mode 100644
index 0000000..0f513b1
--- /dev/null
+++ b/src/TMG-Framework/GlobalUsings.cs
@@ -0,0 +1,9 @@
+global using System;
+global using System.Collections.Generic;
+global using System.Diagnostics.CodeAnalysis;
+global using System.Linq;
+global using System.Runtime.CompilerServices;
+global using System.Runtime.InteropServices;
+global using System.Text;
+
+global using XTMF2;
diff --git a/src/TMG-Framework/Loading/LoadCategoriesFromCSV.cs b/src/TMG-Framework/Loading/LoadCategoriesFromCSV.cs
index d4489e1..bcaf3d7 100644
--- a/src/TMG-Framework/Loading/LoadCategoriesFromCSV.cs
+++ b/src/TMG-Framework/Loading/LoadCategoriesFromCSV.cs
@@ -16,11 +16,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
You should have received a copy of the GNU General Public License
along with TMG-Framework for XTMF2. If not, see .
*/
-using System;
-using System.Collections.Generic;
-using System.Text;
+
using TMG.Utilities;
-using XTMF2;
namespace TMG.Loading;
diff --git a/src/TMG-Framework/Loading/LoadCategoryMapFromThirdNormalizedCSV.cs b/src/TMG-Framework/Loading/LoadCategoryMapFromThirdNormalizedCSV.cs
index 8654563..fe1ad5c 100644
--- a/src/TMG-Framework/Loading/LoadCategoryMapFromThirdNormalizedCSV.cs
+++ b/src/TMG-Framework/Loading/LoadCategoryMapFromThirdNormalizedCSV.cs
@@ -16,173 +16,167 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
You should have received a copy of the GNU General Public License
along with TMG-Framework for XTMF2. If not, see .
*/
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Text;
using TMG.Utilities;
-using XTMF2;
-namespace TMG.Loading
+namespace TMG.Loading;
+
+[Module(Name = "Load Category Map From Third Normalized CSV",
+ Description = "Loads a category map (such as planning districts)",
+ DocumentationLink = "http://tmg.utoronto.ca/doc/2.0")]
+public class LoadCategoryMapFromThirdNormalizedCSV : BaseFunction
{
- [Module(Name = "Load Category Map From Third Normalized CSV",
- Description = "Loads a category map (such as planning districts)",
- DocumentationLink = "http://tmg.utoronto.ca/doc/2.0")]
- public class LoadCategoryMapFromThirdNormalizedCSV : BaseFunction
- {
- [SubModule(Index = 0, Required = true, Name = "Base Categories", Description = "The categories that this map from to the Destination Categories.")]
- public IFunction BaseCategories = null!;
+ [SubModule(Index = 0, Required = true, Name = "Base Categories", Description = "The categories that this map from to the Destination Categories.")]
+ public IFunction BaseCategories = null!;
- [SubModule(Index = 1, Required = false, Name = "Destination Categories", Description = "The categories that this map to from the Base Categories. If not linked the CSV will create a new one based on the destination values found.")]
- public IFunction? DestinationCategories;
+ [SubModule(Index = 1, Required = false, Name = "Destination Categories", Description = "The categories that this map to from the Base Categories. If not linked the CSV will create a new one based on the destination values found.")]
+ public IFunction? DestinationCategories;
- [SubModule(Index = 2, Required = true, Name = "CSV Stream", Description = "The stream that we will read from.")]
- public IFunction CSVStream = null!;
+ [SubModule(Index = 2, Required = true, Name = "CSV Stream", Description = "The stream that we will read from.")]
+ public IFunction CSVStream = null!;
- [Parameter(DefaultValue = "0", Name = "Base Column", Index = 3, Description = "The 0 indexed column containing the sparse map index for the base category index.")]
- public IFunction BaseColumn = null!;
+ [Parameter(DefaultValue = "0", Name = "Base Column", Index = 3, Description = "The 0 indexed column containing the sparse map index for the base category index.")]
+ public IFunction BaseColumn = null!;
- [Parameter(DefaultValue = "1", Name = "Destination Column", Index = 4, Description = "The 0 indexed column containing the sparse map index for the destination category index.")]
- public IFunction DestinationColumn = null!;
+ [Parameter(DefaultValue = "1", Name = "Destination Column", Index = 4, Description = "The 0 indexed column containing the sparse map index for the destination category index.")]
+ public IFunction DestinationColumn = null!;
- public override CategoryMap Invoke()
+ public override CategoryMap Invoke()
+ {
+ var destinationCategories = DestinationCategories?.Invoke();
+ if (destinationCategories is null)
{
- var destinationCategories = DestinationCategories?.Invoke();
- if (destinationCategories is null)
- {
- return LoadWithCustomDestinations();
- }
- else
- {
- return LoadWithStrictDestinations(destinationCategories);
- }
+ return LoadWithCustomDestinations();
}
-
- ///
- /// Load the category map where we are generating the destinations on the fly.
- ///
- /// Returns the mapping of categories from the base to the destination.
- private CategoryMap LoadWithCustomDestinations()
+ else
{
- var records = LoadMapRecords();
- Categories destinationCategories = GetDestinationCategoriesFromRecords(records);
- return Load(records, destinationCategories);
+ return LoadWithStrictDestinations(destinationCategories);
}
+ }
- ///
- /// Load the category map where there are pre-defined destination categories.
- ///
- /// The destination categories to map to.
- /// Returns the mapping of categories from the base to the destination.
- private CategoryMap LoadWithStrictDestinations(Categories destinationCategories)
- {
- return Load(LoadMapRecords(), destinationCategories);
- }
+ ///
+ /// Load the category map where we are generating the destinations on the fly.
+ ///
+ /// Returns the mapping of categories from the base to the destination.
+ private CategoryMap LoadWithCustomDestinations()
+ {
+ var records = LoadMapRecords();
+ Categories destinationCategories = GetDestinationCategoriesFromRecords(records);
+ return Load(records, destinationCategories);
+ }
- ///
- /// Generates a Categories object using the destinations specified in the loaded mapping records.
- ///
- /// The records of the map.
- /// A Categories object that represents the destinations from the records organized in ascending order.
- /// This throws when we are unable to create the categories object.
- private Categories GetDestinationCategoriesFromRecords(List<(int baseSparseIndex, int destinationSparseIndex)> records)
- {
- string? error = null;
- if(!Categories.CreateCategories(records
- .Select(r => r.destinationSparseIndex)
- .Distinct()
- .OrderBy(r => r)
- .ToList(), out var ret,ref error))
- {
- throw new XTMFRuntimeException(this, error);
- }
- return ret;
- }
+ ///
+ /// Load the category map where there are pre-defined destination categories.
+ ///
+ /// The destination categories to map to.
+ /// Returns the mapping of categories from the base to the destination.
+ private CategoryMap LoadWithStrictDestinations(Categories destinationCategories)
+ {
+ return Load(LoadMapRecords(), destinationCategories);
+ }
- ///
- /// Creates the CategoryMap using the sparse records and destination categories.
- ///
- /// The records in sparse-space for the map.
- /// The destination categories that we will check for.
- /// Returns a category map between the Base categories and the Destination categories.
- /// This is thrown if there is a sparse-record that is not defined in their respective category.
- private CategoryMap Load(List<(int baseSparseIndex, int destinationSparseIndex)> records, Categories destinationCategories)
+ ///
+ /// Generates a Categories object using the destinations specified in the loaded mapping records.
+ ///
+ /// The records of the map.
+ /// A Categories object that represents the destinations from the records organized in ascending order.
+ /// This throws when we are unable to create the categories object.
+ private Categories GetDestinationCategoriesFromRecords(List<(int baseSparseIndex, int destinationSparseIndex)> records)
+ {
+ string? error = null;
+ if (!Categories.CreateCategories(records
+ .Select(r => r.destinationSparseIndex)
+ .Distinct()
+ .OrderBy(r => r)
+ .ToList(), out var ret, ref error))
{
- var baseCategories = BaseCategories!.Invoke();
- var flatRecords = records
- .Select(record =>
- {
- var ret = (BaseIndex: baseCategories.GetFlatIndex(record.baseSparseIndex),
- DestinationIndex: destinationCategories.GetFlatIndex(record.destinationSparseIndex));
- if (ret.BaseIndex < 0)
- {
- ThrowBadBaseIndex(ret.BaseIndex);
- }
- if (ret.DestinationIndex < 0)
- {
- ThrowBadDestinationIndex(ret.DestinationIndex);
- }
- return ret;
- }).ToList();
- string? error = null;
- if (!CategoryMap.CreateCategoryMap(baseCategories, destinationCategories, flatRecords, out var map, ref error))
- {
- throw new XTMFRuntimeException(this, error);
- }
- return map;
+ throw new XTMFRuntimeException(this, error);
}
+ return ret;
+ }
- ///
- /// A helper function to throw if we load a sparse index that is not contained in the base categories.
- ///
- /// The sparse index that was not found.
- /// This always throws.
- private void ThrowBadBaseIndex(int baseSparseIndex)
+ ///
+ /// Creates the CategoryMap using the sparse records and destination categories.
+ ///
+ /// The records in sparse-space for the map.
+ /// The destination categories that we will check for.
+ /// Returns a category map between the Base categories and the Destination categories.
+ /// This is thrown if there is a sparse-record that is not defined in their respective category.
+ private CategoryMap Load(List<(int baseSparseIndex, int destinationSparseIndex)> records, Categories destinationCategories)
+ {
+ var baseCategories = BaseCategories!.Invoke();
+ var flatRecords = records
+ .Select(record =>
+ {
+ var ret = (BaseIndex: baseCategories.GetFlatIndex(record.baseSparseIndex),
+ DestinationIndex: destinationCategories.GetFlatIndex(record.destinationSparseIndex));
+ if (ret.BaseIndex < 0)
+ {
+ ThrowBadBaseIndex(ret.BaseIndex);
+ }
+ if (ret.DestinationIndex < 0)
+ {
+ ThrowBadDestinationIndex(ret.DestinationIndex);
+ }
+ return ret;
+ }).ToList();
+ string? error = null;
+ if (!CategoryMap.CreateCategoryMap(baseCategories, destinationCategories, flatRecords, out var map, ref error))
{
- throw new XTMFRuntimeException(this, $"Found an invalid base category sparse index {baseSparseIndex} while loading in the category map!");
+ throw new XTMFRuntimeException(this, error);
}
+ return map;
+ }
- ///
- /// A helper function to throw if we load a sparse index that is not contained in the destination categories.
- ///
- /// The sparse index that was not found.
- /// This always throws.
- private void ThrowBadDestinationIndex(int destinationSparseIndex)
- {
- throw new XTMFRuntimeException(this, $"Found an invalid destination category sparse index {destinationSparseIndex} while loading in the category map!");
- }
+ ///
+ /// A helper function to throw if we load a sparse index that is not contained in the base categories.
+ ///
+ /// The sparse index that was not found.
+ /// This always throws.
+ private void ThrowBadBaseIndex(int baseSparseIndex)
+ {
+ throw new XTMFRuntimeException(this, $"Found an invalid base category sparse index {baseSparseIndex} while loading in the category map!");
+ }
- ///
- /// Loads the sparse-index mapping records from the stream.
- ///
- /// The sparse-indexed records.
- /// This is thrown if we are unable to properly parse a line.
- private List<(int baseSparseIndex, int destinationSparseIndex)> LoadMapRecords()
+ ///
+ /// A helper function to throw if we load a sparse index that is not contained in the destination categories.
+ ///
+ /// The sparse index that was not found.
+ /// This always throws.
+ private void ThrowBadDestinationIndex(int destinationSparseIndex)
+ {
+ throw new XTMFRuntimeException(this, $"Found an invalid destination category sparse index {destinationSparseIndex} while loading in the category map!");
+ }
+
+ ///
+ /// Loads the sparse-index mapping records from the stream.
+ ///
+ /// The sparse-indexed records.
+ /// This is thrown if we are unable to properly parse a line.
+ private List<(int baseSparseIndex, int destinationSparseIndex)> LoadMapRecords()
+ {
+ var baseColumn = BaseColumn!.Invoke();
+ var destinationColumn = DestinationColumn!.Invoke();
+ int requiredColumns = Math.Max(baseColumn, destinationColumn) + 1;
+ var streamReader = new CsvReader(CSVStream!.Invoke(), true);
+ var records = new List<(int baseSparseIndex, int destinationSparseIndex)>();
+ try
{
- var baseColumn = BaseColumn!.Invoke();
- var destinationColumn = DestinationColumn!.Invoke();
- int requiredColumns = Math.Max(baseColumn, destinationColumn) + 1;
- var streamReader = new CsvReader(CSVStream!.Invoke(), true);
- var records = new List<(int baseSparseIndex, int destinationSparseIndex)>();
- try
+ while (streamReader.LoadLine(out int columns))
{
- while (streamReader.LoadLine(out int columns))
+ if (columns >= requiredColumns)
{
- if (columns >= requiredColumns)
- {
- streamReader.Get(out int baseSparseIndex, baseColumn);
- streamReader.Get(out int destinationSparseIndex, destinationColumn);
- records.Add((baseSparseIndex, destinationSparseIndex));
- }
+ streamReader.Get(out int baseSparseIndex, baseColumn);
+ streamReader.Get(out int destinationSparseIndex, destinationColumn);
+ records.Add((baseSparseIndex, destinationSparseIndex));
}
}
- catch
- {
- throw new XTMFRuntimeException(this, $"Unable to read category map from {streamReader.FileName} on line {streamReader.LineNumber}!");
- }
-
- return records;
}
+ catch
+ {
+ throw new XTMFRuntimeException(this, $"Unable to read category map from {streamReader.FileName} on line {streamReader.LineNumber}!");
+ }
+
+ return records;
}
}
+
diff --git a/src/TMG-Framework/Loading/LoadMatrixFromCSVMatrix.cs b/src/TMG-Framework/Loading/LoadMatrixFromCSVMatrix.cs
index 28ed1f5..907f829 100644
--- a/src/TMG-Framework/Loading/LoadMatrixFromCSVMatrix.cs
+++ b/src/TMG-Framework/Loading/LoadMatrixFromCSVMatrix.cs
@@ -16,63 +16,58 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
You should have received a copy of the GNU General Public License
along with TMG-Framework for XTMF2. If not, see .
*/
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Text;
+
using TMG.Utilities;
-using XTMF2;
-namespace TMG.Loading
+namespace TMG.Loading;
+
+[Module(Name = "Load Matrix From CSV", Description = "Loads a matrix of data in the shape of the SparseMap from a CSV in third normalized form.",
+ DocumentationLink = "http://tmg.utoronto.ca/doc/2.0")]
+public sealed class LoadMatrixFromCSVMatrix : BaseFunction
{
- [Module(Name = "Load Matrix From CSV", Description = "Loads a matrix of data in the shape of the SparseMap from a CSV in third normalized form.",
- DocumentationLink = "http://tmg.utoronto.ca/doc/2.0")]
- public sealed class LoadMatrixFromCSVMatrix : BaseFunction
- {
- [SubModule(Required = true, Name = "Row Categories", Description = "The sparse map this vector will be shaped in.", Index = 0)]
- public IFunction RowCategories = null!;
+ [SubModule(Required = true, Name = "Row Categories", Description = "The sparse map this vector will be shaped in.", Index = 0)]
+ public IFunction RowCategories = null!;
- [SubModule(Required = true, Name = "Column Categories", Description = "The sparse map this vector will be shaped in.", Index = 1)]
- public IFunction ColumnCategories = null!;
+ [SubModule(Required = true, Name = "Column Categories", Description = "The sparse map this vector will be shaped in.", Index = 1)]
+ public IFunction ColumnCategories = null!;
- public override Matrix Invoke(ReadStream stream)
+ public override Matrix Invoke(ReadStream stream)
+ {
+ var columnCategories = ColumnCategories.Invoke();
+ var rowCategories = RowCategories.Invoke();
+ var ret = new Matrix(rowCategories, columnCategories);
+ var flatData = ret.Data;
+ var rowSize = columnCategories.Count;
+ using (var reader = new CsvReader(stream, true))
{
- var columnCategories = ColumnCategories.Invoke();
- var rowCategories = RowCategories.Invoke();
- var ret = new Matrix(rowCategories, columnCategories);
- var flatData = ret.Data;
- var rowSize = columnCategories.Count;
- using (var reader = new CsvReader(stream, true))
+ var headers = reader.Headers;
+ // read in the destination indexes
+ int[] destinationFlatIndex = new int[headers.Length - 1];
+ for (int i = 1; i < headers.Length; i++)
{
- var headers = reader.Headers;
- // read in the destination indexes
- int[] destinationFlatIndex = new int[headers.Length - 1];
- for (int i = 1; i < headers.Length; i++)
+ var sparseIndex = int.Parse(headers[i]);
+ if ((destinationFlatIndex[i - 1] = columnCategories.GetFlatIndex(sparseIndex)) < 0)
{
- var sparseIndex = int.Parse(headers[i]);
- if((destinationFlatIndex[i - 1] = columnCategories.GetFlatIndex(sparseIndex)) < 0)
- {
- throw new XTMFRuntimeException(this, $"Invalid sparse column index {sparseIndex}!");
- }
+ throw new XTMFRuntimeException(this, $"Invalid sparse column index {sparseIndex}!");
}
- while(reader.LoadLine(out var columns))
+ }
+ while (reader.LoadLine(out var columns))
+ {
+ if (columns >= destinationFlatIndex.Length + 1)
{
- if(columns >= destinationFlatIndex.Length + 1)
+ reader.Get(out int sparseIndex, 0);
+ var originOffset = rowCategories.GetFlatIndex(sparseIndex) * rowSize;
+ if (originOffset < 0)
+ {
+ throw new XTMFRuntimeException(this, $"Invalid sparse row index {sparseIndex}!");
+ }
+ for (int i = 0; i < destinationFlatIndex.Length; i++)
{
- reader.Get(out int sparseIndex, 0);
- var originOffset = rowCategories.GetFlatIndex(sparseIndex) * rowSize;
- if(originOffset < 0)
- {
- throw new XTMFRuntimeException(this, $"Invalid sparse row index {sparseIndex}!");
- }
- for (int i = 0; i < destinationFlatIndex.Length; i++)
- {
- reader.Get(out flatData[originOffset + destinationFlatIndex[i]], i + 1);
- }
+ reader.Get(out flatData[originOffset + destinationFlatIndex[i]], i + 1);
}
}
}
- return ret;
}
+ return ret;
}
}
diff --git a/src/TMG-Framework/Loading/LoadMatrixFromCSVThirdNormalized.cs b/src/TMG-Framework/Loading/LoadMatrixFromCSVThirdNormalized.cs
index 147515a..9088c6b 100644
--- a/src/TMG-Framework/Loading/LoadMatrixFromCSVThirdNormalized.cs
+++ b/src/TMG-Framework/Loading/LoadMatrixFromCSVThirdNormalized.cs
@@ -16,80 +16,76 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
You should have received a copy of the GNU General Public License
along with TMG-Framework for XTMF2. If not, see .
*/
-using System;
-using System.Collections.Generic;
-using System.Text;
+
using TMG.Utilities;
-using XTMF2;
-namespace TMG.Loading
+namespace TMG.Loading;
+
+[Module(Name = "Load Matrix From CSV", Description = "Loads a matrix of data in the shape of the SparseMap from a CSV in third normalized form.",
+ DocumentationLink = "http://tmg.utoronto.ca/doc/2.0")]
+public sealed class LoadMatrixFromCSVThirdNormalized : BaseFunction
{
- [Module(Name = "Load Matrix From CSV", Description = "Loads a matrix of data in the shape of the SparseMap from a CSV in third normalized form.",
- DocumentationLink = "http://tmg.utoronto.ca/doc/2.0")]
- public sealed class LoadMatrixFromCSVThirdNormalized : BaseFunction
- {
- [SubModule(Required = true, Name = "Row Categories", Description = "The sparse map this vector will be shaped in.", Index = 0)]
- public IFunction RowCategories = null!;
+ [SubModule(Required = true, Name = "Row Categories", Description = "The sparse map this vector will be shaped in.", Index = 0)]
+ public IFunction RowCategories = null!;
- [SubModule(Required = true, Name = "Column Categories", Description = "The sparse map this vector will be shaped in.", Index = 1)]
- public IFunction ColumnCategories = null!;
+ [SubModule(Required = true, Name = "Column Categories", Description = "The sparse map this vector will be shaped in.", Index = 1)]
+ public IFunction ColumnCategories = null!;
- [Parameter(DefaultValue = "0", Name = "Origin Column", Index = 2, Description = "The 0 indexed column containing the sparse map index for the origin.")]
- public IFunction OriginColumn = null!;
+ [Parameter(DefaultValue = "0", Name = "Origin Column", Index = 2, Description = "The 0 indexed column containing the sparse map index for the origin.")]
+ public IFunction OriginColumn = null!;
- [Parameter(DefaultValue = "1", Name = "Destination Column", Index = 3, Description = "The 0 indexed column containing the sparse map index for the destination.")]
- public IFunction DestinationColumn = null!;
+ [Parameter(DefaultValue = "1", Name = "Destination Column", Index = 3, Description = "The 0 indexed column containing the sparse map index for the destination.")]
+ public IFunction DestinationColumn = null!;
- [Parameter(DefaultValue = "2", Name = "Data Column", Index = 4, Description = "The 0 indexed column containing the data to load index.")]
- public IFunction DataColumn = null!;
+ [Parameter(DefaultValue = "2", Name = "Data Column", Index = 4, Description = "The 0 indexed column containing the data to load index.")]
+ public IFunction DataColumn = null!;
- public override Matrix Invoke(ReadStream stream)
+ public override Matrix Invoke(ReadStream stream)
+ {
+ var rowCategories = RowCategories.Invoke();
+ var columnCategories = ColumnCategories.Invoke();
+ var rowSize = rowCategories.Count;
+ var ret = new Matrix(rowCategories, columnCategories);
+ var data = ret.Data;
+ var originColumn = OriginColumn.Invoke();
+ var destinationColumn = DestinationColumn.Invoke();
+ var dataColumn = DataColumn.Invoke();
+ if (originColumn < 0 || destinationColumn < 0 || dataColumn < 0)
{
- var rowCategories = RowCategories.Invoke();
- var columnCategories = ColumnCategories.Invoke();
- var rowSize = rowCategories.Count;
- var ret = new Matrix(rowCategories, columnCategories);
- var data = ret.Data;
- var originColumn = OriginColumn.Invoke();
- var destinationColumn = DestinationColumn.Invoke();
- var dataColumn = DataColumn.Invoke();
- if (originColumn < 0 || destinationColumn < 0 || dataColumn < 0)
- {
- throw new XTMFRuntimeException(this, "Column indexes must be greater than or equal to zero!");
- }
- var minColumnSize = Math.Max(originColumn, dataColumn);
- using (var reader = new CsvReader(stream, true))
+ throw new XTMFRuntimeException(this, "Column indexes must be greater than or equal to zero!");
+ }
+ var minColumnSize = Math.Max(originColumn, dataColumn);
+ using (var reader = new CsvReader(stream, true))
+ {
+ reader.LoadLine();
+ while (reader.LoadLine(out var columns))
{
- reader.LoadLine();
- while (reader.LoadLine(out var columns))
+ // This is strictly greater because the column size is 0 indexed
+ if (columns > minColumnSize)
{
- // This is strictly greater because the column size is 0 indexed
- if (columns > minColumnSize)
+ int flatOrigin, flatDestination;
+ reader.Get(out int originIndex, originColumn);
+ reader.Get(out int destinationIndex, originColumn);
+ reader.Get(out float dataValue, dataColumn);
+ if ((flatOrigin = rowCategories.GetFlatIndex(originIndex)) >= 0 && (flatDestination = columnCategories.GetFlatIndex(destinationIndex)) >= 0)
+ {
+ // if we know where to put it
+ data[flatOrigin * rowSize + flatDestination] = dataValue;
+ }
+ else
{
- int flatOrigin, flatDestination;
- reader.Get(out int originIndex, originColumn);
- reader.Get(out int destinationIndex, originColumn);
- reader.Get(out float dataValue, dataColumn);
- if ((flatOrigin = rowCategories.GetFlatIndex(originIndex)) >= 0 && (flatDestination = columnCategories.GetFlatIndex(destinationIndex)) >= 0)
+ if (flatOrigin < 0)
{
- // if we know where to put it
- data[flatOrigin * rowSize + flatDestination] = dataValue;
+ throw new XTMFRuntimeException(this, $"An invalid origin was specified {originIndex}!");
}
else
{
- if (flatOrigin < 0)
- {
- throw new XTMFRuntimeException(this, $"An invalid origin was specified {originIndex}!");
- }
- else
- {
- throw new XTMFRuntimeException(this, $"An invalid destination was specified {destinationIndex}!");
- }
+ throw new XTMFRuntimeException(this, $"An invalid destination was specified {destinationIndex}!");
}
}
}
}
- return ret;
}
+ return ret;
}
}
diff --git a/src/TMG-Framework/Loading/LoadMatrixFromMTX.cs b/src/TMG-Framework/Loading/LoadMatrixFromMTX.cs
index 0967881..e653a8e 100644
--- a/src/TMG-Framework/Loading/LoadMatrixFromMTX.cs
+++ b/src/TMG-Framework/Loading/LoadMatrixFromMTX.cs
@@ -16,163 +16,155 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
You should have received a copy of the GNU General Public License
along with TMG-Framework for XTMF2. If not, see .
*/
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using System.Text;
-using TMG.Utilities;
-using XTMF2;
-
-namespace TMG.Loading
+
+namespace TMG.Loading;
+
+[Module(Name = "Load SparseMatrix From MTX", Description = "Loads a matrix of data in the shape of the SparseMap from an EMME matrix file.",
+DocumentationLink = "http://tmg.utoronto.ca/doc/2.0")]
+public sealed class LoadMatrixFromMTX : BaseFunction
{
- [Module(Name = "Load SparseMatrix From MTX", Description = "Loads a matrix of data in the shape of the SparseMap from an EMME matrix file.",
- DocumentationLink = "http://tmg.utoronto.ca/doc/2.0")]
- public sealed class LoadMatrixFromMTX : BaseFunction
- {
- [SubModule(Required = true, Name = "Map", Description = "The sparse map this vector will be shaped in.", Index = 0)]
- public IFunction Categories = null!;
+ [SubModule(Required = true, Name = "Map", Description = "The sparse map this vector will be shaped in.", Index = 0)]
+ public IFunction Categories = null!;
- [Parameter(Name = "Convert Between Zone Systems", DefaultValue = "false", Description = "A function that converts between the zone system of the matrix and the zone system of the map.", Index = 1)]
- public IFunction ConvertBetweenZoneSystems = null!;
+ [Parameter(Name = "Convert Between Zone Systems", DefaultValue = "false", Description = "A function that converts between the zone system of the matrix and the zone system of the map.", Index = 1)]
+ public IFunction ConvertBetweenZoneSystems = null!;
- private const uint MagicNumber = 0xC4D4F1B2;
+ private const uint MagicNumber = 0xC4D4F1B2;
- private const int FloatType = 0x1;
+ private const int FloatType = 0x1;
- public override Matrix Invoke(ReadStream context)
+ public override Matrix Invoke(ReadStream context)
+ {
+ var categories = Categories.Invoke();
+ var matrix = new Matrix(categories, categories);
+ using (var reader = new BinaryReader(context))
{
- var categories = Categories.Invoke();
- var matrix = new Matrix(categories, categories);
- using (var reader = new BinaryReader(context))
+ var magic = reader.ReadUInt32();
+ if (magic != MagicNumber)
{
- var magic = reader.ReadUInt32();
- if(magic != MagicNumber)
- {
- throw new XTMFRuntimeException(this, "The file was not an EMME matrix!");
- }
- // version
- reader.ReadInt32();
- var type = reader.ReadInt32();
- if(type != FloatType)
- {
- throw new XTMFRuntimeException(this, "The matrix was not using a float type!");
- }
- var numberOfIndexes = reader.ReadInt32();
- if(numberOfIndexes != 2)
- {
- throw new XTMFRuntimeException(this, $"The matrix contained {numberOfIndexes} dimensions!");
- }
-
- var convert = ConvertBetweenZoneSystems.Invoke();
- if(!convert)
- {
- LoadWithoutConversion(categories, matrix, reader);
- }
- else
- {
- LoadWithConversion(categories, matrix, reader);
- }
+ throw new XTMFRuntimeException(this, "The file was not an EMME matrix!");
}
- return matrix;
- }
-
- private void LoadWithoutConversion(Categories categories, Matrix matrix, BinaryReader reader)
- {
- int firstSize = reader.ReadInt32();
- int secondSize = reader.ReadInt32();
- if (categories.Count != firstSize)
+ // version
+ reader.ReadInt32();
+ var type = reader.ReadInt32();
+ if (type != FloatType)
{
- throw new XTMFRuntimeException(this, "The matrix had the wrong number of elements in the first dimension!");
+ throw new XTMFRuntimeException(this, "The matrix was not using a float type!");
}
- if (categories.Count != secondSize)
+ var numberOfIndexes = reader.ReadInt32();
+ if (numberOfIndexes != 2)
{
- throw new XTMFRuntimeException(this, "The matrix had the wrong number of elements in the second dimension!");
+ throw new XTMFRuntimeException(this, $"The matrix contained {numberOfIndexes} dimensions!");
}
- ValidateIndexes(reader, categories);
- ValidateIndexes(reader, categories);
- var data = matrix.Data;
- var dataSize = data.Length * sizeof(float);
- var soFar = 0;
- while (soFar < dataSize)
+ var convert = ConvertBetweenZoneSystems.Invoke();
+ if (!convert)
{
- var amount = reader.Read(MemoryMarshal.Cast(data)[soFar..dataSize]);
- if (amount == 0)
- {
- throw new XTMFRuntimeException(this, $"The matrix expected {dataSize}bytes but we only could get {soFar}bytes!");
- }
- soFar += amount;
+ LoadWithoutConversion(categories, matrix, reader);
+ }
+ else
+ {
+ LoadWithConversion(categories, matrix, reader);
}
}
+ return matrix;
+ }
+
+ private void LoadWithoutConversion(Categories categories, Matrix matrix, BinaryReader reader)
+ {
+ int firstSize = reader.ReadInt32();
+ int secondSize = reader.ReadInt32();
+ if (categories.Count != firstSize)
+ {
+ throw new XTMFRuntimeException(this, "The matrix had the wrong number of elements in the first dimension!");
+ }
+ if (categories.Count != secondSize)
+ {
+ throw new XTMFRuntimeException(this, "The matrix had the wrong number of elements in the second dimension!");
+ }
+ ValidateIndexes(reader, categories);
+ ValidateIndexes(reader, categories);
- private void LoadWithConversion(Categories categories, Matrix matrix, BinaryReader reader)
+ var data = matrix.Data;
+ var dataSize = data.Length * sizeof(float);
+ var soFar = 0;
+ while (soFar < dataSize)
{
- int rowSize = reader.ReadInt32();
- int columnSize = reader.ReadInt32();
-
- if (rowSize != columnSize)
+ var amount = reader.Read(MemoryMarshal.Cast(data)[soFar..dataSize]);
+ if (amount == 0)
{
- throw new XTMFRuntimeException(this, "The matrix was not square!");
+ throw new XTMFRuntimeException(this, $"The matrix expected {dataSize}bytes but we only could get {soFar}bytes!");
}
+ soFar += amount;
+ }
+ }
- // Load in the column categories (sparse space)
- var rows = new int[rowSize];
- var columns = new int[columnSize];
+ private void LoadWithConversion(Categories categories, Matrix matrix, BinaryReader reader)
+ {
+ int rowSize = reader.ReadInt32();
+ int columnSize = reader.ReadInt32();
- reader.ReadExactly(MemoryMarshal.Cast(rows.AsSpan()));
- reader.ReadExactly(MemoryMarshal.Cast(columns.AsSpan()));
+ if (rowSize != columnSize)
+ {
+ throw new XTMFRuntimeException(this, "The matrix was not square!");
+ }
+
+ // Load in the column categories (sparse space)
+ var rows = new int[rowSize];
+ var columns = new int[columnSize];
- // Load in the matrix data
- var numberOfElements = rowSize * columnSize;
- var dataSize = numberOfElements * sizeof(float);
- var data = new float[numberOfElements];
- var dataSpan = data.AsSpan();
- var soFar = 0;
- while (soFar < dataSize)
+ reader.ReadExactly(MemoryMarshal.Cast(rows.AsSpan()));
+ reader.ReadExactly(MemoryMarshal.Cast(columns.AsSpan()));
+
+ // Load in the matrix data
+ var numberOfElements = rowSize * columnSize;
+ var dataSize = numberOfElements * sizeof(float);
+ var data = new float[numberOfElements];
+ var dataSpan = data.AsSpan();
+ var soFar = 0;
+ while (soFar < dataSize)
+ {
+ var amount = reader.Read(MemoryMarshal.Cast(dataSpan)[soFar..dataSize]);
+ if (amount == 0)
{
- var amount = reader.Read(MemoryMarshal.Cast(dataSpan)[soFar..dataSize]);
- if (amount == 0)
- {
- throw new XTMFRuntimeException(this, $"The matrix expected {dataSize}bytes but we only could get {soFar}bytes!");
- }
- soFar += amount;
+ throw new XTMFRuntimeException(this, $"The matrix expected {dataSize}bytes but we only could get {soFar}bytes!");
}
+ soFar += amount;
+ }
- ref var matrixData = ref MemoryMarshal.GetReference(matrix.Data);
- ref var rData = ref MemoryMarshal.GetReference(dataSpan);
- var matrixColumnSize = matrix.NumberOfColumns;
- for (int i = 0; i < rowSize; i++)
+ ref var matrixData = ref MemoryMarshal.GetReference(matrix.Data);
+ ref var rData = ref MemoryMarshal.GetReference(dataSpan);
+ var matrixColumnSize = matrix.NumberOfColumns;
+ for (int i = 0; i < rowSize; i++)
+ {
+ var rowIndex = categories.GetFlatIndex(rows[i]);
+ if (rowIndex < 0)
{
- var rowIndex = categories.GetFlatIndex(rows[i]);
- if (rowIndex < 0)
- {
- continue;
- }
- for (int j = 0; j < columnSize; j++)
+ continue;
+ }
+ for (int j = 0; j < columnSize; j++)
+ {
+ var columnIndex = categories.GetFlatIndex(columns[j]);
+ if (columnIndex >= 0)
{
- var columnIndex = categories.GetFlatIndex(columns[j]);
- if (columnIndex >= 0)
- {
- ref var writeTo = ref Unsafe.Add(ref matrixData, rowIndex * matrixColumnSize + columnIndex);
- writeTo = Unsafe.Add(ref rData, i * columnSize + j);
- }
+ ref var writeTo = ref Unsafe.Add(ref matrixData, rowIndex * matrixColumnSize + columnIndex);
+ writeTo = Unsafe.Add(ref rData, i * columnSize + j);
}
}
}
+ }
- private void ValidateIndexes(BinaryReader reader, Categories categories)
+ private void ValidateIndexes(BinaryReader reader, Categories categories)
+ {
+ var length = categories.Count;
+ for (int i = 0; i < length; i++)
{
- var length = categories.Count;
- for (int i = 0; i < length; i++)
+ var index = reader.ReadInt32();
+ if (index != categories.GetSparseIndex(i))
{
- var index = reader.ReadInt32();
- if(index != categories.GetSparseIndex(i))
- {
- throw new XTMFRuntimeException(this, $"The matrix file has an index of {index} where we were expecting an index of {categories.GetSparseIndex(i)}!");
- }
+ throw new XTMFRuntimeException(this, $"The matrix file has an index of {index} where we were expecting an index of {categories.GetSparseIndex(i)}!");
}
}
}
}
+
diff --git a/src/TMG-Framework/Loading/LoadVectorFromCSV.cs b/src/TMG-Framework/Loading/LoadVectorFromCSV.cs
index 50c13df..338b12d 100644
--- a/src/TMG-Framework/Loading/LoadVectorFromCSV.cs
+++ b/src/TMG-Framework/Loading/LoadVectorFromCSV.cs
@@ -16,62 +16,58 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
You should have received a copy of the GNU General Public License
along with TMG-Framework for XTMF2. If not, see .
*/
-using System;
-using System.Collections.Generic;
-using System.Text;
+
using TMG.Utilities;
-using XTMF2;
-namespace TMG.Loading
+namespace TMG.Loading;
+
+[Module(Name = "Load Vector From CSV", Description = "Loads a map where each row has a different sparse index.",
+ DocumentationLink = "http://tmg.utoronto.ca/doc/2.0")]
+public sealed class LoadVectorFromCSV : BaseFunction
{
- [Module(Name = "Load Vector From CSV", Description = "Loads a map where each row has a different sparse index.",
- DocumentationLink = "http://tmg.utoronto.ca/doc/2.0")]
- public sealed class LoadVectorFromCSV : BaseFunction
- {
- [SubModule(Required = true, Name = "Categories", Description = "The sparse map this vector will be shaped in.", Index = 0)]
- public IFunction Categories = null!;
+ [SubModule(Required = true, Name = "Categories", Description = "The sparse map this vector will be shaped in.", Index = 0)]
+ public IFunction Categories = null!;
- [Parameter(DefaultValue = "0", Name = "Map Column", Index = 1, Description = "The 0 indexed column containing the sparse map index.")]
- public IFunction MapColumn = null!;
+ [Parameter(DefaultValue = "0", Name = "Map Column", Index = 1, Description = "The 0 indexed column containing the sparse map index.")]
+ public IFunction MapColumn = null!;
- [Parameter(DefaultValue = "1", Name = "Data Column", Index = 2, Description = "The 0 indexed column containing the data to load index.")]
- public IFunction DataColumn = null!;
+ [Parameter(DefaultValue = "1", Name = "Data Column", Index = 2, Description = "The 0 indexed column containing the data to load index.")]
+ public IFunction DataColumn = null!;
- public override Vector Invoke(ReadStream stream)
+ public override Vector Invoke(ReadStream stream)
+ {
+ var map = Categories.Invoke();
+ var ret = new Vector(map);
+ var data = ret.Data;
+ var mapColumn = MapColumn.Invoke();
+ var dataColumn = DataColumn.Invoke();
+ if (mapColumn < 0 || dataColumn < 0)
{
- var map = Categories.Invoke();
- var ret = new Vector(map);
- var data = ret.Data;
- var mapColumn = MapColumn.Invoke();
- var dataColumn = DataColumn.Invoke();
- if(mapColumn < 0 || dataColumn < 0)
- {
- throw new XTMFRuntimeException(this, "Column indexes must be greater than or equal to zero!");
- }
- var minColumnSize = Math.Max(mapColumn, dataColumn);
- using (var reader = new CsvReader(stream, true))
+ throw new XTMFRuntimeException(this, "Column indexes must be greater than or equal to zero!");
+ }
+ var minColumnSize = Math.Max(mapColumn, dataColumn);
+ using (var reader = new CsvReader(stream, true))
+ {
+ while (reader.LoadLine(out var columns))
{
- while(reader.LoadLine(out var columns))
+ // This is strictly greater because the column size is 0 indexed
+ if (columns > minColumnSize)
{
- // This is strictly greater because the column size is 0 indexed
- if(columns > minColumnSize)
+ int flatIndex;
+ reader.Get(out int mapIndex, mapColumn);
+ reader.Get(out float dataValue, dataColumn);
+ if ((flatIndex = map.GetFlatIndex(mapIndex)) >= 0)
+ {
+ // if we know where to put it
+ data[flatIndex] = dataValue;
+ }
+ else
{
- int flatIndex;
- reader.Get(out int mapIndex, mapColumn);
- reader.Get(out float dataValue, dataColumn);
- if((flatIndex = map.GetFlatIndex(mapIndex)) >= 0)
- {
- // if we know where to put it
- data[flatIndex] = dataValue;
- }
- else
- {
- throw new XTMFRuntimeException(this, $"An invalid sparse map index was specified {mapIndex}!");
- }
+ throw new XTMFRuntimeException(this, $"An invalid sparse map index was specified {mapIndex}!");
}
}
}
- return ret;
}
+ return ret;
}
}
diff --git a/src/TMG-Framework/Processing/AST/ASTNode.cs b/src/TMG-Framework/Processing/AST/ASTNode.cs
index f1e7b84..8b3fe02 100644
--- a/src/TMG-Framework/Processing/AST/ASTNode.cs
+++ b/src/TMG-Framework/Processing/AST/ASTNode.cs
@@ -17,92 +17,87 @@ You should have received a copy of the GNU General Public License
along with XTMF. If not, see .
*/
-using System.Diagnostics.CodeAnalysis;
-using XTMF2;
-using TMG.Utilities;
+namespace TMG.Frameworks.Data.Processing.AST;
-namespace TMG.Frameworks.Data.Processing.AST
+public abstract class AstNode
{
- public abstract class AstNode
+ ///
+ /// The starting point of the node
+ ///
+ internal readonly int Start;
+
+ protected AstNode(int start)
{
- ///
- /// The starting point of the node
- ///
- internal readonly int Start;
+ Start = start;
+ }
- protected AstNode(int start)
- {
- Start = start;
- }
+ public abstract ComputationResult Evaluate(IModule[] dataSources);
- public abstract ComputationResult Evaluate(IModule[] dataSources);
+ internal abstract bool OptimizeAst(
+ ref Expression ex,
+ [NotNullWhen(false)] ref string? error);
+}
- internal abstract bool OptimizeAst(
- ref Expression ex,
- [NotNullWhen(false)] ref string? error);
- }
+public class ComputationResult
+{
+ public bool IsOdResult => OdData is not null;
- public class ComputationResult
- {
- public bool IsOdResult => OdData is not null;
+ public bool IsVectorResult => VectorData is not null;
- public bool IsVectorResult => VectorData is not null;
+ public bool Error => ErrorMessage is not null;
- public bool Error => ErrorMessage is not null;
+ public string? ErrorMessage { get; private set; }
- public string? ErrorMessage { get; private set; }
+ public bool Accumulator { get; private set; }
- public bool Accumulator { get; private set; }
+ public enum VectorDirection
+ {
+ Unassigned,
+ Horizontal,
+ Vertical
+ }
- public enum VectorDirection
- {
- Unassigned,
- Horizontal,
- Vertical
- }
+ public VectorDirection Direction { get; private set; }
- public VectorDirection Direction { get; private set; }
+ public Matrix OdData { get; }
- public Matrix OdData { get; }
+ public Vector VectorData { get; }
- public Vector VectorData { get; }
+ public float LiteralValue { get; }
- public float LiteralValue { get; }
-
- public bool IsValue => !IsOdResult && !IsVectorResult && !Error;
+ public bool IsValue => !IsOdResult && !IsVectorResult && !Error;
-// TODO: Get these warnings fixes once we have the time to do so. For now, we will just suppress them.
+ // TODO: Get these warnings fixes once we have the time to do so. For now, we will just suppress them.
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
- public ComputationResult(float value)
- {
- LiteralValue = value;
- }
-
- public ComputationResult(Matrix data, bool accumulator)
- {
- OdData = data;
- Accumulator = accumulator;
- }
-
- public ComputationResult(Vector data, bool accumulator, VectorDirection direction = VectorDirection.Unassigned)
- {
- VectorData = data;
- Accumulator = accumulator;
- Direction = direction;
- }
-
- public ComputationResult(ComputationResult res, VectorDirection direction)
- {
- OdData = res.OdData;
- LiteralValue = res.LiteralValue;
- VectorData = res.VectorData;
- Direction = direction;
- }
-
- public ComputationResult(string errorMessage)
- {
- ErrorMessage = errorMessage;
- }
- #pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
+ public ComputationResult(float value)
+ {
+ LiteralValue = value;
+ }
+
+ public ComputationResult(Matrix data, bool accumulator)
+ {
+ OdData = data;
+ Accumulator = accumulator;
+ }
+
+ public ComputationResult(Vector data, bool accumulator, VectorDirection direction = VectorDirection.Unassigned)
+ {
+ VectorData = data;
+ Accumulator = accumulator;
+ Direction = direction;
+ }
+
+ public ComputationResult(ComputationResult res, VectorDirection direction)
+ {
+ OdData = res.OdData;
+ LiteralValue = res.LiteralValue;
+ VectorData = res.VectorData;
+ Direction = direction;
+ }
+
+ public ComputationResult(string errorMessage)
+ {
+ ErrorMessage = errorMessage;
}
+#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
}
diff --git a/src/TMG-Framework/Processing/AST/Add.cs b/src/TMG-Framework/Processing/AST/Add.cs
index e1a915f..8e2a255 100644
--- a/src/TMG-Framework/Processing/AST/Add.cs
+++ b/src/TMG-Framework/Processing/AST/Add.cs
@@ -17,195 +17,193 @@ You should have received a copy of the GNU General Public License
along with XTMF. If not, see .
*/
-using System;
-using System.Diagnostics.CodeAnalysis;
using TMG.Utilities;
-namespace TMG.Frameworks.Data.Processing.AST
+namespace TMG.Frameworks.Data.Processing.AST;
+
+public class Add : BinaryExpression
{
- public class Add : BinaryExpression
+ public Add(int start) : base(start)
+ {
+
+ }
+
+ internal override bool OptimizeAst(
+ ref Expression ex,
+ [NotNullWhen(false)] ref string? error)
{
- public Add(int start) : base(start)
+ if (!base.OptimizeAst(ref ex, ref error))
+ {
+ return false;
+ }
+ if (!OptimizeFusedMultiplyAdd(ref ex, ref error)
+ || !OptimizeLiterals(ref ex, ref error))
{
+ return false;
}
+ return true;
+ }
- internal override bool OptimizeAst(
- ref Expression ex,
- [NotNullWhen(false)] ref string? error)
+ private bool OptimizeLiterals(
+ [NotNullWhen(true)] ref Expression ex,
+ [NotNullWhen(false)] ref string? error)
+ {
+ var lhs = Lhs as Literal;
+ var rhs = Rhs as Literal;
+ if (lhs != null && rhs != null)
{
- if(!base.OptimizeAst(ref ex, ref error))
- {
- return false;
- }
- if(!OptimizeFusedMultiplyAdd(ref ex, ref error)
- || !OptimizeLiterals(ref ex, ref error))
- {
-
- return false;
- }
+ ex = new Literal(Start, lhs.Value + rhs.Value);
return true;
}
+ return true;
+ }
- private bool OptimizeLiterals(
- [NotNullWhen(true)] ref Expression ex,
- [NotNullWhen(false)] ref string? error)
+ private bool OptimizeFusedMultiplyAdd(
+ ref Expression ex,
+ [NotNullWhen(false)] ref string? error)
+ {
+ var lhsMul = Lhs as Multiply;
+ var rhsMul = Rhs as Multiply;
+ if (lhsMul is not null)
{
- var lhs = Lhs as Literal;
- var rhs = Rhs as Literal;
- if(lhs != null && rhs != null)
+ ex = new FusedMultiplyAdd(Start, Rhs?.Start ?? -1)
{
- ex = new Literal(Start, lhs.Value + rhs.Value);
- return true;
- }
- return true;
+ MulLhs = lhsMul.Lhs,
+ MulRhs = lhsMul.Rhs,
+ Add = Rhs
+ };
+ }
+ else if (rhsMul != null)
+ {
+ ex = new FusedMultiplyAdd(Start, Lhs?.Start ?? -1)
+ {
+ MulLhs = rhsMul.Lhs,
+ MulRhs = rhsMul.Rhs,
+ Add = Lhs
+ };
}
+ return true;
+ }
- private bool OptimizeFusedMultiplyAdd(
- ref Expression ex,
- [NotNullWhen(false)] ref string? error)
+ public override ComputationResult Evaluate(ComputationResult lhs, ComputationResult rhs)
+ {
+ // see if we have two values, in this case we can skip doing the matrix operation
+ if (lhs.IsValue && rhs.IsValue)
+ {
+ return new ComputationResult(lhs.LiteralValue + rhs.LiteralValue);
+ }
+ // float / matrix
+ if (lhs.IsValue)
{
- var lhsMul = Lhs as Multiply;
- var rhsMul = Rhs as Multiply;
- if (lhsMul is not null)
+ if (rhs.IsVectorResult)
{
- ex = new FusedMultiplyAdd(Start, Rhs?.Start ?? -1)
- {
- MulLhs = lhsMul.Lhs,
- MulRhs = lhsMul.Rhs,
- Add = Rhs
- };
+ var retVector = rhs.Accumulator ? rhs.VectorData : new Vector(rhs.VectorData.Categories);
+ var flat = retVector.Data;
+ VectorHelper.Add(flat, rhs.VectorData.Data, lhs.LiteralValue);
+ return new ComputationResult(retVector, true);
}
- else if (rhsMul != null)
+ else
{
- ex = new FusedMultiplyAdd(Start, Lhs?.Start ?? -1)
- {
- MulLhs = rhsMul.Lhs,
- MulRhs = rhsMul.Rhs,
- Add = Lhs
- };
+ var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData.RowCategories, rhs.OdData.ColumnCategories);
+ VectorHelper.Add(retMatrix.Data, rhs.OdData.Data, lhs.LiteralValue);
+ return new ComputationResult(retMatrix, true);
}
- return true;
}
-
- public override ComputationResult Evaluate(ComputationResult lhs, ComputationResult rhs)
+ else if (rhs.IsValue)
{
- // see if we have two values, in this case we can skip doing the matrix operation
- if (lhs.IsValue && rhs.IsValue)
+ if (lhs.IsVectorResult)
{
- return new ComputationResult(lhs.LiteralValue + rhs.LiteralValue);
+ var retVector = lhs.Accumulator ? lhs.VectorData : new Vector(lhs.VectorData.Categories);
+ var flat = retVector.Data;
+ VectorHelper.Add(flat, lhs.VectorData.Data, rhs.LiteralValue);
+ return new ComputationResult(retVector, true);
}
- // float / matrix
- if (lhs.IsValue)
+ else
{
- if (rhs.IsVectorResult)
- {
- var retVector = rhs.Accumulator ? rhs.VectorData : new Vector(rhs.VectorData.Categories);
- var flat = retVector.Data;
- VectorHelper.Add(flat, rhs.VectorData.Data, lhs.LiteralValue);
- return new ComputationResult(retVector, true);
- }
- else
- {
- var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData.RowCategories, rhs.OdData.ColumnCategories);
- VectorHelper.Add(retMatrix.Data, rhs.OdData.Data, lhs.LiteralValue);
- return new ComputationResult(retMatrix, true);
- }
+ // matrix / float
+ var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData.RowCategories, lhs.OdData.ColumnCategories);
+ VectorHelper.Add(retMatrix.Data, lhs.OdData.Data, rhs.LiteralValue);
+ return new ComputationResult(retMatrix, true);
}
- else if (rhs.IsValue)
+ }
+ else
+ {
+ if (lhs.IsVectorResult || rhs.IsVectorResult)
{
- if (lhs.IsVectorResult)
+ if (lhs.IsVectorResult && rhs.IsVectorResult)
{
- var retVector = lhs.Accumulator ? lhs.VectorData : new Vector(lhs.VectorData.Categories);
- var flat = retVector.Data;
- VectorHelper.Add(flat, lhs.VectorData.Data, rhs.LiteralValue);
- return new ComputationResult(retVector, true);
- }
- else
- {
- // matrix / float
- var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData.RowCategories, lhs.OdData.ColumnCategories);
- VectorHelper.Add(retMatrix.Data, lhs.OdData.Data, rhs.LiteralValue);
- return new ComputationResult(retMatrix, true);
+ var retMatrix = lhs.Accumulator ? lhs.VectorData : (rhs.Accumulator ? rhs.VectorData : new Vector(lhs.VectorData));
+ VectorHelper.Add(retMatrix.Data, 0, lhs.VectorData.Data, 0, rhs.VectorData.Data, 0, retMatrix.Data.Length);
+ return new ComputationResult(retMatrix, true, lhs.Direction);
}
- }
- else
- {
- if (lhs.IsVectorResult || rhs.IsVectorResult)
+ else if (lhs.IsVectorResult)
{
- if (lhs.IsVectorResult && rhs.IsVectorResult)
- {
- var retMatrix = lhs.Accumulator ? lhs.VectorData : (rhs.Accumulator ? rhs.VectorData : new Vector(lhs.VectorData));
- VectorHelper.Add(retMatrix.Data, 0, lhs.VectorData.Data, 0, rhs.VectorData.Data, 0, retMatrix.Data.Length);
- return new ComputationResult(retMatrix, true, lhs.Direction);
- }
- else if (lhs.IsVectorResult)
+ var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData.RowCategories, rhs.OdData.ColumnCategories);
+ var flatLhs = lhs.VectorData.Data;
+ var rowSize = flatLhs.Length;
+ if (lhs.Direction == ComputationResult.VectorDirection.Vertical)
{
- var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData.RowCategories, rhs.OdData.ColumnCategories);
- var flatLhs = lhs.VectorData.Data;
- var rowSize = flatLhs.Length;
- if (lhs.Direction == ComputationResult.VectorDirection.Vertical)
+ for (int i = 0; i < rowSize; i++)
{
- for (int i = 0; i < rowSize; i++)
- {
- var retRow = retMatrix.GetRow(i);
- var rhsRow = rhs.OdData.GetRow(i);
- VectorHelper.Add(retRow, rhsRow, flatLhs[i]);
- }
+ var retRow = retMatrix.GetRow(i);
+ var rhsRow = rhs.OdData.GetRow(i);
+ VectorHelper.Add(retRow, rhsRow, flatLhs[i]);
}
- else if (lhs.Direction == ComputationResult.VectorDirection.Horizontal)
- {
- for (int i = 0; i < rowSize; i++)
- {
- var retRow = retMatrix.GetRow(i);
- var rhsRow = rhs.OdData.GetRow(i);
- VectorHelper.Add(retRow, rhsRow, flatLhs);
- }
- }
- else
+ }
+ else if (lhs.Direction == ComputationResult.VectorDirection.Horizontal)
+ {
+ for (int i = 0; i < rowSize; i++)
{
- return new ComputationResult("Unable to add vector without directionality starting at position " + (Lhs?.Start ?? -1) + "!");
+ var retRow = retMatrix.GetRow(i);
+ var rhsRow = rhs.OdData.GetRow(i);
+ VectorHelper.Add(retRow, rhsRow, flatLhs);
}
- return new ComputationResult(retMatrix, true);
}
else
{
- var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData.RowCategories, lhs.OdData.ColumnCategories);
- var flatLhs = lhs.OdData.Data;
- var flatRhs = rhs.VectorData.Data;
- var rowSize = flatRhs.Length;
- if (rhs.Direction == ComputationResult.VectorDirection.Vertical)
- {
- for (int i = 0; i < rowSize; i++)
- {
- var retRow = retMatrix.GetRow(i);
- var lhsRow = lhs.OdData.GetRow(i);
- VectorHelper.Add(retRow, lhsRow, flatRhs[i]);
- }
- }
- else if (rhs.Direction == ComputationResult.VectorDirection.Horizontal)
+ return new ComputationResult("Unable to add vector without directionality starting at position " + (Lhs?.Start ?? -1) + "!");
+ }
+ return new ComputationResult(retMatrix, true);
+ }
+ else
+ {
+ var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData.RowCategories, lhs.OdData.ColumnCategories);
+ var flatLhs = lhs.OdData.Data;
+ var flatRhs = rhs.VectorData.Data;
+ var rowSize = flatRhs.Length;
+ if (rhs.Direction == ComputationResult.VectorDirection.Vertical)
+ {
+ for (int i = 0; i < rowSize; i++)
{
- for (int i = 0; i < rowSize; i++)
- {
- var retRow = retMatrix.GetRow(i);
- var lhsRow = lhs.OdData.GetRow(i);
- VectorHelper.Add(retRow, lhsRow, flatRhs);
- }
+ var retRow = retMatrix.GetRow(i);
+ var lhsRow = lhs.OdData.GetRow(i);
+ VectorHelper.Add(retRow, lhsRow, flatRhs[i]);
}
- else
+ }
+ else if (rhs.Direction == ComputationResult.VectorDirection.Horizontal)
+ {
+ for (int i = 0; i < rowSize; i++)
{
- return new ComputationResult("Unable to add vector without directionality starting at position " + (Lhs?.Start ?? -1) + "!");
+ var retRow = retMatrix.GetRow(i);
+ var lhsRow = lhs.OdData.GetRow(i);
+ VectorHelper.Add(retRow, lhsRow, flatRhs);
}
- return new ComputationResult(retMatrix, true);
}
- }
- else
- {
- var retMatrix = lhs.Accumulator ? lhs.OdData : (rhs.Accumulator ? rhs.OdData : new Matrix(lhs.OdData));
- VectorHelper.Add(retMatrix.Data, lhs.OdData.Data, rhs.OdData.Data);
+ else
+ {
+ return new ComputationResult("Unable to add vector without directionality starting at position " + (Lhs?.Start ?? -1) + "!");
+ }
return new ComputationResult(retMatrix, true);
}
}
+ else
+ {
+ var retMatrix = lhs.Accumulator ? lhs.OdData : (rhs.Accumulator ? rhs.OdData : new Matrix(lhs.OdData));
+ VectorHelper.Add(retMatrix.Data, lhs.OdData.Data, rhs.OdData.Data);
+ return new ComputationResult(retMatrix, true);
+ }
}
}
}
+
diff --git a/src/TMG-Framework/Processing/AST/CompareAnd.cs b/src/TMG-Framework/Processing/AST/CompareAnd.cs
index 683b607..fbb9f7f 100644
--- a/src/TMG-Framework/Processing/AST/CompareAnd.cs
+++ b/src/TMG-Framework/Processing/AST/CompareAnd.cs
@@ -17,134 +17,131 @@ You should have received a copy of the GNU General Public License
along with XTMF. If not, see .
*/
-using XTMF2;
using TMG.Utilities;
-using System;
-namespace TMG.Frameworks.Data.Processing.AST
+namespace TMG.Frameworks.Data.Processing.AST;
+
+public sealed class CompareAnd : BinaryExpression
{
- public sealed class CompareAnd : BinaryExpression
+
+ public CompareAnd(int start) : base(start)
{
- public CompareAnd(int start) : base(start)
- {
+ }
+ public override ComputationResult Evaluate(ComputationResult lhs, ComputationResult rhs)
+ {
+ // see if we have two values, in this case we can skip doing the matrix operation
+ if (lhs.IsValue && rhs.IsValue)
+ {
+ // ReSharper disable once CompareOfFloatsByEqualityOperator
+ return new ComputationResult(lhs.LiteralValue == rhs.LiteralValue ? 1 : 0);
}
-
- public override ComputationResult Evaluate(ComputationResult lhs, ComputationResult rhs)
+ // float / matrix
+ if (lhs.IsValue)
{
- // see if we have two values, in this case we can skip doing the matrix operation
- if (lhs.IsValue && rhs.IsValue)
+ if (rhs.IsVectorResult)
{
- // ReSharper disable once CompareOfFloatsByEqualityOperator
- return new ComputationResult(lhs.LiteralValue == rhs.LiteralValue ? 1 : 0);
+ var retVector = rhs.Accumulator ? rhs.VectorData : new Vector(rhs.VectorData);
+ var flat = retVector.Data;
+ VectorHelper.FlagAnd(flat, lhs.LiteralValue, rhs.VectorData.Data);
+ return new ComputationResult(retVector, true, rhs.Direction);
}
- // float / matrix
- if (lhs.IsValue)
+ else
{
- if (rhs.IsVectorResult)
- {
- var retVector = rhs.Accumulator ? rhs.VectorData : new Vector(rhs.VectorData);
- var flat = retVector.Data;
- VectorHelper.FlagAnd(flat, lhs.LiteralValue, rhs.VectorData.Data);
- return new ComputationResult(retVector, true, rhs.Direction);
- }
- else
- {
- var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData);
- VectorHelper.FlagAnd(retMatrix.Data, lhs.LiteralValue, rhs.OdData.Data);
- return new ComputationResult(retMatrix, true);
- }
+ var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData);
+ VectorHelper.FlagAnd(retMatrix.Data, lhs.LiteralValue, rhs.OdData.Data);
+ return new ComputationResult(retMatrix, true);
}
- else if (rhs.IsValue)
+ }
+ else if (rhs.IsValue)
+ {
+ if (lhs.IsVectorResult)
{
- if (lhs.IsVectorResult)
- {
- var retVector = lhs.Accumulator ? lhs.VectorData : new Vector(lhs.VectorData);
- var flat = retVector.Data;
- VectorHelper.FlagAnd(flat, lhs.VectorData.Data, rhs.LiteralValue);
- return new ComputationResult(retVector, true, lhs.Direction);
- }
- else
- {
- // matrix / float
- var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
- VectorHelper.FlagAnd(retMatrix.Data, lhs.OdData.Data, rhs.LiteralValue);
- return new ComputationResult(retMatrix, true);
- }
+ var retVector = lhs.Accumulator ? lhs.VectorData : new Vector(lhs.VectorData);
+ var flat = retVector.Data;
+ VectorHelper.FlagAnd(flat, lhs.VectorData.Data, rhs.LiteralValue);
+ return new ComputationResult(retVector, true, lhs.Direction);
}
else
{
- if (lhs.IsVectorResult || rhs.IsVectorResult)
+ // matrix / float
+ var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
+ VectorHelper.FlagAnd(retMatrix.Data, lhs.OdData.Data, rhs.LiteralValue);
+ return new ComputationResult(retMatrix, true);
+ }
+ }
+ else
+ {
+ if (lhs.IsVectorResult || rhs.IsVectorResult)
+ {
+ if (lhs.IsVectorResult && rhs.IsVectorResult)
{
- if (lhs.IsVectorResult && rhs.IsVectorResult)
- {
- var retMatrix = lhs.Accumulator ? lhs.VectorData : (rhs.Accumulator ? rhs.VectorData : new Vector(lhs.VectorData));
- VectorHelper.FlagAnd(retMatrix.Data, lhs.VectorData.Data, rhs.VectorData.Data);
- return new ComputationResult(retMatrix, true, lhs.Direction);
- }
- else if (lhs.IsVectorResult)
+ var retMatrix = lhs.Accumulator ? lhs.VectorData : (rhs.Accumulator ? rhs.VectorData : new Vector(lhs.VectorData));
+ VectorHelper.FlagAnd(retMatrix.Data, lhs.VectorData.Data, rhs.VectorData.Data);
+ return new ComputationResult(retMatrix, true, lhs.Direction);
+ }
+ else if (lhs.IsVectorResult)
+ {
+ var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData);
+ var flatRet = retMatrix.Data;
+ var flatRhs = rhs.OdData.Data;
+ var flatLhs = lhs.VectorData.Data;
+ var rowSize = flatLhs.Length;
+ if (lhs.Direction == ComputationResult.VectorDirection.Vertical)
{
- var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData);
- var flatRet = retMatrix.Data;
- var flatRhs = rhs.OdData.Data;
- var flatLhs = lhs.VectorData.Data;
- var rowSize = flatLhs.Length;
- if (lhs.Direction == ComputationResult.VectorDirection.Vertical)
+ for (int i = 0; i < rowSize; i++)
{
- for (int i = 0; i < rowSize; i++)
- {
- VectorHelper.FlagAnd(retMatrix.GetRow(i), flatLhs[i], flatRhs.Slice(i * rowSize, rowSize));
- }
+ VectorHelper.FlagAnd(retMatrix.GetRow(i), flatLhs[i], flatRhs.Slice(i * rowSize, rowSize));
}
- else if (lhs.Direction == ComputationResult.VectorDirection.Horizontal)
- {
- for (int i = 0; i < rowSize; i++)
- {
- VectorHelper.FlagAnd(retMatrix.GetRow(i), flatLhs, flatRhs.Slice(i * rowSize, rowSize));
- }
- }
- else
+ }
+ else if (lhs.Direction == ComputationResult.VectorDirection.Horizontal)
+ {
+ for (int i = 0; i < rowSize; i++)
{
- return new ComputationResult("Unable to add vector without directionality starting at position " + (Lhs?.Start ?? -1) + "!");
+ VectorHelper.FlagAnd(retMatrix.GetRow(i), flatLhs, flatRhs.Slice(i * rowSize, rowSize));
}
- return new ComputationResult(retMatrix, true);
}
else
{
- var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
- var flatRet = retMatrix.Data;
- var flatLhs = lhs.OdData.Data;
- var flatRhs = rhs.VectorData.Data;
- var rowSize = flatRhs.Length;
- if (rhs.Direction == ComputationResult.VectorDirection.Vertical)
- {
- for (int i = 0; i < rowSize; i++)
- {
- VectorHelper.FlagAnd(retMatrix.GetRow(i), flatRhs[i], flatLhs.Slice(i * rowSize, rowSize));
- }
- }
- else if (rhs.Direction == ComputationResult.VectorDirection.Horizontal)
+ return new ComputationResult("Unable to add vector without directionality starting at position " + (Lhs?.Start ?? -1) + "!");
+ }
+ return new ComputationResult(retMatrix, true);
+ }
+ else
+ {
+ var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
+ var flatRet = retMatrix.Data;
+ var flatLhs = lhs.OdData.Data;
+ var flatRhs = rhs.VectorData.Data;
+ var rowSize = flatRhs.Length;
+ if (rhs.Direction == ComputationResult.VectorDirection.Vertical)
+ {
+ for (int i = 0; i < rowSize; i++)
{
- for (int i = 0; i < rowSize; i++)
- {
- VectorHelper.FlagAnd(retMatrix.GetRow(i), flatRhs, flatLhs.Slice(i * rowSize, rowSize));
- }
+ VectorHelper.FlagAnd(retMatrix.GetRow(i), flatRhs[i], flatLhs.Slice(i * rowSize, rowSize));
}
- else
+ }
+ else if (rhs.Direction == ComputationResult.VectorDirection.Horizontal)
+ {
+ for (int i = 0; i < rowSize; i++)
{
- return new ComputationResult("Unable to add vector without directionality starting at position " + (Lhs?.Start ?? -1) + "!");
+ VectorHelper.FlagAnd(retMatrix.GetRow(i), flatRhs, flatLhs.Slice(i * rowSize, rowSize));
}
- return new ComputationResult(retMatrix, true);
}
- }
- else
- {
- var retMatrix = lhs.Accumulator ? lhs.OdData : (rhs.Accumulator ? rhs.OdData : new Matrix(lhs.OdData));
- VectorHelper.FlagAnd(retMatrix.Data, lhs.OdData.Data, rhs.OdData.Data);
+ else
+ {
+ return new ComputationResult("Unable to add vector without directionality starting at position " + (Lhs?.Start ?? -1) + "!");
+ }
return new ComputationResult(retMatrix, true);
}
}
+ else
+ {
+ var retMatrix = lhs.Accumulator ? lhs.OdData : (rhs.Accumulator ? rhs.OdData : new Matrix(lhs.OdData));
+ VectorHelper.FlagAnd(retMatrix.Data, lhs.OdData.Data, rhs.OdData.Data);
+ return new ComputationResult(retMatrix, true);
+ }
}
}
}
diff --git a/src/TMG-Framework/Processing/AST/CompareEqual.cs b/src/TMG-Framework/Processing/AST/CompareEqual.cs
index 6d265d8..55f7127 100644
--- a/src/TMG-Framework/Processing/AST/CompareEqual.cs
+++ b/src/TMG-Framework/Processing/AST/CompareEqual.cs
@@ -17,133 +17,130 @@ You should have received a copy of the GNU General Public License
along with XTMF. If not, see .
*/
-using XTMF2;
using TMG.Utilities;
-using System;
-namespace TMG.Frameworks.Data.Processing.AST
+namespace TMG.Frameworks.Data.Processing.AST;
+
+public sealed class CompareEqual : BinaryExpression
{
- public sealed class CompareEqual : BinaryExpression
+ public CompareEqual(int start) : base(start)
{
- public CompareEqual(int start) : base(start)
- {
- }
+ }
- public override ComputationResult Evaluate(ComputationResult lhs, ComputationResult rhs)
+ public override ComputationResult Evaluate(ComputationResult lhs, ComputationResult rhs)
+ {
+ // see if we have two values, in this case we can skip doing the matrix operation
+ if (lhs.IsValue && rhs.IsValue)
+ {
+ // ReSharper disable once CompareOfFloatsByEqualityOperator
+ return new ComputationResult(lhs.LiteralValue == rhs.LiteralValue ? 1 : 0);
+ }
+ // float / matrix
+ if (lhs.IsValue)
{
- // see if we have two values, in this case we can skip doing the matrix operation
- if (lhs.IsValue && rhs.IsValue)
+ if (rhs.IsVectorResult)
{
- // ReSharper disable once CompareOfFloatsByEqualityOperator
- return new ComputationResult(lhs.LiteralValue == rhs.LiteralValue ? 1 : 0);
+ var retVector = rhs.Accumulator ? rhs.VectorData : new Vector(rhs.VectorData);
+ var flat = retVector.Data;
+ VectorHelper.FlagIfEquals(flat, lhs.LiteralValue, rhs.VectorData.Data);
+ return new ComputationResult(retVector, true, rhs.Direction);
}
- // float / matrix
- if (lhs.IsValue)
+ else
{
- if (rhs.IsVectorResult)
- {
- var retVector = rhs.Accumulator ? rhs.VectorData : new Vector(rhs.VectorData);
- var flat = retVector.Data;
- VectorHelper.FlagIfEquals(flat, lhs.LiteralValue, rhs.VectorData.Data);
- return new ComputationResult(retVector, true, rhs.Direction);
- }
- else
- {
- var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData);
- VectorHelper.FlagIfEquals(retMatrix.Data, lhs.LiteralValue, rhs.OdData.Data);
- return new ComputationResult(retMatrix, true);
- }
+ var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData);
+ VectorHelper.FlagIfEquals(retMatrix.Data, lhs.LiteralValue, rhs.OdData.Data);
+ return new ComputationResult(retMatrix, true);
}
- else if (rhs.IsValue)
+ }
+ else if (rhs.IsValue)
+ {
+ if (lhs.IsVectorResult)
{
- if (lhs.IsVectorResult)
- {
- var retVector = lhs.Accumulator ? lhs.VectorData : new Vector(lhs.VectorData);
- var flat = retVector.Data;
- VectorHelper.FlagIfEquals(flat, lhs.VectorData.Data, rhs.LiteralValue);
- return new ComputationResult(retVector, true, lhs.Direction);
- }
- else
- {
- // matrix / float
- var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
- VectorHelper.FlagIfEquals(retMatrix.Data, lhs.OdData.Data, rhs.LiteralValue);
- return new ComputationResult(retMatrix, true);
- }
+ var retVector = lhs.Accumulator ? lhs.VectorData : new Vector(lhs.VectorData);
+ var flat = retVector.Data;
+ VectorHelper.FlagIfEquals(flat, lhs.VectorData.Data, rhs.LiteralValue);
+ return new ComputationResult(retVector, true, lhs.Direction);
}
else
{
- if (lhs.IsVectorResult || rhs.IsVectorResult)
+ // matrix / float
+ var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
+ VectorHelper.FlagIfEquals(retMatrix.Data, lhs.OdData.Data, rhs.LiteralValue);
+ return new ComputationResult(retMatrix, true);
+ }
+ }
+ else
+ {
+ if (lhs.IsVectorResult || rhs.IsVectorResult)
+ {
+ if (lhs.IsVectorResult && rhs.IsVectorResult)
{
- if (lhs.IsVectorResult && rhs.IsVectorResult)
- {
- var retMatrix = lhs.Accumulator ? lhs.VectorData : (rhs.Accumulator ? rhs.VectorData : new Vector(lhs.VectorData));
- VectorHelper.FlagIfEquals(retMatrix.Data, lhs.VectorData.Data, rhs.VectorData.Data);
- return new ComputationResult(retMatrix, true, lhs.Direction);
- }
- else if (lhs.IsVectorResult)
+ var retMatrix = lhs.Accumulator ? lhs.VectorData : (rhs.Accumulator ? rhs.VectorData : new Vector(lhs.VectorData));
+ VectorHelper.FlagIfEquals(retMatrix.Data, lhs.VectorData.Data, rhs.VectorData.Data);
+ return new ComputationResult(retMatrix, true, lhs.Direction);
+ }
+ else if (lhs.IsVectorResult)
+ {
+ var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData);
+ var flatRet = retMatrix.Data;
+ var flatRhs = rhs.OdData.Data;
+ var flatLhs = lhs.VectorData.Data;
+ var rowSize = flatLhs.Length;
+ if (lhs.Direction == ComputationResult.VectorDirection.Vertical)
{
- var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData);
- var flatRet = retMatrix.Data;
- var flatRhs = rhs.OdData.Data;
- var flatLhs = lhs.VectorData.Data;
- var rowSize = flatLhs.Length;
- if (lhs.Direction == ComputationResult.VectorDirection.Vertical)
+ for (int i = 0; i < rowSize; i++)
{
- for (int i = 0; i < rowSize; i++)
- {
- VectorHelper.FlagIfEquals(retMatrix.Data.Slice(i * rowSize, rowSize), flatLhs[i], flatRhs.Slice(i * rowSize, rowSize));
- }
+ VectorHelper.FlagIfEquals(retMatrix.Data.Slice(i * rowSize, rowSize), flatLhs[i], flatRhs.Slice(i * rowSize, rowSize));
}
- else if (lhs.Direction == ComputationResult.VectorDirection.Horizontal)
- {
- for (int i = 0; i < rowSize; i++)
- {
- VectorHelper.FlagIfEquals(retMatrix.Data.Slice(i * rowSize, rowSize), flatLhs, flatRhs.Slice(i * rowSize, rowSize));
- }
- }
- else
+ }
+ else if (lhs.Direction == ComputationResult.VectorDirection.Horizontal)
+ {
+ for (int i = 0; i < rowSize; i++)
{
- return new ComputationResult("Unable to compare equal a vector without directionality to a matrix starting at position " + (Lhs?.Start ?? -1) + "!");
+ VectorHelper.FlagIfEquals(retMatrix.Data.Slice(i * rowSize, rowSize), flatLhs, flatRhs.Slice(i * rowSize, rowSize));
}
- return new ComputationResult(retMatrix, true);
}
else
{
- var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
- var flatRet = retMatrix.Data;
- var flatLhs = lhs.OdData.Data;
- var flatRhs = rhs.VectorData.Data;
- var rowSize = flatRhs.Length;
- if (rhs.Direction == ComputationResult.VectorDirection.Vertical)
- {
- for (int i = 0; i < rowSize; i++)
- {
- VectorHelper.FlagIfEquals(retMatrix.GetRow(i), flatLhs.Slice(i * rowSize, rowSize), flatRhs[i]);
- }
- }
- else if (rhs.Direction == ComputationResult.VectorDirection.Horizontal)
+ return new ComputationResult("Unable to compare equal a vector without directionality to a matrix starting at position " + (Lhs?.Start ?? -1) + "!");
+ }
+ return new ComputationResult(retMatrix, true);
+ }
+ else
+ {
+ var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
+ var flatRet = retMatrix.Data;
+ var flatLhs = lhs.OdData.Data;
+ var flatRhs = rhs.VectorData.Data;
+ var rowSize = flatRhs.Length;
+ if (rhs.Direction == ComputationResult.VectorDirection.Vertical)
+ {
+ for (int i = 0; i < rowSize; i++)
{
- for (int i = 0; i < rowSize; i++)
- {
- VectorHelper.FlagIfEquals(retMatrix.GetRow(i), flatLhs.Slice(i * rowSize, rowSize), flatRhs);
- }
+ VectorHelper.FlagIfEquals(retMatrix.GetRow(i), flatLhs.Slice(i * rowSize, rowSize), flatRhs[i]);
}
- else
+ }
+ else if (rhs.Direction == ComputationResult.VectorDirection.Horizontal)
+ {
+ for (int i = 0; i < rowSize; i++)
{
- return new ComputationResult("Unable to compare equal a vector without directionality to a matrix starting at position " + (Lhs?.Start ?? -1) + "!");
+ VectorHelper.FlagIfEquals(retMatrix.GetRow(i), flatLhs.Slice(i * rowSize, rowSize), flatRhs);
}
- return new ComputationResult(retMatrix, true);
}
- }
- else
- {
- var retMatrix = lhs.Accumulator ? lhs.OdData : (rhs.Accumulator ? rhs.OdData : new Matrix(lhs.OdData));
- VectorHelper.FlagIfEquals(retMatrix.Data, lhs.OdData.Data, rhs.OdData.Data);
+ else
+ {
+ return new ComputationResult("Unable to compare equal a vector without directionality to a matrix starting at position " + (Lhs?.Start ?? -1) + "!");
+ }
return new ComputationResult(retMatrix, true);
}
}
+ else
+ {
+ var retMatrix = lhs.Accumulator ? lhs.OdData : (rhs.Accumulator ? rhs.OdData : new Matrix(lhs.OdData));
+ VectorHelper.FlagIfEquals(retMatrix.Data, lhs.OdData.Data, rhs.OdData.Data);
+ return new ComputationResult(retMatrix, true);
+ }
}
}
}
diff --git a/src/TMG-Framework/Processing/AST/CompareGreaterThan.cs b/src/TMG-Framework/Processing/AST/CompareGreaterThan.cs
index cdfb74f..93ca14a 100644
--- a/src/TMG-Framework/Processing/AST/CompareGreaterThan.cs
+++ b/src/TMG-Framework/Processing/AST/CompareGreaterThan.cs
@@ -17,132 +17,129 @@ You should have received a copy of the GNU General Public License
along with XTMF. If not, see .
*/
-using XTMF2;
using TMG.Utilities;
-using System;
-namespace TMG.Frameworks.Data.Processing.AST
+namespace TMG.Frameworks.Data.Processing.AST;
+
+public sealed class CompareGreaterThan : BinaryExpression
{
- public sealed class CompareGreaterThan : BinaryExpression
+ public CompareGreaterThan(int start) : base(start)
{
- public CompareGreaterThan(int start) : base(start)
- {
- }
+ }
- public override ComputationResult Evaluate(ComputationResult lhs, ComputationResult rhs)
+ public override ComputationResult Evaluate(ComputationResult lhs, ComputationResult rhs)
+ {
+ // see if we have two values, in this case we can skip doing the matrix operation
+ if (lhs.IsValue && rhs.IsValue)
+ {
+ return new ComputationResult(lhs.LiteralValue > rhs.LiteralValue ? 1 : 0);
+ }
+ // float / matrix
+ if (lhs.IsValue)
{
- // see if we have two values, in this case we can skip doing the matrix operation
- if (lhs.IsValue && rhs.IsValue)
+ if (rhs.IsVectorResult)
{
- return new ComputationResult(lhs.LiteralValue > rhs.LiteralValue ? 1 : 0);
+ var retVector = rhs.Accumulator ? rhs.VectorData : new Vector(rhs.VectorData);
+ var flat = retVector.Data;
+ VectorHelper.FlagIfGreaterThan(flat, lhs.LiteralValue, rhs.VectorData.Data);
+ return new ComputationResult(retVector, true, rhs.Direction);
}
- // float / matrix
- if (lhs.IsValue)
+ else
{
- if (rhs.IsVectorResult)
- {
- var retVector = rhs.Accumulator ? rhs.VectorData : new Vector(rhs.VectorData);
- var flat = retVector.Data;
- VectorHelper.FlagIfGreaterThan(flat, lhs.LiteralValue, rhs.VectorData.Data);
- return new ComputationResult(retVector, true, rhs.Direction);
- }
- else
- {
- var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData);
- VectorHelper.FlagIfGreaterThan(retMatrix.Data, lhs.LiteralValue, rhs.OdData.Data);
- return new ComputationResult(retMatrix, true);
- }
+ var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData);
+ VectorHelper.FlagIfGreaterThan(retMatrix.Data, lhs.LiteralValue, rhs.OdData.Data);
+ return new ComputationResult(retMatrix, true);
}
- else if (rhs.IsValue)
+ }
+ else if (rhs.IsValue)
+ {
+ if (lhs.IsVectorResult)
{
- if (lhs.IsVectorResult)
- {
- var retVector = lhs.Accumulator ? lhs.VectorData : new Vector(lhs.VectorData);
- var flat = retVector.Data;
- VectorHelper.FlagIfGreaterThan(flat, lhs.VectorData.Data, rhs.LiteralValue);
- return new ComputationResult(retVector, true, lhs.Direction);
- }
- else
- {
- // matrix / float
- var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
- VectorHelper.FlagIfGreaterThan(retMatrix.Data, lhs.OdData.Data, rhs.LiteralValue);
- return new ComputationResult(retMatrix, true);
- }
+ var retVector = lhs.Accumulator ? lhs.VectorData : new Vector(lhs.VectorData);
+ var flat = retVector.Data;
+ VectorHelper.FlagIfGreaterThan(flat, lhs.VectorData.Data, rhs.LiteralValue);
+ return new ComputationResult(retVector, true, lhs.Direction);
}
else
{
- if (lhs.IsVectorResult || rhs.IsVectorResult)
+ // matrix / float
+ var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
+ VectorHelper.FlagIfGreaterThan(retMatrix.Data, lhs.OdData.Data, rhs.LiteralValue);
+ return new ComputationResult(retMatrix, true);
+ }
+ }
+ else
+ {
+ if (lhs.IsVectorResult || rhs.IsVectorResult)
+ {
+ if (lhs.IsVectorResult && rhs.IsVectorResult)
{
- if (lhs.IsVectorResult && rhs.IsVectorResult)
- {
- var retMatrix = lhs.Accumulator ? lhs.VectorData : (rhs.Accumulator ? rhs.VectorData : new Vector(lhs.VectorData));
- VectorHelper.FlagIfGreaterThan(retMatrix.Data, lhs.VectorData.Data, rhs.VectorData.Data);
- return new ComputationResult(retMatrix, true, lhs.Direction);
- }
- else if (lhs.IsVectorResult)
+ var retMatrix = lhs.Accumulator ? lhs.VectorData : (rhs.Accumulator ? rhs.VectorData : new Vector(lhs.VectorData));
+ VectorHelper.FlagIfGreaterThan(retMatrix.Data, lhs.VectorData.Data, rhs.VectorData.Data);
+ return new ComputationResult(retMatrix, true, lhs.Direction);
+ }
+ else if (lhs.IsVectorResult)
+ {
+ var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData);
+ var flatRet = retMatrix.Data;
+ var flatRhs = rhs.OdData.Data;
+ var flatLhs = lhs.VectorData.Data;
+ var rowSize = flatLhs.Length;
+ if (lhs.Direction == ComputationResult.VectorDirection.Vertical)
{
- var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData);
- var flatRet = retMatrix.Data;
- var flatRhs = rhs.OdData.Data;
- var flatLhs = lhs.VectorData.Data;
- var rowSize = flatLhs.Length;
- if (lhs.Direction == ComputationResult.VectorDirection.Vertical)
+ for (int i = 0; i < rowSize; i++)
{
- for (int i = 0; i < rowSize; i++)
- {
- VectorHelper.FlagIfGreaterThan(retMatrix.GetRow(i), flatLhs[i], flatRhs.Slice(i * rowSize, rowSize));
- }
+ VectorHelper.FlagIfGreaterThan(retMatrix.GetRow(i), flatLhs[i], flatRhs.Slice(i * rowSize, rowSize));
}
- else if (lhs.Direction == ComputationResult.VectorDirection.Horizontal)
- {
- for (int i = 0; i < rowSize; i++)
- {
- VectorHelper.FlagIfGreaterThan(retMatrix.GetRow(i), flatLhs, flatRhs.Slice(i * rowSize, rowSize));
- }
- }
- else
+ }
+ else if (lhs.Direction == ComputationResult.VectorDirection.Horizontal)
+ {
+ for (int i = 0; i < rowSize; i++)
{
- return new ComputationResult("Unable to add vector without directionality starting at position " + (Lhs?.Start ?? -1) + "!");
+ VectorHelper.FlagIfGreaterThan(retMatrix.GetRow(i), flatLhs, flatRhs.Slice(i * rowSize, rowSize));
}
- return new ComputationResult(retMatrix, true);
}
else
{
- var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
- var flatRet = retMatrix.Data;
- var flatLhs = lhs.OdData.Data;
- var flatRhs = rhs.VectorData.Data;
- var rowSize = flatRhs.Length;
- if (rhs.Direction == ComputationResult.VectorDirection.Vertical)
- {
- for (int i = 0; i < rowSize; i++)
- {
- VectorHelper.FlagIfGreaterThan(retMatrix.GetRow(i), flatLhs.Slice(i * rowSize, rowSize), flatRhs[i]);
- }
- }
- else if (rhs.Direction == ComputationResult.VectorDirection.Horizontal)
+ return new ComputationResult("Unable to add vector without directionality starting at position " + (Lhs?.Start ?? -1) + "!");
+ }
+ return new ComputationResult(retMatrix, true);
+ }
+ else
+ {
+ var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
+ var flatRet = retMatrix.Data;
+ var flatLhs = lhs.OdData.Data;
+ var flatRhs = rhs.VectorData.Data;
+ var rowSize = flatRhs.Length;
+ if (rhs.Direction == ComputationResult.VectorDirection.Vertical)
+ {
+ for (int i = 0; i < rowSize; i++)
{
- for (int i = 0; i < rowSize; i++)
- {
- VectorHelper.FlagIfGreaterThan(retMatrix.GetRow(i), flatLhs.Slice(i * rowSize, rowSize), flatRhs);
- }
+ VectorHelper.FlagIfGreaterThan(retMatrix.GetRow(i), flatLhs.Slice(i * rowSize, rowSize), flatRhs[i]);
}
- else
+ }
+ else if (rhs.Direction == ComputationResult.VectorDirection.Horizontal)
+ {
+ for (int i = 0; i < rowSize; i++)
{
- return new ComputationResult("Unable to add vector without directionality starting at position " + (Lhs?.Start ?? -1) + "!");
+ VectorHelper.FlagIfGreaterThan(retMatrix.GetRow(i), flatLhs.Slice(i * rowSize, rowSize), flatRhs);
}
- return new ComputationResult(retMatrix, true);
}
- }
- else
- {
- var retMatrix = lhs.Accumulator ? lhs.OdData : (rhs.Accumulator ? rhs.OdData : new Matrix(lhs.OdData));
- VectorHelper.FlagIfGreaterThan(retMatrix.Data, lhs.OdData.Data, rhs.OdData.Data);
+ else
+ {
+ return new ComputationResult("Unable to add vector without directionality starting at position " + (Lhs?.Start ?? -1) + "!");
+ }
return new ComputationResult(retMatrix, true);
}
}
+ else
+ {
+ var retMatrix = lhs.Accumulator ? lhs.OdData : (rhs.Accumulator ? rhs.OdData : new Matrix(lhs.OdData));
+ VectorHelper.FlagIfGreaterThan(retMatrix.Data, lhs.OdData.Data, rhs.OdData.Data);
+ return new ComputationResult(retMatrix, true);
+ }
}
}
}
diff --git a/src/TMG-Framework/Processing/AST/CompareGreaterThanOrEqual.cs b/src/TMG-Framework/Processing/AST/CompareGreaterThanOrEqual.cs
index 5fed622..b6ebb72 100644
--- a/src/TMG-Framework/Processing/AST/CompareGreaterThanOrEqual.cs
+++ b/src/TMG-Framework/Processing/AST/CompareGreaterThanOrEqual.cs
@@ -17,132 +17,129 @@ You should have received a copy of the GNU General Public License
along with XTMF. If not, see .
*/
-using XTMF2;
using TMG.Utilities;
-using System;
-namespace TMG.Frameworks.Data.Processing.AST
+namespace TMG.Frameworks.Data.Processing.AST;
+
+public sealed class CompareGreaterThanOrEqual : BinaryExpression
{
- public sealed class CompareGreaterThanOrEqual : BinaryExpression
+ public CompareGreaterThanOrEqual(int start) : base(start)
{
- public CompareGreaterThanOrEqual(int start) : base(start)
- {
- }
+ }
- public override ComputationResult Evaluate(ComputationResult lhs, ComputationResult rhs)
+ public override ComputationResult Evaluate(ComputationResult lhs, ComputationResult rhs)
+ {
+ // see if we have two values, in this case we can skip doing the matrix operation
+ if (lhs.IsValue && rhs.IsValue)
+ {
+ return new ComputationResult(lhs.LiteralValue >= rhs.LiteralValue ? 1 : 0);
+ }
+ // float / matrix
+ if (lhs.IsValue)
{
- // see if we have two values, in this case we can skip doing the matrix operation
- if (lhs.IsValue && rhs.IsValue)
+ if (rhs.IsVectorResult)
{
- return new ComputationResult(lhs.LiteralValue >= rhs.LiteralValue ? 1 : 0);
+ var retVector = rhs.Accumulator ? rhs.VectorData : new Vector(rhs.VectorData);
+ var flat = retVector.Data;
+ VectorHelper.FlagIfGreaterThanOrEqual(flat, lhs.LiteralValue, rhs.VectorData.Data);
+ return new ComputationResult(retVector, true, rhs.Direction);
}
- // float / matrix
- if (lhs.IsValue)
+ else
{
- if (rhs.IsVectorResult)
- {
- var retVector = rhs.Accumulator ? rhs.VectorData : new Vector(rhs.VectorData);
- var flat = retVector.Data;
- VectorHelper.FlagIfGreaterThanOrEqual(flat, lhs.LiteralValue, rhs.VectorData.Data);
- return new ComputationResult(retVector, true, rhs.Direction);
- }
- else
- {
- var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData);
- VectorHelper.FlagIfGreaterThanOrEqual(retMatrix.Data, lhs.LiteralValue, rhs.OdData.Data);
- return new ComputationResult(retMatrix, true);
- }
+ var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData);
+ VectorHelper.FlagIfGreaterThanOrEqual(retMatrix.Data, lhs.LiteralValue, rhs.OdData.Data);
+ return new ComputationResult(retMatrix, true);
}
- else if (rhs.IsValue)
+ }
+ else if (rhs.IsValue)
+ {
+ if (lhs.IsVectorResult)
{
- if (lhs.IsVectorResult)
- {
- var retVector = lhs.Accumulator ? lhs.VectorData : new Vector(lhs.VectorData);
- var flat = retVector.Data;
- VectorHelper.FlagIfGreaterThanOrEqual(flat, lhs.VectorData.Data, rhs.LiteralValue);
- return new ComputationResult(retVector, true, lhs.Direction);
- }
- else
- {
- // matrix / float
- var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
- VectorHelper.FlagIfGreaterThanOrEqual(retMatrix.Data, lhs.OdData.Data, rhs.LiteralValue);
- return new ComputationResult(retMatrix, true);
- }
+ var retVector = lhs.Accumulator ? lhs.VectorData : new Vector(lhs.VectorData);
+ var flat = retVector.Data;
+ VectorHelper.FlagIfGreaterThanOrEqual(flat, lhs.VectorData.Data, rhs.LiteralValue);
+ return new ComputationResult(retVector, true, lhs.Direction);
}
else
{
- if (lhs.IsVectorResult || rhs.IsVectorResult)
+ // matrix / float
+ var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
+ VectorHelper.FlagIfGreaterThanOrEqual(retMatrix.Data, lhs.OdData.Data, rhs.LiteralValue);
+ return new ComputationResult(retMatrix, true);
+ }
+ }
+ else
+ {
+ if (lhs.IsVectorResult || rhs.IsVectorResult)
+ {
+ if (lhs.IsVectorResult && rhs.IsVectorResult)
{
- if (lhs.IsVectorResult && rhs.IsVectorResult)
- {
- var retMatrix = lhs.Accumulator ? lhs.VectorData : (rhs.Accumulator ? rhs.VectorData : new Vector(lhs.VectorData));
- VectorHelper.FlagIfGreaterThanOrEqual(retMatrix.Data, lhs.VectorData.Data, rhs.VectorData.Data);
- return new ComputationResult(retMatrix, true, lhs.Direction);
- }
- else if (lhs.IsVectorResult)
+ var retMatrix = lhs.Accumulator ? lhs.VectorData : (rhs.Accumulator ? rhs.VectorData : new Vector(lhs.VectorData));
+ VectorHelper.FlagIfGreaterThanOrEqual(retMatrix.Data, lhs.VectorData.Data, rhs.VectorData.Data);
+ return new ComputationResult(retMatrix, true, lhs.Direction);
+ }
+ else if (lhs.IsVectorResult)
+ {
+ var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData);
+ var flatRet = retMatrix.Data;
+ var flatRhs = rhs.OdData.Data;
+ var flatLhs = lhs.VectorData.Data;
+ var rowSize = flatLhs.Length;
+ if (lhs.Direction == ComputationResult.VectorDirection.Vertical)
{
- var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData);
- var flatRet = retMatrix.Data;
- var flatRhs = rhs.OdData.Data;
- var flatLhs = lhs.VectorData.Data;
- var rowSize = flatLhs.Length;
- if (lhs.Direction == ComputationResult.VectorDirection.Vertical)
+ for (int i = 0; i < rowSize; i++)
{
- for (int i = 0; i < rowSize; i++)
- {
- VectorHelper.FlagIfGreaterThanOrEqual(retMatrix.GetRow(i), flatLhs[i], flatRhs.Slice(i * rowSize, rowSize));
- }
+ VectorHelper.FlagIfGreaterThanOrEqual(retMatrix.GetRow(i), flatLhs[i], flatRhs.Slice(i * rowSize, rowSize));
}
- else if (lhs.Direction == ComputationResult.VectorDirection.Horizontal)
- {
- for (int i = 0; i < rowSize; i++)
- {
- VectorHelper.FlagIfGreaterThanOrEqual(retMatrix.GetRow(i), flatLhs, flatRhs.Slice(i * rowSize, rowSize));
- }
- }
- else
+ }
+ else if (lhs.Direction == ComputationResult.VectorDirection.Horizontal)
+ {
+ for (int i = 0; i < rowSize; i++)
{
- return new ComputationResult("Unable to compare vector without directionality starting at position " + (Lhs?.Start ?? -1) + "!");
+ VectorHelper.FlagIfGreaterThanOrEqual(retMatrix.GetRow(i), flatLhs, flatRhs.Slice(i * rowSize, rowSize));
}
- return new ComputationResult(retMatrix, true);
}
else
{
- var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
- var flatRet = retMatrix.Data;
- var flatLhs = lhs.OdData.Data;
- var flatRhs = rhs.VectorData.Data;
- var rowSize = flatRhs.Length;
- if (rhs.Direction == ComputationResult.VectorDirection.Vertical)
- {
- for (int i = 0; i < rowSize; i++)
- {
- VectorHelper.FlagIfGreaterThanOrEqual(retMatrix.GetRow(i), flatLhs.Slice(i * rowSize, rowSize), flatRhs[i]);
- }
- }
- else if (rhs.Direction == ComputationResult.VectorDirection.Horizontal)
+ return new ComputationResult("Unable to compare vector without directionality starting at position " + (Lhs?.Start ?? -1) + "!");
+ }
+ return new ComputationResult(retMatrix, true);
+ }
+ else
+ {
+ var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
+ var flatRet = retMatrix.Data;
+ var flatLhs = lhs.OdData.Data;
+ var flatRhs = rhs.VectorData.Data;
+ var rowSize = flatRhs.Length;
+ if (rhs.Direction == ComputationResult.VectorDirection.Vertical)
+ {
+ for (int i = 0; i < rowSize; i++)
{
- for (int i = 0; i < rowSize; i++)
- {
- VectorHelper.FlagIfGreaterThanOrEqual(retMatrix.GetRow(i), flatLhs.Slice(i * rowSize, rowSize), flatRhs);
- }
+ VectorHelper.FlagIfGreaterThanOrEqual(retMatrix.GetRow(i), flatLhs.Slice(i * rowSize, rowSize), flatRhs[i]);
}
- else
+ }
+ else if (rhs.Direction == ComputationResult.VectorDirection.Horizontal)
+ {
+ for (int i = 0; i < rowSize; i++)
{
- return new ComputationResult("Unable to add vector without directionality starting at position " + (Lhs?.Start ?? -1) + "!");
+ VectorHelper.FlagIfGreaterThanOrEqual(retMatrix.GetRow(i), flatLhs.Slice(i * rowSize, rowSize), flatRhs);
}
- return new ComputationResult(retMatrix, true);
}
- }
- else
- {
- var retMatrix = lhs.Accumulator ? lhs.OdData : (rhs.Accumulator ? rhs.OdData : new Matrix(lhs.OdData));
- VectorHelper.FlagIfGreaterThanOrEqual(retMatrix.Data, lhs.OdData.Data, rhs.OdData.Data);
+ else
+ {
+ return new ComputationResult("Unable to add vector without directionality starting at position " + (Lhs?.Start ?? -1) + "!");
+ }
return new ComputationResult(retMatrix, true);
}
}
+ else
+ {
+ var retMatrix = lhs.Accumulator ? lhs.OdData : (rhs.Accumulator ? rhs.OdData : new Matrix(lhs.OdData));
+ VectorHelper.FlagIfGreaterThanOrEqual(retMatrix.Data, lhs.OdData.Data, rhs.OdData.Data);
+ return new ComputationResult(retMatrix, true);
+ }
}
}
}
diff --git a/src/TMG-Framework/Processing/AST/CompareNotEquals.cs b/src/TMG-Framework/Processing/AST/CompareNotEquals.cs
index 9139314..8406852 100644
--- a/src/TMG-Framework/Processing/AST/CompareNotEquals.cs
+++ b/src/TMG-Framework/Processing/AST/CompareNotEquals.cs
@@ -17,133 +17,130 @@ You should have received a copy of the GNU General Public License
along with XTMF. If not, see .
*/
-using XTMF2;
using TMG.Utilities;
-using System;
-namespace TMG.Frameworks.Data.Processing.AST
+namespace TMG.Frameworks.Data.Processing.AST;
+
+public sealed class CompareNotEquals : BinaryExpression
{
- public sealed class CompareNotEquals : BinaryExpression
+ public CompareNotEquals(int start) : base(start)
{
- public CompareNotEquals(int start) : base(start)
- {
- }
+ }
- public override ComputationResult Evaluate(ComputationResult lhs, ComputationResult rhs)
+ public override ComputationResult Evaluate(ComputationResult lhs, ComputationResult rhs)
+ {
+ // see if we have two values, in this case we can skip doing the matrix operation
+ if (lhs.IsValue && rhs.IsValue)
+ {
+ // ReSharper disable once CompareOfFloatsByEqualityOperator
+ return new ComputationResult(lhs.LiteralValue != rhs.LiteralValue ? 1 : 0);
+ }
+ // float / matrix
+ if (lhs.IsValue)
{
- // see if we have two values, in this case we can skip doing the matrix operation
- if (lhs.IsValue && rhs.IsValue)
+ if (rhs.IsVectorResult)
{
- // ReSharper disable once CompareOfFloatsByEqualityOperator
- return new ComputationResult(lhs.LiteralValue != rhs.LiteralValue ? 1 : 0);
+ var retVector = rhs.Accumulator ? rhs.VectorData : new Vector(rhs.VectorData);
+ var flat = retVector.Data;
+ VectorHelper.FlagIfNotEquals(flat, lhs.LiteralValue, rhs.VectorData.Data);
+ return new ComputationResult(retVector, true, rhs.Direction);
}
- // float / matrix
- if (lhs.IsValue)
+ else
{
- if (rhs.IsVectorResult)
- {
- var retVector = rhs.Accumulator ? rhs.VectorData : new Vector(rhs.VectorData);
- var flat = retVector.Data;
- VectorHelper.FlagIfNotEquals(flat, lhs.LiteralValue, rhs.VectorData.Data);
- return new ComputationResult(retVector, true, rhs.Direction);
- }
- else
- {
- var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData);
- VectorHelper.FlagIfNotEquals(retMatrix.Data, lhs.LiteralValue, rhs.OdData.Data);
- return new ComputationResult(retMatrix, true);
- }
+ var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData);
+ VectorHelper.FlagIfNotEquals(retMatrix.Data, lhs.LiteralValue, rhs.OdData.Data);
+ return new ComputationResult(retMatrix, true);
}
- else if (rhs.IsValue)
+ }
+ else if (rhs.IsValue)
+ {
+ if (lhs.IsVectorResult)
{
- if (lhs.IsVectorResult)
- {
- var retVector = lhs.Accumulator ? lhs.VectorData : new Vector(lhs.VectorData);
- var flat = retVector.Data;
- VectorHelper.FlagIfNotEquals(flat, lhs.VectorData.Data, rhs.LiteralValue);
- return new ComputationResult(retVector, true, lhs.Direction);
- }
- else
- {
- // matrix / float
- var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
- VectorHelper.FlagIfNotEquals(retMatrix.Data, lhs.OdData.Data, rhs.LiteralValue);
- return new ComputationResult(retMatrix, true);
- }
+ var retVector = lhs.Accumulator ? lhs.VectorData : new Vector(lhs.VectorData);
+ var flat = retVector.Data;
+ VectorHelper.FlagIfNotEquals(flat, lhs.VectorData.Data, rhs.LiteralValue);
+ return new ComputationResult(retVector, true, lhs.Direction);
}
else
{
- if (lhs.IsVectorResult || rhs.IsVectorResult)
+ // matrix / float
+ var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
+ VectorHelper.FlagIfNotEquals(retMatrix.Data, lhs.OdData.Data, rhs.LiteralValue);
+ return new ComputationResult(retMatrix, true);
+ }
+ }
+ else
+ {
+ if (lhs.IsVectorResult || rhs.IsVectorResult)
+ {
+ if (lhs.IsVectorResult && rhs.IsVectorResult)
{
- if (lhs.IsVectorResult && rhs.IsVectorResult)
- {
- var retMatrix = lhs.Accumulator ? lhs.VectorData : (rhs.Accumulator ? rhs.VectorData : new Vector(lhs.VectorData));
- VectorHelper.FlagIfNotEquals(retMatrix.Data, lhs.VectorData.Data, rhs.VectorData.Data);
- return new ComputationResult(retMatrix, true, lhs.Direction);
- }
- else if (lhs.IsVectorResult)
+ var retMatrix = lhs.Accumulator ? lhs.VectorData : (rhs.Accumulator ? rhs.VectorData : new Vector(lhs.VectorData));
+ VectorHelper.FlagIfNotEquals(retMatrix.Data, lhs.VectorData.Data, rhs.VectorData.Data);
+ return new ComputationResult(retMatrix, true, lhs.Direction);
+ }
+ else if (lhs.IsVectorResult)
+ {
+ var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData);
+ var flatRet = retMatrix.Data;
+ var flatRhs = rhs.OdData.Data;
+ var flatLhs = lhs.VectorData.Data;
+ var rowSize = flatLhs.Length;
+ if (lhs.Direction == ComputationResult.VectorDirection.Vertical)
{
- var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData);
- var flatRet = retMatrix.Data;
- var flatRhs = rhs.OdData.Data;
- var flatLhs = lhs.VectorData.Data;
- var rowSize = flatLhs.Length;
- if (lhs.Direction == ComputationResult.VectorDirection.Vertical)
+ for (int i = 0; i < rowSize; i++)
{
- for (int i = 0; i < rowSize; i++)
- {
- VectorHelper.FlagIfNotEquals(retMatrix.GetRow(i), flatLhs[i], flatRhs.Slice(i * rowSize, rowSize));
- }
+ VectorHelper.FlagIfNotEquals(retMatrix.GetRow(i), flatLhs[i], flatRhs.Slice(i * rowSize, rowSize));
}
- else if (lhs.Direction == ComputationResult.VectorDirection.Horizontal)
- {
- for (int i = 0; i < rowSize; i++)
- {
- VectorHelper.FlagIfNotEquals(retMatrix.GetRow(i), flatLhs, flatRhs.Slice(i * rowSize, rowSize));
- }
- }
- else
+ }
+ else if (lhs.Direction == ComputationResult.VectorDirection.Horizontal)
+ {
+ for (int i = 0; i < rowSize; i++)
{
- return new ComputationResult("Unable to add vector without directionality starting at position " + (Lhs?.Start ?? -1) + "!");
+ VectorHelper.FlagIfNotEquals(retMatrix.GetRow(i), flatLhs, flatRhs.Slice(i * rowSize, rowSize));
}
- return new ComputationResult(retMatrix, true);
}
else
{
- var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
- var flatRet = retMatrix.Data;
- var flatLhs = lhs.OdData.Data;
- var flatRhs = rhs.VectorData.Data;
- var rowSize = flatRhs.Length;
- if (rhs.Direction == ComputationResult.VectorDirection.Vertical)
- {
- for (int i = 0; i < rowSize; i++)
- {
- VectorHelper.FlagIfNotEquals(retMatrix.GetRow(i), flatLhs.Slice(i * rowSize, rowSize), flatRhs[i]);
- }
- }
- else if (rhs.Direction == ComputationResult.VectorDirection.Horizontal)
+ return new ComputationResult("Unable to add vector without directionality starting at position " + (Lhs?.Start ?? -1) + "!");
+ }
+ return new ComputationResult(retMatrix, true);
+ }
+ else
+ {
+ var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
+ var flatRet = retMatrix.Data;
+ var flatLhs = lhs.OdData.Data;
+ var flatRhs = rhs.VectorData.Data;
+ var rowSize = flatRhs.Length;
+ if (rhs.Direction == ComputationResult.VectorDirection.Vertical)
+ {
+ for (int i = 0; i < rowSize; i++)
{
- for (int i = 0; i < rowSize; i++)
- {
- VectorHelper.FlagIfNotEquals(retMatrix.GetRow(i), flatLhs.Slice(i * rowSize, rowSize), flatRhs);
- }
+ VectorHelper.FlagIfNotEquals(retMatrix.GetRow(i), flatLhs.Slice(i * rowSize, rowSize), flatRhs[i]);
}
- else
+ }
+ else if (rhs.Direction == ComputationResult.VectorDirection.Horizontal)
+ {
+ for (int i = 0; i < rowSize; i++)
{
- return new ComputationResult("Unable to add vector without directionality starting at position " + (Lhs?.Start ?? -1) + "!");
+ VectorHelper.FlagIfNotEquals(retMatrix.GetRow(i), flatLhs.Slice(i * rowSize, rowSize), flatRhs);
}
- return new ComputationResult(retMatrix, true);
}
- }
- else
- {
- var retMatrix = lhs.Accumulator ? lhs.OdData : (rhs.Accumulator ? rhs.OdData : new Matrix(lhs.OdData));
- VectorHelper.FlagIfNotEquals(retMatrix.Data, lhs.OdData.Data, rhs.OdData.Data);
+ else
+ {
+ return new ComputationResult("Unable to add vector without directionality starting at position " + (Lhs?.Start ?? -1) + "!");
+ }
return new ComputationResult(retMatrix, true);
}
}
+ else
+ {
+ var retMatrix = lhs.Accumulator ? lhs.OdData : (rhs.Accumulator ? rhs.OdData : new Matrix(lhs.OdData));
+ VectorHelper.FlagIfNotEquals(retMatrix.Data, lhs.OdData.Data, rhs.OdData.Data);
+ return new ComputationResult(retMatrix, true);
+ }
}
}
}
diff --git a/src/TMG-Framework/Processing/AST/CompareOr.cs b/src/TMG-Framework/Processing/AST/CompareOr.cs
index ddf2b19..9b303a6 100644
--- a/src/TMG-Framework/Processing/AST/CompareOr.cs
+++ b/src/TMG-Framework/Processing/AST/CompareOr.cs
@@ -17,134 +17,131 @@ You should have received a copy of the GNU General Public License
along with XTMF. If not, see .
*/
-using XTMF2;
using TMG.Utilities;
-using System;
-namespace TMG.Frameworks.Data.Processing.AST
+namespace TMG.Frameworks.Data.Processing.AST;
+
+public sealed class CompareOr : BinaryExpression
{
- public sealed class CompareOr : BinaryExpression
+
+ public CompareOr(int start) : base(start)
{
- public CompareOr(int start) : base(start)
- {
+ }
+ public override ComputationResult Evaluate(ComputationResult lhs, ComputationResult rhs)
+ {
+ // see if we have two values, in this case we can skip doing the matrix operation
+ if (lhs.IsValue && rhs.IsValue)
+ {
+ // ReSharper disable once CompareOfFloatsByEqualityOperator
+ return new ComputationResult(lhs.LiteralValue == rhs.LiteralValue ? 1 : 0);
}
-
- public override ComputationResult Evaluate(ComputationResult lhs, ComputationResult rhs)
+ // float / matrix
+ if (lhs.IsValue)
{
- // see if we have two values, in this case we can skip doing the matrix operation
- if (lhs.IsValue && rhs.IsValue)
+ if (rhs.IsVectorResult)
{
- // ReSharper disable once CompareOfFloatsByEqualityOperator
- return new ComputationResult(lhs.LiteralValue == rhs.LiteralValue ? 1 : 0);
+ var retVector = rhs.Accumulator ? rhs.VectorData : new Vector(rhs.VectorData);
+ var flat = retVector.Data;
+ VectorHelper.FlagOr(flat, lhs.LiteralValue, rhs.VectorData.Data);
+ return new ComputationResult(retVector, true, rhs.Direction);
}
- // float / matrix
- if (lhs.IsValue)
+ else
{
- if (rhs.IsVectorResult)
- {
- var retVector = rhs.Accumulator ? rhs.VectorData : new Vector(rhs.VectorData);
- var flat = retVector.Data;
- VectorHelper.FlagOr(flat, lhs.LiteralValue, rhs.VectorData.Data);
- return new ComputationResult(retVector, true, rhs.Direction);
- }
- else
- {
- var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData);
- VectorHelper.FlagOr(retMatrix.Data, lhs.LiteralValue, rhs.OdData.Data);
- return new ComputationResult(retMatrix, true);
- }
+ var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData);
+ VectorHelper.FlagOr(retMatrix.Data, lhs.LiteralValue, rhs.OdData.Data);
+ return new ComputationResult(retMatrix, true);
}
- else if (rhs.IsValue)
+ }
+ else if (rhs.IsValue)
+ {
+ if (lhs.IsVectorResult)
{
- if (lhs.IsVectorResult)
- {
- var retVector = lhs.Accumulator ? lhs.VectorData : new Vector(lhs.VectorData);
- var flat = retVector.Data;
- VectorHelper.FlagOr(flat, lhs.VectorData.Data, rhs.LiteralValue);
- return new ComputationResult(retVector, true, lhs.Direction);
- }
- else
- {
- // matrix / float
- var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
- VectorHelper.FlagOr(retMatrix.Data, lhs.OdData.Data, rhs.LiteralValue);
- return new ComputationResult(retMatrix, true);
- }
+ var retVector = lhs.Accumulator ? lhs.VectorData : new Vector(lhs.VectorData);
+ var flat = retVector.Data;
+ VectorHelper.FlagOr(flat, lhs.VectorData.Data, rhs.LiteralValue);
+ return new ComputationResult(retVector, true, lhs.Direction);
}
else
{
- if (lhs.IsVectorResult || rhs.IsVectorResult)
+ // matrix / float
+ var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
+ VectorHelper.FlagOr(retMatrix.Data, lhs.OdData.Data, rhs.LiteralValue);
+ return new ComputationResult(retMatrix, true);
+ }
+ }
+ else
+ {
+ if (lhs.IsVectorResult || rhs.IsVectorResult)
+ {
+ if (lhs.IsVectorResult && rhs.IsVectorResult)
{
- if (lhs.IsVectorResult && rhs.IsVectorResult)
- {
- var retMatrix = lhs.Accumulator ? lhs.VectorData : (rhs.Accumulator ? rhs.VectorData : new Vector(lhs.VectorData));
- VectorHelper.FlagOr(retMatrix.Data, lhs.VectorData.Data, rhs.VectorData.Data);
- return new ComputationResult(retMatrix, true, lhs.Direction);
- }
- else if (lhs.IsVectorResult)
+ var retMatrix = lhs.Accumulator ? lhs.VectorData : (rhs.Accumulator ? rhs.VectorData : new Vector(lhs.VectorData));
+ VectorHelper.FlagOr(retMatrix.Data, lhs.VectorData.Data, rhs.VectorData.Data);
+ return new ComputationResult(retMatrix, true, lhs.Direction);
+ }
+ else if (lhs.IsVectorResult)
+ {
+ var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData);
+ var flatRet = retMatrix.Data;
+ var flatRhs = rhs.OdData.Data;
+ var flatLhs = lhs.VectorData.Data;
+ var rowSize = flatLhs.Length;
+ if (lhs.Direction == ComputationResult.VectorDirection.Vertical)
{
- var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData);
- var flatRet = retMatrix.Data;
- var flatRhs = rhs.OdData.Data;
- var flatLhs = lhs.VectorData.Data;
- var rowSize = flatLhs.Length;
- if (lhs.Direction == ComputationResult.VectorDirection.Vertical)
+ for (int i = 0; i < rowSize; i++)
{
- for (int i = 0; i < rowSize; i++)
- {
- VectorHelper.FlagOr(retMatrix.GetRow(i), flatLhs[i], flatRhs.Slice(i * rowSize, rowSize));
- }
+ VectorHelper.FlagOr(retMatrix.GetRow(i), flatLhs[i], flatRhs.Slice(i * rowSize, rowSize));
}
- else if (lhs.Direction == ComputationResult.VectorDirection.Horizontal)
- {
- for (int i = 0; i < rowSize; i++)
- {
- VectorHelper.FlagOr(retMatrix.GetRow(i), flatLhs, flatRhs.Slice(i * rowSize, rowSize));
- }
- }
- else
+ }
+ else if (lhs.Direction == ComputationResult.VectorDirection.Horizontal)
+ {
+ for (int i = 0; i < rowSize; i++)
{
- return new ComputationResult("Unable to add vector without directionality starting at position " + (Lhs?.Start ?? -1) + "!");
+ VectorHelper.FlagOr(retMatrix.GetRow(i), flatLhs, flatRhs.Slice(i * rowSize, rowSize));
}
- return new ComputationResult(retMatrix, true);
}
else
{
- var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
- var flatRet = retMatrix.Data;
- var flatLhs = lhs.OdData.Data;
- var flatRhs = rhs.VectorData.Data;
- var rowSize = flatRhs.Length;
- if (rhs.Direction == ComputationResult.VectorDirection.Vertical)
- {
- for (int i = 0; i < rowSize; i++)
- {
- VectorHelper.FlagOr(retMatrix.GetRow(i), flatRhs[i], flatLhs.Slice(i * rowSize, rowSize));
- }
- }
- else if (rhs.Direction == ComputationResult.VectorDirection.Horizontal)
+ return new ComputationResult("Unable to add vector without directionality starting at position " + (Lhs?.Start ?? -1) + "!");
+ }
+ return new ComputationResult(retMatrix, true);
+ }
+ else
+ {
+ var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
+ var flatRet = retMatrix.Data;
+ var flatLhs = lhs.OdData.Data;
+ var flatRhs = rhs.VectorData.Data;
+ var rowSize = flatRhs.Length;
+ if (rhs.Direction == ComputationResult.VectorDirection.Vertical)
+ {
+ for (int i = 0; i < rowSize; i++)
{
- for (int i = 0; i < rowSize; i++)
- {
- VectorHelper.FlagOr(retMatrix.GetRow(i), flatRhs, flatLhs.Slice(i * rowSize, rowSize));
- }
+ VectorHelper.FlagOr(retMatrix.GetRow(i), flatRhs[i], flatLhs.Slice(i * rowSize, rowSize));
}
- else
+ }
+ else if (rhs.Direction == ComputationResult.VectorDirection.Horizontal)
+ {
+ for (int i = 0; i < rowSize; i++)
{
- return new ComputationResult("Unable to add vector without directionality starting at position " + (Lhs?.Start ?? -1) + "!");
+ VectorHelper.FlagOr(retMatrix.GetRow(i), flatRhs, flatLhs.Slice(i * rowSize, rowSize));
}
- return new ComputationResult(retMatrix, true);
}
- }
- else
- {
- var retMatrix = lhs.Accumulator ? lhs.OdData : (rhs.Accumulator ? rhs.OdData : new Matrix(lhs.OdData));
- VectorHelper.FlagOr(retMatrix.Data, lhs.OdData.Data, rhs.OdData.Data);
+ else
+ {
+ return new ComputationResult("Unable to add vector without directionality starting at position " + (Lhs?.Start ?? -1) + "!");
+ }
return new ComputationResult(retMatrix, true);
}
}
+ else
+ {
+ var retMatrix = lhs.Accumulator ? lhs.OdData : (rhs.Accumulator ? rhs.OdData : new Matrix(lhs.OdData));
+ VectorHelper.FlagOr(retMatrix.Data, lhs.OdData.Data, rhs.OdData.Data);
+ return new ComputationResult(retMatrix, true);
+ }
}
}
}
diff --git a/src/TMG-Framework/Processing/AST/Compiler.cs b/src/TMG-Framework/Processing/AST/Compiler.cs
index 56f269a..9196ca3 100644
--- a/src/TMG-Framework/Processing/AST/Compiler.cs
+++ b/src/TMG-Framework/Processing/AST/Compiler.cs
@@ -17,18 +17,15 @@ You should have received a copy of the GNU General Public License
along with XTMF. If not, see .
*/
-using System.Diagnostics.CodeAnalysis;
+namespace TMG.Frameworks.Data.Processing.AST;
-namespace TMG.Frameworks.Data.Processing.AST
+public static class Compiler
{
- public static class Compiler
+ public static bool Compile(string expression,
+ [NotNullWhen(true)] out Expression? ex,
+ [NotNullWhen(false)] ref string? error)
{
- public static bool Compile(string expression,
- [NotNullWhen(true)] out Expression? ex,
- [NotNullWhen(false)] ref string? error)
- {
- var buffer = expression.ToCharArray();
- return Expression.Compile(buffer, 0, buffer.Length, out ex, ref error) && Expression.Optimize(ref ex, ref error);
- }
+ var buffer = expression.ToCharArray();
+ return Expression.Compile(buffer, 0, buffer.Length, out ex, ref error) && Expression.Optimize(ref ex, ref error);
}
}
diff --git a/src/TMG-Framework/Processing/AST/Divide.cs b/src/TMG-Framework/Processing/AST/Divide.cs
index aa0fce0..c2665cd 100644
--- a/src/TMG-Framework/Processing/AST/Divide.cs
+++ b/src/TMG-Framework/Processing/AST/Divide.cs
@@ -17,165 +17,161 @@ You should have received a copy of the GNU General Public License
along with XTMF. If not, see .
*/
-using XTMF2;
using TMG.Utilities;
-using System;
-using System.Diagnostics.CodeAnalysis;
-namespace TMG.Frameworks.Data.Processing.AST
+namespace TMG.Frameworks.Data.Processing.AST;
+
+public sealed class Divide : BinaryExpression
{
- public sealed class Divide : BinaryExpression
+ public Divide(int start) : base(start)
{
- public Divide(int start) : base(start)
- {
- }
+ }
- internal override bool OptimizeAst(
- ref Expression ex,
- [NotNullWhen(false)] ref string? error)
+ internal override bool OptimizeAst(
+ ref Expression ex,
+ [NotNullWhen(false)] ref string? error)
+ {
+ if (!base.OptimizeAst(ref ex, ref error))
+ {
+ return false;
+ }
+ var lhs = Lhs as Literal;
+ var rhs = Rhs as Literal;
+ if (lhs != null && rhs != null)
+ {
+ ex = new Literal(Start, lhs.Value / rhs.Value);
+ }
+ else if (rhs != null)
{
- if (!base.OptimizeAst(ref ex, ref error))
+ // if the RHS is a literal we can replace it with a multiply instead
+ ex = new Multiply(Start)
{
- return false;
- }
- var lhs = Lhs as Literal;
- var rhs = Rhs as Literal;
- if (lhs != null && rhs != null)
+ Lhs = Lhs,
+ Rhs = new Literal(rhs.Start, 1.0f / rhs.Value)
+ };
+ }
+ return true;
+ }
+
+ public override ComputationResult Evaluate(ComputationResult lhs, ComputationResult rhs)
+ {
+ // see if we have two values, in this case we can skip doing the matrix operation
+ if (lhs.IsValue && rhs.IsValue)
+ {
+ return new ComputationResult(lhs.LiteralValue / rhs.LiteralValue);
+ }
+ // float / matrix
+ if (lhs.IsValue)
+ {
+ if (rhs.IsVectorResult)
{
- ex = new Literal(Start, lhs.Value / rhs.Value);
+ var retVector = rhs.Accumulator ? rhs.VectorData : new Vector(rhs.VectorData);
+ var flat = retVector.Data;
+ VectorHelper.Divide(flat, lhs.LiteralValue, rhs.VectorData.Data);
+ return new ComputationResult(retVector, true);
}
- else if(rhs != null)
+ else
{
- // if the RHS is a literal we can replace it with a multiply instead
- ex = new Multiply(Start)
- {
- Lhs = Lhs,
- Rhs = new Literal(rhs.Start, 1.0f / rhs.Value)
- };
+ var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData);
+ VectorHelper.Divide(retMatrix.Data, lhs.LiteralValue, rhs.OdData.Data);
+ return new ComputationResult(retMatrix, true);
}
- return true;
}
-
- public override ComputationResult Evaluate(ComputationResult lhs, ComputationResult rhs)
+ else if (rhs.IsValue)
{
- // see if we have two values, in this case we can skip doing the matrix operation
- if (lhs.IsValue && rhs.IsValue)
+ if (lhs.IsVectorResult)
{
- return new ComputationResult(lhs.LiteralValue / rhs.LiteralValue);
+ var retVector = lhs.Accumulator ? lhs.VectorData : new Vector(lhs.VectorData);
+ var flat = retVector.Data;
+ VectorHelper.Divide(flat, lhs.VectorData.Data, rhs.LiteralValue);
+ return new ComputationResult(retVector, true);
}
- // float / matrix
- if (lhs.IsValue)
+ else
{
- if (rhs.IsVectorResult)
- {
- var retVector = rhs.Accumulator ? rhs.VectorData : new Vector(rhs.VectorData);
- var flat = retVector.Data;
- VectorHelper.Divide(flat, lhs.LiteralValue, rhs.VectorData.Data);
- return new ComputationResult(retVector, true);
- }
- else
- {
- var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData);
- VectorHelper.Divide(retMatrix.Data, lhs.LiteralValue, rhs.OdData.Data);
- return new ComputationResult(retMatrix, true);
- }
+ // matrix / float
+ var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
+ VectorHelper.Divide(retMatrix.Data, lhs.OdData.Data, rhs.LiteralValue);
+ return new ComputationResult(retMatrix, true);
}
- else if (rhs.IsValue)
+ }
+ else
+ {
+ if (lhs.IsVectorResult || rhs.IsVectorResult)
{
- if (lhs.IsVectorResult)
- {
- var retVector = lhs.Accumulator ? lhs.VectorData : new Vector(lhs.VectorData);
- var flat = retVector.Data;
- VectorHelper.Divide(flat, lhs.VectorData.Data, rhs.LiteralValue);
- return new ComputationResult(retVector, true);
- }
- else
+ if (lhs.IsVectorResult && rhs.IsVectorResult)
{
- // matrix / float
- var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
- VectorHelper.Divide(retMatrix.Data, lhs.OdData.Data, rhs.LiteralValue);
- return new ComputationResult(retMatrix, true);
+ var retMatrix = lhs.Accumulator ? lhs.VectorData : (rhs.Accumulator ? rhs.VectorData : new Vector(lhs.VectorData));
+ VectorHelper.Divide(retMatrix.Data, lhs.VectorData.Data, rhs.VectorData.Data);
+ return new ComputationResult(retMatrix, true, lhs.Direction);
}
- }
- else
- {
- if (lhs.IsVectorResult || rhs.IsVectorResult)
+ else if (lhs.IsVectorResult)
{
- if (lhs.IsVectorResult && rhs.IsVectorResult)
- {
- var retMatrix = lhs.Accumulator ? lhs.VectorData : (rhs.Accumulator ? rhs.VectorData : new Vector(lhs.VectorData));
- VectorHelper.Divide(retMatrix.Data, lhs.VectorData.Data, rhs.VectorData.Data);
- return new ComputationResult(retMatrix, true, lhs.Direction);
- }
- else if (lhs.IsVectorResult)
+ var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData);
+ var flatLhs = lhs.VectorData.Data;
+ var rowSize = flatLhs.Length;
+ if (lhs.Direction == ComputationResult.VectorDirection.Vertical)
{
- var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData);
- var flatLhs = lhs.VectorData.Data;
- var rowSize = flatLhs.Length;
- if (lhs.Direction == ComputationResult.VectorDirection.Vertical)
- {
- for (int i = 0; i < rowSize; i++)
- {
- var retRow = retMatrix.GetRow(i);
- var retRight = rhs.OdData.GetRow(i);
- VectorHelper.Divide(retRow, flatLhs[i], retRight);
- }
- }
- else if (lhs.Direction == ComputationResult.VectorDirection.Horizontal)
+ for (int i = 0; i < rowSize; i++)
{
- for (int i = 0; i < rowSize; i++)
- {
- var retRow = retMatrix.GetRow(i);
- var retRight = rhs.OdData.GetRow(i);
- VectorHelper.Divide(retRow, flatLhs, retRight);
- }
+ var retRow = retMatrix.GetRow(i);
+ var retRight = rhs.OdData.GetRow(i);
+ VectorHelper.Divide(retRow, flatLhs[i], retRight);
}
- else
+ }
+ else if (lhs.Direction == ComputationResult.VectorDirection.Horizontal)
+ {
+ for (int i = 0; i < rowSize; i++)
{
- return new ComputationResult("Unable to add vector without directionality starting at position " + (Lhs?.Start ?? -1) + "!");
+ var retRow = retMatrix.GetRow(i);
+ var retRight = rhs.OdData.GetRow(i);
+ VectorHelper.Divide(retRow, flatLhs, retRight);
}
- return new ComputationResult(retMatrix, true);
}
else
{
- var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
- var flatRet = retMatrix.Data;
- var flatLhs = lhs.OdData.Data;
- var flatRhs = rhs.VectorData.Data;
- var rowSize = flatRhs.Length;
- if (rhs.Direction == ComputationResult.VectorDirection.Vertical)
- {
- for (int i = 0; i < rowSize; i++)
- {
- var retRow = retMatrix.GetRow(i);
- var retLeft = lhs.OdData.GetRow(i);
- VectorHelper.Divide(retRow, retLeft, flatRhs[i]);
- }
- }
- else if (rhs.Direction == ComputationResult.VectorDirection.Horizontal)
+ return new ComputationResult("Unable to add vector without directionality starting at position " + (Lhs?.Start ?? -1) + "!");
+ }
+ return new ComputationResult(retMatrix, true);
+ }
+ else
+ {
+ var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
+ var flatRet = retMatrix.Data;
+ var flatLhs = lhs.OdData.Data;
+ var flatRhs = rhs.VectorData.Data;
+ var rowSize = flatRhs.Length;
+ if (rhs.Direction == ComputationResult.VectorDirection.Vertical)
+ {
+ for (int i = 0; i < rowSize; i++)
{
- for (int i = 0; i < rowSize; i++)
- {
- var retRow = retMatrix.GetRow(i);
- var retLeft = lhs.OdData.GetRow(i);
- VectorHelper.Divide(retRow, retLeft, flatRhs);
- }
+ var retRow = retMatrix.GetRow(i);
+ var retLeft = lhs.OdData.GetRow(i);
+ VectorHelper.Divide(retRow, retLeft, flatRhs[i]);
}
- else
+ }
+ else if (rhs.Direction == ComputationResult.VectorDirection.Horizontal)
+ {
+ for (int i = 0; i < rowSize; i++)
{
- return new ComputationResult("Unable to add vector without directionality starting at position " + (Lhs?.Start ?? -1) + "!");
+ var retRow = retMatrix.GetRow(i);
+ var retLeft = lhs.OdData.GetRow(i);
+ VectorHelper.Divide(retRow, retLeft, flatRhs);
}
- return new ComputationResult(retMatrix, true);
}
- }
- else
- {
- var retMatrix = lhs.Accumulator ? lhs.OdData : (rhs.Accumulator ? rhs.OdData : new Matrix(lhs.OdData));
- VectorHelper.Divide(retMatrix.Data, lhs.OdData.Data, rhs.OdData.Data);
+ else
+ {
+ return new ComputationResult("Unable to add vector without directionality starting at position " + (Lhs?.Start ?? -1) + "!");
+ }
return new ComputationResult(retMatrix, true);
}
}
+ else
+ {
+ var retMatrix = lhs.Accumulator ? lhs.OdData : (rhs.Accumulator ? rhs.OdData : new Matrix(lhs.OdData));
+ VectorHelper.Divide(retMatrix.Data, lhs.OdData.Data, rhs.OdData.Data);
+ return new ComputationResult(retMatrix, true);
+ }
}
}
}
diff --git a/src/TMG-Framework/Processing/AST/Exponent.cs b/src/TMG-Framework/Processing/AST/Exponent.cs
index 92cfbe6..1d85ab8 100644
--- a/src/TMG-Framework/Processing/AST/Exponent.cs
+++ b/src/TMG-Framework/Processing/AST/Exponent.cs
@@ -16,136 +16,134 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
You should have received a copy of the GNU General Public License
along with XTMF. If not, see .
*/
-using XTMF2;
-using System;
+
using TMG.Utilities;
-namespace TMG.Frameworks.Data.Processing.AST
+namespace TMG.Frameworks.Data.Processing.AST;
+
+public sealed class Exponent : BinaryExpression
{
- public sealed class Exponent : BinaryExpression
+ public Exponent(int start) : base(start)
{
- public Exponent(int start) : base(start)
- {
- }
+ }
- public override ComputationResult Evaluate(ComputationResult lhs, ComputationResult rhs)
+ public override ComputationResult Evaluate(ComputationResult lhs, ComputationResult rhs)
+ {
+ // see if we have two values, in this case we can skip doing the matrix operation
+ if (lhs.IsValue && rhs.IsValue)
+ {
+ return new ComputationResult((float)Math.Pow(lhs.LiteralValue, rhs.LiteralValue));
+ }
+ // float / matrix
+ if (lhs.IsValue)
{
- // see if we have two values, in this case we can skip doing the matrix operation
- if (lhs.IsValue && rhs.IsValue)
+ if (rhs.IsVectorResult)
{
- return new ComputationResult((float)Math.Pow(lhs.LiteralValue, rhs.LiteralValue));
+ var retVector = rhs.Accumulator ? rhs.VectorData : new Vector(rhs.VectorData);
+ var flat = retVector.Data;
+ VectorHelper.Pow(flat, lhs.LiteralValue, rhs.VectorData.Data);
+ return new ComputationResult(retVector, true);
}
- // float / matrix
- if (lhs.IsValue)
+ else
{
- if (rhs.IsVectorResult)
- {
- var retVector = rhs.Accumulator ? rhs.VectorData : new Vector(rhs.VectorData);
- var flat = retVector.Data;
- VectorHelper.Pow(flat, lhs.LiteralValue, rhs.VectorData.Data);
- return new ComputationResult(retVector, true);
- }
- else
- {
- var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData);
- VectorHelper.Pow(retMatrix.Data, lhs.LiteralValue, rhs.OdData.Data);
- return new ComputationResult(retMatrix, true);
- }
+ var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData);
+ VectorHelper.Pow(retMatrix.Data, lhs.LiteralValue, rhs.OdData.Data);
+ return new ComputationResult(retMatrix, true);
}
- else if (rhs.IsValue)
+ }
+ else if (rhs.IsValue)
+ {
+ if (lhs.IsVectorResult)
{
- if (lhs.IsVectorResult)
- {
- var retVector = lhs.Accumulator ? lhs.VectorData : new Vector(lhs.VectorData);
- var flat = retVector.Data;
- VectorHelper.Pow(flat, lhs.VectorData.Data, rhs.LiteralValue);
- return new ComputationResult(retVector, true);
- }
- else
- {
- // matrix / float
- var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
- VectorHelper.Pow(retMatrix.Data, lhs.OdData.Data, rhs.LiteralValue);
- return new ComputationResult(retMatrix, true);
- }
+ var retVector = lhs.Accumulator ? lhs.VectorData : new Vector(lhs.VectorData);
+ var flat = retVector.Data;
+ VectorHelper.Pow(flat, lhs.VectorData.Data, rhs.LiteralValue);
+ return new ComputationResult(retVector, true);
}
else
{
- if (lhs.IsVectorResult || rhs.IsVectorResult)
+ // matrix / float
+ var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
+ VectorHelper.Pow(retMatrix.Data, lhs.OdData.Data, rhs.LiteralValue);
+ return new ComputationResult(retMatrix, true);
+ }
+ }
+ else
+ {
+ if (lhs.IsVectorResult || rhs.IsVectorResult)
+ {
+ if (lhs.IsVectorResult && rhs.IsVectorResult)
{
- if (lhs.IsVectorResult && rhs.IsVectorResult)
- {
- var retMatrix = lhs.Accumulator ? lhs.VectorData : (rhs.Accumulator ? rhs.VectorData : new Vector(lhs.VectorData));
- VectorHelper.Pow(retMatrix.Data, lhs.VectorData.Data, rhs.VectorData.Data);
- return new ComputationResult(retMatrix, true, lhs.Direction);
- }
- else if (lhs.IsVectorResult)
+ var retMatrix = lhs.Accumulator ? lhs.VectorData : (rhs.Accumulator ? rhs.VectorData : new Vector(lhs.VectorData));
+ VectorHelper.Pow(retMatrix.Data, lhs.VectorData.Data, rhs.VectorData.Data);
+ return new ComputationResult(retMatrix, true, lhs.Direction);
+ }
+ else if (lhs.IsVectorResult)
+ {
+ var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData);
+ var flatLhs = lhs.VectorData.Data;
+ var rowSize = flatLhs.Length;
+ if (lhs.Direction == ComputationResult.VectorDirection.Vertical)
{
- var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData);
- var flatLhs = lhs.VectorData.Data;
- var rowSize = flatLhs.Length;
- if (lhs.Direction == ComputationResult.VectorDirection.Vertical)
- {
- for (int i = 0; i < rowSize; i++)
- {
- var retRow = retMatrix.GetRow(i);
- var rhsRow = rhs.OdData.GetRow(i);
- VectorHelper.Pow(retRow, flatLhs[i], rhsRow);
- }
- }
- else if (lhs.Direction == ComputationResult.VectorDirection.Horizontal)
+ for (int i = 0; i < rowSize; i++)
{
- for (int i = 0; i < rowSize; i++)
- {
- var retRow = retMatrix.GetRow(i);
- var rhsRow = rhs.OdData.GetRow(i);
- VectorHelper.Pow(retRow, flatLhs, rhsRow);
- }
+ var retRow = retMatrix.GetRow(i);
+ var rhsRow = rhs.OdData.GetRow(i);
+ VectorHelper.Pow(retRow, flatLhs[i], rhsRow);
}
- else
+ }
+ else if (lhs.Direction == ComputationResult.VectorDirection.Horizontal)
+ {
+ for (int i = 0; i < rowSize; i++)
{
- return new ComputationResult("Unable to subtract vector without directionality starting at position " + (Lhs?.Start ?? -1) + "!");
+ var retRow = retMatrix.GetRow(i);
+ var rhsRow = rhs.OdData.GetRow(i);
+ VectorHelper.Pow(retRow, flatLhs, rhsRow);
}
- return new ComputationResult(retMatrix, true);
}
else
{
- var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
- var flatRhs = rhs.VectorData.Data;
- var rowSize = flatRhs.Length;
- if (rhs.Direction == ComputationResult.VectorDirection.Vertical)
- {
- for (int i = 0; i < rowSize; i++)
- {
- var retRow = retMatrix.GetRow(i);
- var lhsRow = lhs.OdData.GetRow(i);
- VectorHelper.Pow(retRow, lhsRow, flatRhs[i]);
- }
- }
- else if (rhs.Direction == ComputationResult.VectorDirection.Horizontal)
+ return new ComputationResult("Unable to subtract vector without directionality starting at position " + (Lhs?.Start ?? -1) + "!");
+ }
+ return new ComputationResult(retMatrix, true);
+ }
+ else
+ {
+ var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
+ var flatRhs = rhs.VectorData.Data;
+ var rowSize = flatRhs.Length;
+ if (rhs.Direction == ComputationResult.VectorDirection.Vertical)
+ {
+ for (int i = 0; i < rowSize; i++)
{
- for (int i = 0; i < rowSize; i++)
- {
- var retRow = retMatrix.GetRow(i);
- var lhsRow = lhs.OdData.GetRow(i);
- VectorHelper.Pow(retRow, lhsRow, flatRhs);
- }
+ var retRow = retMatrix.GetRow(i);
+ var lhsRow = lhs.OdData.GetRow(i);
+ VectorHelper.Pow(retRow, lhsRow, flatRhs[i]);
}
- else
+ }
+ else if (rhs.Direction == ComputationResult.VectorDirection.Horizontal)
+ {
+ for (int i = 0; i < rowSize; i++)
{
- return new ComputationResult("Unable to subtract vector without directionality starting at position " + (Lhs?.Start ?? -1) + "!");
+ var retRow = retMatrix.GetRow(i);
+ var lhsRow = lhs.OdData.GetRow(i);
+ VectorHelper.Pow(retRow, lhsRow, flatRhs);
}
- return new ComputationResult(retMatrix, true);
}
- }
- else
- {
- var retMatrix = lhs.Accumulator ? lhs.OdData : (rhs.Accumulator ? rhs.OdData : new Matrix(lhs.OdData));
- VectorHelper.Pow(retMatrix.Data, lhs.OdData.Data, rhs.OdData.Data);
+ else
+ {
+ return new ComputationResult("Unable to subtract vector without directionality starting at position " + (Lhs?.Start ?? -1) + "!");
+ }
return new ComputationResult(retMatrix, true);
}
}
+ else
+ {
+ var retMatrix = lhs.Accumulator ? lhs.OdData : (rhs.Accumulator ? rhs.OdData : new Matrix(lhs.OdData));
+ VectorHelper.Pow(retMatrix.Data, lhs.OdData.Data, rhs.OdData.Data);
+ return new ComputationResult(retMatrix, true);
+ }
}
}
}
diff --git a/src/TMG-Framework/Processing/AST/Expression.cs b/src/TMG-Framework/Processing/AST/Expression.cs
index ee9c4fe..c19b694 100644
--- a/src/TMG-Framework/Processing/AST/Expression.cs
+++ b/src/TMG-Framework/Processing/AST/Expression.cs
@@ -17,481 +17,449 @@ You should have received a copy of the GNU General Public License
along with XTMF. If not, see .
*/
-using System;
-using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
-using System.Text;
-using System.Threading.Tasks;
-using XTMF2;
-
-namespace TMG.Frameworks.Data.Processing.AST
+namespace TMG.Frameworks.Data.Processing.AST;
+
+public abstract class Expression : AstNode
{
- public abstract class Expression : AstNode
+
+ public Expression(int start) : base(start)
{
- public Expression(int start) : base(start)
- {
+ }
- }
+ private static bool FailWithError(
+ [NotNullWhen(false)] out ComputationResult? result, string message)
+ {
+ result = new ComputationResult(message);
+ return false;
+ }
- private static bool FailWithError(
- [NotNullWhen(false)] out ComputationResult? result, string message)
+ protected bool ValidateSizes(ComputationResult lhs, ComputationResult rhs, int position,
+ [NotNullWhen(false)] out ComputationResult? errorResult)
+ {
+ errorResult = null;
+ if (lhs.IsValue || lhs.IsVectorResult && rhs.IsOdResult)
{
- result = new ComputationResult(message);
- return false;
+ var temp = rhs;
+ rhs = lhs;
+ lhs = temp;
}
-
- protected bool ValidateSizes(ComputationResult lhs, ComputationResult rhs, int position,
- [NotNullWhen(false)] out ComputationResult? errorResult)
+ if (lhs.IsOdResult)
{
- errorResult = null;
- if (lhs.IsValue || lhs.IsVectorResult && rhs.IsOdResult)
- {
- var temp = rhs;
- rhs = lhs;
- lhs = temp;
- }
- if (lhs.IsOdResult)
+ if (rhs.IsOdResult)
{
- if (rhs.IsOdResult)
+ if (!(lhs.OdData!.ColumnCategories == rhs.OdData!.ColumnCategories
+ && lhs.OdData.RowCategories == rhs.OdData.RowCategories))
{
- if (!(lhs.OdData!.ColumnCategories == rhs.OdData!.ColumnCategories
- && lhs.OdData.RowCategories == rhs.OdData.RowCategories))
- {
- return FailWithError(out errorResult, $"Operation at position {position} failed because data was not of compatible categories.");
- }
+ return FailWithError(out errorResult, $"Operation at position {position} failed because data was not of compatible categories.");
}
- else if (rhs.IsVectorResult)
+ }
+ else if (rhs.IsVectorResult)
+ {
+ switch (rhs.Direction)
{
- switch (rhs.Direction)
- {
- case ComputationResult.VectorDirection.Horizontal:
- if (!(lhs.OdData!.ColumnCategories == rhs.VectorData!.Categories))
- {
- return FailWithError(out errorResult, $"Operation at position {position} failed because data was not of compatible categories.");
- }
- break;
- case ComputationResult.VectorDirection.Vertical:
- if (!(lhs.OdData!.RowCategories == rhs.VectorData!.Categories))
- {
- return FailWithError(out errorResult, $"Operation at position {position} failed because data was not of compatible categories.");
- }
- break;
- case ComputationResult.VectorDirection.Unassigned:
- return FailWithError(out errorResult, $"Operation at position {position} failed because a non-oriented vector can not be applied to a matrix.");
- }
+ case ComputationResult.VectorDirection.Horizontal:
+ if (!(lhs.OdData!.ColumnCategories == rhs.VectorData!.Categories))
+ {
+ return FailWithError(out errorResult, $"Operation at position {position} failed because data was not of compatible categories.");
+ }
+ break;
+ case ComputationResult.VectorDirection.Vertical:
+ if (!(lhs.OdData!.RowCategories == rhs.VectorData!.Categories))
+ {
+ return FailWithError(out errorResult, $"Operation at position {position} failed because data was not of compatible categories.");
+ }
+ break;
+ case ComputationResult.VectorDirection.Unassigned:
+ return FailWithError(out errorResult, $"Operation at position {position} failed because a non-oriented vector can not be applied to a matrix.");
}
}
- else if (lhs.IsVectorResult)
+ }
+ else if (lhs.IsVectorResult)
+ {
+ if (rhs.IsVectorResult)
{
- if (rhs.IsVectorResult)
+ if (lhs.VectorData!.Categories != rhs.VectorData!.Categories)
{
- if (lhs.VectorData!.Categories != rhs.VectorData!.Categories)
- {
- return FailWithError(out errorResult, "Operation failed because data was not of compatible categories.");
- }
+ return FailWithError(out errorResult, "Operation failed because data was not of compatible categories.");
}
}
- return true;
}
+ return true;
+ }
- private static int FindEndOfBracket(char[] buffer, int start, int length,
- [NotNullWhen(false)] ref string? error)
+ private static int FindEndOfBracket(char[] buffer, int start, int length,
+ [NotNullWhen(false)] ref string? error)
+ {
+ int bracketLevel = 1;
+ int i = start;
+ for (; i < start + length && bracketLevel > 0; i++)
{
- int bracketLevel = 1;
- int i = start;
- for (; i < start + length && bracketLevel > 0; i++)
+ if (buffer[i] == ')')
{
- if (buffer[i] == ')')
- {
- bracketLevel--;
- }
- else if (buffer[i] == '(')
- {
- bracketLevel++;
- }
+ bracketLevel--;
}
- if (bracketLevel == 0)
+ else if (buffer[i] == '(')
{
- return i - 1;
+ bracketLevel++;
}
- error = "Unable to find end of bracket starting at position " + start;
- return -1;
}
-
- internal static bool Optimize(
- [NotNullWhen(true)] ref Expression ex,
- [NotNullWhen(false)] ref string? error)
+ if (bracketLevel == 0)
{
- // if this ever becomes a real problem try to add some optimization to the expression tree
- return ex.OptimizeAst(ref ex, ref error);
+ return i - 1;
}
+ error = "Unable to find end of bracket starting at position " + start;
+ return -1;
+ }
+
+ internal static bool Optimize(
+ [NotNullWhen(true)] ref Expression ex,
+ [NotNullWhen(false)] ref string? error)
+ {
+ // if this ever becomes a real problem try to add some optimization to the expression tree
+ return ex.OptimizeAst(ref ex, ref error);
+ }
- private static int FindStartOfBracket(char[] buffer, int start, int length,
- [NotNullWhen(false)] ref string? error)
+ private static int FindStartOfBracket(char[] buffer, int start, int length,
+ [NotNullWhen(false)] ref string? error)
+ {
+ int bracketLevel = 1;
+ int i = start + length - 1;
+ for (; i >= start && bracketLevel > 0; i--)
{
- int bracketLevel = 1;
- int i = start + length - 1;
- for (; i >= start && bracketLevel > 0; i--)
+ if (buffer[i] == '(')
{
- if (buffer[i] == '(')
- {
- bracketLevel--;
- }
- else if (buffer[i] == ')')
- {
- bracketLevel++;
- }
+ bracketLevel--;
}
- if (bracketLevel == 0)
+ else if (buffer[i] == ')')
{
- return i + 1;
+ bracketLevel++;
}
- error = "Unable to find start of bracket with the end bracket at position " + start;
- return -1;
}
+ if (bracketLevel == 0)
+ {
+ return i + 1;
+ }
+ error = "Unable to find start of bracket with the end bracket at position " + start;
+ return -1;
+ }
- private static bool AnyNonWhitespace(char[] buffer, int start, int length)
+ private static bool AnyNonWhitespace(char[] buffer, int start, int length)
+ {
+ for (int i = start; i < start + length; i++)
{
- for (int i = start; i < start + length; i++)
+ if (buffer[i] != ' ')
{
- if (buffer[i] != ' ')
- {
- return true;
- }
+ return true;
}
- return false;
}
+ return false;
+ }
- private static bool IsCompareType(Expression e)
+ private static bool IsCompareType(Expression e)
+ {
+ var t = e.GetType();
+ if (t == typeof(Bracket))
{
- var t = e.GetType();
- if (t == typeof(Bracket))
+ var inner = ((Bracket)e).InnerExpression;
+ if (inner is null)
{
- var inner = ((Bracket)e).InnerExpression;
- if (inner is null)
- {
- return false;
- }
- return IsCompareType(inner);
+ return false;
}
- return t == typeof(CompareEqual)
- || t == typeof(CompareNotEquals)
- || t == typeof(CompareGreaterThan)
- || t == typeof(CompareGreaterThanOrEqual)
- || t == typeof(CompareAnd)
- || t == typeof(CompareOr);
- }
-
- public static bool Compile(char[] buffer, int start, int length,
- [NotNullWhen(true)] out Expression? ex,
- [NotNullWhen(false)] ref string? error)
- {
- ex = null;
- var endPlusOne = (length + start);
- // support AND and OR for our compare operations
- for (int i = start; i < endPlusOne; i++)
+ return IsCompareType(inner);
+ }
+ return t == typeof(CompareEqual)
+ || t == typeof(CompareNotEquals)
+ || t == typeof(CompareGreaterThan)
+ || t == typeof(CompareGreaterThanOrEqual)
+ || t == typeof(CompareAnd)
+ || t == typeof(CompareOr);
+ }
+
+ public static bool Compile(char[] buffer, int start, int length,
+ [NotNullWhen(true)] out Expression? ex,
+ [NotNullWhen(false)] ref string? error)
+ {
+ ex = null;
+ var endPlusOne = (length + start);
+ // support AND and OR for our compare operations
+ for (int i = start; i < endPlusOne; i++)
+ {
+ switch (buffer[i])
{
- switch (buffer[i])
- {
- case '(':
+ case '(':
+ {
+ int endIndex = FindEndOfBracket(buffer, i + 1, endPlusOne - (i + 1), ref error);
+ if (endIndex < 0)
{
- int endIndex = FindEndOfBracket(buffer, i + 1, endPlusOne - (i + 1), ref error);
- if (endIndex < 0)
- {
- error = $"At position {i} we found a '(' character without an accompanying ')'";
- return false;
- }
- i = endIndex;
+ error = $"At position {i} we found a '(' character without an accompanying ')'";
+ return false;
}
- break;
- case '&':
+ i = endIndex;
+ }
+ break;
+ case '&':
+ {
+ BinaryExpression toReturn = new CompareAnd(i);
+ if (!Compile(buffer, start, i - start, out toReturn.Lhs, ref error)) return false;
+ if (!Compile(buffer, i + 1, endPlusOne - i - 1, out toReturn.Rhs, ref error)) return false;
+ // test LHS to make sure it is a compare
+ if (!IsCompareType(toReturn.Lhs) && !IsCompareType(toReturn.Rhs))
{
- BinaryExpression toReturn = new CompareAnd(i);
- if (!Compile(buffer, start, i - start, out toReturn.Lhs, ref error)) return false;
- if (!Compile(buffer, i + 1, endPlusOne - i - 1, out toReturn.Rhs, ref error)) return false;
- // test LHS to make sure it is a compare
- if (!IsCompareType(toReturn.Lhs) && !IsCompareType(toReturn.Rhs))
- {
- error = $"At position {i} we found an '&' character where neither the LHS and the RHS were flag types, at least one is required!";
- return false;
- }
- ex = toReturn;
- return true;
+ error = $"At position {i} we found an '&' character where neither the LHS and the RHS were flag types, at least one is required!";
+ return false;
+ }
+ ex = toReturn;
+ return true;
+ }
+ case '|':
+ {
+ BinaryExpression toReturn = new CompareOr(i);
+ if (!Compile(buffer, start, i - start, out toReturn.Lhs, ref error)) return false;
+ if (!Compile(buffer, i + 1, endPlusOne - i - 1, out toReturn.Rhs, ref error)) return false;
+ // test LHS to make sure it is a compare
+ if (!IsCompareType(toReturn.Lhs))
+ {
+ error = $"At position {i} we found a '|' character where the LHS was not a flag type!";
+ return false;
}
- case '|':
+ // test RHS to make sure it is a compare
+ if (!IsCompareType(toReturn.Rhs))
{
- BinaryExpression toReturn = new CompareOr(i);
- if (!Compile(buffer, start, i - start, out toReturn.Lhs, ref error)) return false;
- if (!Compile(buffer, i + 1, endPlusOne - i - 1, out toReturn.Rhs, ref error)) return false;
- // test LHS to make sure it is a compare
- if (!IsCompareType(toReturn.Lhs))
- {
- error = $"At position {i} we found a '|' character where the LHS was not a flag type!";
- return false;
- }
- // test RHS to make sure it is a compare
- if (!IsCompareType(toReturn.Rhs))
- {
- error = $"At position {i} we found a '|' character where the RHS was not a flag type!";
- return false;
- }
- ex = toReturn;
- return true;
+ error = $"At position {i} we found a '|' character where the RHS was not a flag type!";
+ return false;
}
- }
+ ex = toReturn;
+ return true;
+ }
}
- // support compare
- for (int i = start; i < endPlusOne; i++)
+ }
+ // support compare
+ for (int i = start; i < endPlusOne; i++)
+ {
+ switch (buffer[i])
{
- switch (buffer[i])
- {
- case '(':
+ case '(':
+ {
+ int endIndex = FindEndOfBracket(buffer, i + 1, endPlusOne - (i + 1), ref error);
+ if (endIndex < 0)
{
- int endIndex = FindEndOfBracket(buffer, i + 1, endPlusOne - (i + 1), ref error);
- if (endIndex < 0)
- {
- error = $"At position {i} we found a '(' character without an accompanying ')'";
- return false;
- }
- i = endIndex;
+ error = $"At position {i} we found a '(' character without an accompanying ')'";
+ return false;
}
- break;
- case '=':
+ i = endIndex;
+ }
+ break;
+ case '=':
+ {
+ if (i + 1 < endPlusOne && buffer[i + 1] == '=')
{
- if (i + 1 < endPlusOne && buffer[i + 1] == '=')
- {
- BinaryExpression toReturn = new CompareEqual(i);
- if (!Compile(buffer, start, i - start, out toReturn.Lhs, ref error)) return false;
- if (!Compile(buffer, i + 2, endPlusOne - i - 2, out toReturn.Rhs, ref error)) return false;
- ex = toReturn;
- return true;
- }
- else
- {
- error = $"At position {i} we found an '=' character without an accompanying '='!";
- return false;
- }
+ BinaryExpression toReturn = new CompareEqual(i);
+ if (!Compile(buffer, start, i - start, out toReturn.Lhs, ref error)) return false;
+ if (!Compile(buffer, i + 2, endPlusOne - i - 2, out toReturn.Rhs, ref error)) return false;
+ ex = toReturn;
+ return true;
}
- case '!':
+ else
{
- if (i + 1 < endPlusOne && buffer[i + 1] == '=')
- {
- BinaryExpression toReturn = new CompareNotEquals(i);
- if (!Compile(buffer, start, i - start, out toReturn.Lhs, ref error)) return false;
- if (!Compile(buffer, i + 2, endPlusOne - i - 2, out toReturn.Rhs, ref error)) return false;
- ex = toReturn;
- return true;
- }
- else
- {
- error = $"At position {i} we found an '!' character without an accompanying '='!";
- return false;
- }
+ error = $"At position {i} we found an '=' character without an accompanying '='!";
+ return false;
}
- case '>':
+ }
+ case '!':
+ {
+ if (i + 1 < endPlusOne && buffer[i + 1] == '=')
{
- if (i + 1 < endPlusOne && buffer[i + 1] == '=')
- {
- BinaryExpression toReturn = new CompareGreaterThanOrEqual(i);
- if (!Compile(buffer, start, i - start, out toReturn.Lhs, ref error)) return false;
- if (!Compile(buffer, i + 2, endPlusOne - i - 2, out toReturn.Rhs, ref error)) return false;
- ex = toReturn;
- return true;
- }
- else
- {
- BinaryExpression toReturn = new CompareGreaterThan(i);
- if (!Compile(buffer, start, i - start, out toReturn.Lhs, ref error)) return false;
- if (!Compile(buffer, i + 1, endPlusOne - i - 1, out toReturn.Rhs, ref error)) return false;
- ex = toReturn;
- return true;
- }
+ BinaryExpression toReturn = new CompareNotEquals(i);
+ if (!Compile(buffer, start, i - start, out toReturn.Lhs, ref error)) return false;
+ if (!Compile(buffer, i + 2, endPlusOne - i - 2, out toReturn.Rhs, ref error)) return false;
+ ex = toReturn;
+ return true;
}
- case '<':
+ else
{
- if (i + 1 < endPlusOne && buffer[i + 1] == '=')
- {
- // Inverse the LHS and RHS to reuse the greater comparisons
- BinaryExpression toReturn = new CompareGreaterThanOrEqual(i);
- if (!Compile(buffer, i + 2, endPlusOne - i - 2, out toReturn.Lhs, ref error)) return false;
- if (!Compile(buffer, start, i - start, out toReturn.Rhs, ref error)) return false;
- ex = toReturn;
- return true;
- }
- else
- {
- // Inverse the LHS and RHS to reuse the greater comparisons
- BinaryExpression toReturn = new CompareGreaterThan(i);
- if (!Compile(buffer, i + 1, endPlusOne - i - 1, out toReturn.Lhs, ref error)) return false;
- if (!Compile(buffer, start, i - start, out toReturn.Rhs, ref error)) return false;
- ex = toReturn;
- return true;
- }
+ error = $"At position {i} we found an '!' character without an accompanying '='!";
+ return false;
}
- }
- }
- // try to extract +
- for (int i = start; i < endPlusOne; i++)
- {
- switch (buffer[i])
- {
- case '(':
+ }
+ case '>':
+ {
+ if (i + 1 < endPlusOne && buffer[i + 1] == '=')
{
- int endIndex = FindEndOfBracket(buffer, i + 1, endPlusOne - (i + 1), ref error);
- if (endIndex < 0)
- {
- error = $"At position {i} we found a '(' character without an accompanying ')'";
- return false;
- }
- i = endIndex;
+ BinaryExpression toReturn = new CompareGreaterThanOrEqual(i);
+ if (!Compile(buffer, start, i - start, out toReturn.Lhs, ref error)) return false;
+ if (!Compile(buffer, i + 2, endPlusOne - i - 2, out toReturn.Rhs, ref error)) return false;
+ ex = toReturn;
+ return true;
}
- break;
- case '+':
+ else
{
- BinaryExpression toReturn = new Add(i);
- if (!Compile(buffer, start, i - start, out toReturn.Lhs, ref error))
- {
- return false;
- }
+ BinaryExpression toReturn = new CompareGreaterThan(i);
+ if (!Compile(buffer, start, i - start, out toReturn.Lhs, ref error)) return false;
if (!Compile(buffer, i + 1, endPlusOne - i - 1, out toReturn.Rhs, ref error)) return false;
ex = toReturn;
return true;
}
- }
- }
- // try to extract -
- for (int i = start; i < endPlusOne; i++)
- {
- switch (buffer[i])
- {
- case '(':
+ }
+ case '<':
+ {
+ if (i + 1 < endPlusOne && buffer[i + 1] == '=')
{
- int endIndex = FindEndOfBracket(buffer, i + 1, endPlusOne - (i + 1), ref error);
- if (endIndex < 0)
- {
- error = $"At position {i} we found a '(' character without an accompanying ')'";
- return false;
- }
- i = endIndex;
+ // Inverse the LHS and RHS to reuse the greater comparisons
+ BinaryExpression toReturn = new CompareGreaterThanOrEqual(i);
+ if (!Compile(buffer, i + 2, endPlusOne - i - 2, out toReturn.Lhs, ref error)) return false;
+ if (!Compile(buffer, start, i - start, out toReturn.Rhs, ref error)) return false;
+ ex = toReturn;
+ return true;
}
- break;
- case '-':
+ else
{
- BinaryExpression toReturn = new Subtract(i);
- if (!Compile(buffer, start, i - start, out toReturn.Lhs, ref error))
- {
- // check to see if it is negate
- if (buffer[i] == '-')
- {
- bool anythingAfter = false;
- for (int k = i + 1; k < endPlusOne; k++)
- {
- if (!char.IsWhiteSpace(buffer[k]))
- {
- anythingAfter = true;
- break;
- }
- }
- if (anythingAfter)
- {
- error = null;
- continue;
- }
- }
- return false;
- }
- if (!Compile(buffer, i + 1, endPlusOne - i - 1, out toReturn.Rhs, ref error)) return false;
+ // Inverse the LHS and RHS to reuse the greater comparisons
+ BinaryExpression toReturn = new CompareGreaterThan(i);
+ if (!Compile(buffer, i + 1, endPlusOne - i - 1, out toReturn.Lhs, ref error)) return false;
+ if (!Compile(buffer, start, i - start, out toReturn.Rhs, ref error)) return false;
ex = toReturn;
return true;
}
- }
+ }
}
- // if there are no adds work on multiplies fix this for division
- for (int i = start; i < endPlusOne; i++)
+ }
+ // try to extract +
+ for (int i = start; i < endPlusOne; i++)
+ {
+ switch (buffer[i])
{
- switch (buffer[i])
- {
- case '(':
+ case '(':
+ {
+ int endIndex = FindEndOfBracket(buffer, i + 1, endPlusOne - (i + 1), ref error);
+ if (endIndex < 0)
{
- int endIndex = FindEndOfBracket(buffer, i + 1, endPlusOne - (i + 1), ref error);
- if (endIndex < 0)
- {
- error = $"At position {i} we found a '(' character without an accompanying ')'";
- return false;
- }
- i = endIndex;
+ error = $"At position {i} we found a '(' character without an accompanying ')'";
+ return false;
}
- break;
- case '*':
+ i = endIndex;
+ }
+ break;
+ case '+':
+ {
+ BinaryExpression toReturn = new Add(i);
+ if (!Compile(buffer, start, i - start, out toReturn.Lhs, ref error))
{
- BinaryExpression toReturn = new Multiply(i);
- if (!Compile(buffer, start, i - start, out toReturn.Lhs, ref error)) return false;
- if (!Compile(buffer, i + 1, endPlusOne - i - 1, out toReturn.Rhs, ref error)) return false;
- ex = toReturn;
- return true;
+ return false;
}
- }
+ if (!Compile(buffer, i + 1, endPlusOne - i - 1, out toReturn.Rhs, ref error)) return false;
+ ex = toReturn;
+ return true;
+ }
}
- // if there are no adds work on division
- for (int i = length + start - 1; i >= start; i--)
+ }
+ // try to extract -
+ for (int i = start; i < endPlusOne; i++)
+ {
+ switch (buffer[i])
{
- switch (buffer[i])
- {
- case ')':
+ case '(':
+ {
+ int endIndex = FindEndOfBracket(buffer, i + 1, endPlusOne - (i + 1), ref error);
+ if (endIndex < 0)
{
- int endIndex = FindStartOfBracket(buffer, start, i - start, ref error);
- if (endIndex < 0)
- {
- error = $"At position {i} we found a ')' character without an accompanying '('";
- return false;
- }
- i = endIndex;
+ error = $"At position {i} we found a '(' character without an accompanying ')'";
+ return false;
}
- break;
- case '/':
+ i = endIndex;
+ }
+ break;
+ case '-':
+ {
+ BinaryExpression toReturn = new Subtract(i);
+ if (!Compile(buffer, start, i - start, out toReturn.Lhs, ref error))
{
- BinaryExpression toReturn = new Divide(i);
- if (!Compile(buffer, start, i - start, out toReturn.Lhs, ref error)) return false;
- if (!Compile(buffer, i + 1, endPlusOne - i - 1, out toReturn.Rhs, ref error)) return false;
- ex = toReturn;
- return true;
+ // check to see if it is negate
+ if (buffer[i] == '-')
+ {
+ bool anythingAfter = false;
+ for (int k = i + 1; k < endPlusOne; k++)
+ {
+ if (!char.IsWhiteSpace(buffer[k]))
+ {
+ anythingAfter = true;
+ break;
+ }
+ }
+ if (anythingAfter)
+ {
+ error = null;
+ continue;
+ }
+ }
+ return false;
}
- }
+ if (!Compile(buffer, i + 1, endPlusOne - i - 1, out toReturn.Rhs, ref error)) return false;
+ ex = toReturn;
+ return true;
+ }
}
- // support exponents
- for (int i = start; i < endPlusOne; i++)
+ }
+ // if there are no adds work on multiplies fix this for division
+ for (int i = start; i < endPlusOne; i++)
+ {
+ switch (buffer[i])
{
- switch (buffer[i])
- {
- case '(':
+ case '(':
+ {
+ int endIndex = FindEndOfBracket(buffer, i + 1, endPlusOne - (i + 1), ref error);
+ if (endIndex < 0)
{
- int endIndex = FindEndOfBracket(buffer, i + 1, endPlusOne - (i + 1), ref error);
- if (endIndex < 0)
- {
- error = $"At position {i} we found a '(' character without an accompanying ')'";
- return false;
- }
- i = endIndex;
+ error = $"At position {i} we found a '(' character without an accompanying ')'";
+ return false;
}
- break;
- case '^':
+ i = endIndex;
+ }
+ break;
+ case '*':
+ {
+ BinaryExpression toReturn = new Multiply(i);
+ if (!Compile(buffer, start, i - start, out toReturn.Lhs, ref error)) return false;
+ if (!Compile(buffer, i + 1, endPlusOne - i - 1, out toReturn.Rhs, ref error)) return false;
+ ex = toReturn;
+ return true;
+ }
+ }
+ }
+ // if there are no adds work on division
+ for (int i = length + start - 1; i >= start; i--)
+ {
+ switch (buffer[i])
+ {
+ case ')':
+ {
+ int endIndex = FindStartOfBracket(buffer, start, i - start, ref error);
+ if (endIndex < 0)
{
- BinaryExpression toReturn = new Exponent(i);
- if (!Compile(buffer, start, i - start, out toReturn.Lhs, ref error)) return false;
- if (!Compile(buffer, i + 1, endPlusOne - i - 1, out toReturn.Rhs, ref error)) return false;
- ex = toReturn;
- return true;
+ error = $"At position {i} we found a ')' character without an accompanying '('";
+ return false;
}
- }
+ i = endIndex;
+ }
+ break;
+ case '/':
+ {
+ BinaryExpression toReturn = new Divide(i);
+ if (!Compile(buffer, start, i - start, out toReturn.Lhs, ref error)) return false;
+ if (!Compile(buffer, i + 1, endPlusOne - i - 1, out toReturn.Rhs, ref error)) return false;
+ ex = toReturn;
+ return true;
+ }
}
- // support negate
- for (int i = start; i < endPlusOne; i++)
+ }
+ // support exponents
+ for (int i = start; i < endPlusOne; i++)
+ {
+ switch (buffer[i])
{
- switch (buffer[i])
- {
- case '(':
+ case '(':
+ {
int endIndex = FindEndOfBracket(buffer, i + 1, endPlusOne - (i + 1), ref error);
if (endIndex < 0)
{
@@ -499,310 +467,334 @@ public static bool Compile(char[] buffer, int start, int length,
return false;
}
i = endIndex;
- break;
- case '-':
- {
- MonoExpression toReturn = new Negate(start);
- if (!Compile(buffer, i + 1, endPlusOne - i - 1, out toReturn.InnerExpression, ref error)) return false;
- ex = toReturn;
- return true;
- }
- }
+ }
+ break;
+ case '^':
+ {
+ BinaryExpression toReturn = new Exponent(i);
+ if (!Compile(buffer, start, i - start, out toReturn.Lhs, ref error)) return false;
+ if (!Compile(buffer, i + 1, endPlusOne - i - 1, out toReturn.Rhs, ref error)) return false;
+ ex = toReturn;
+ return true;
+ }
}
- StringBuilder builder = new StringBuilder();
- bool first = true;
- bool complete = false;
- // check for function calls
- for (int i = start; i < start + length && !complete; i++)
+ }
+ // support negate
+ for (int i = start; i < endPlusOne; i++)
+ {
+ switch (buffer[i])
{
- switch (buffer[i])
- {
- case ' ':
- if (!first)
+ case '(':
+ int endIndex = FindEndOfBracket(buffer, i + 1, endPlusOne - (i + 1), ref error);
+ if (endIndex < 0)
+ {
+ error = $"At position {i} we found a '(' character without an accompanying ')'";
+ return false;
+ }
+ i = endIndex;
+ break;
+ case '-':
+ {
+ MonoExpression toReturn = new Negate(start);
+ if (!Compile(buffer, i + 1, endPlusOne - i - 1, out toReturn.InnerExpression, ref error)) return false;
+ ex = toReturn;
+ return true;
+ }
+ }
+ }
+ StringBuilder builder = new StringBuilder();
+ bool first = true;
+ bool complete = false;
+ // check for function calls
+ for (int i = start; i < start + length && !complete; i++)
+ {
+ switch (buffer[i])
+ {
+ case ' ':
+ if (!first)
+ {
+ complete = true;
+ }
+ break;
+ case '(':
+ {
+ if (first)
{
complete = true;
}
- break;
- case '(':
+ else
{
- if (first)
+ int endIndex = FindEndOfBracket(buffer, i + 1, endPlusOne - (i + 1), ref error);
+ if (endIndex < 0)
{
- complete = true;
+ error = $"At position {i} we found a '(' character without an accompanying ')'";
+ return false;
}
- else
+ List parameters = new List();
+ int lastStart = i + 1;
+ Expression? p;
+ for (int j = i + 1; j < endIndex; j++)
{
- int endIndex = FindEndOfBracket(buffer, i + 1, endPlusOne - (i + 1), ref error);
- if (endIndex < 0)
+ if (buffer[j] == '(')
{
- error = $"At position {i} we found a '(' character without an accompanying ')'";
- return false;
- }
- List parameters = new List();
- int lastStart = i + 1;
- Expression? p;
- for (int j = i + 1; j < endIndex; j++)
- {
- if (buffer[j] == '(')
- {
- // skip to the end
- var innerEndIndex = FindEndOfBracket(buffer, j + 1, endIndex, ref error);
- if (innerEndIndex < 0)
- {
- error = $"At position {j} we found a '(' character without an accompanying ')'";
- return false;
- }
- j = innerEndIndex;
- }
- if (buffer[j] == ',')
+ // skip to the end
+ var innerEndIndex = FindEndOfBracket(buffer, j + 1, endIndex, ref error);
+ if (innerEndIndex < 0)
{
- if (!Compile(buffer, lastStart, j - lastStart, out p, ref error))
- {
- return false;
- }
- parameters.Add(p);
- lastStart = j + 1;
+ error = $"At position {j} we found a '(' character without an accompanying ')'";
+ return false;
}
+ j = innerEndIndex;
}
- if (AnyNonWhitespace(buffer, lastStart, endIndex - lastStart))
+ if (buffer[j] == ',')
{
- // add the final parameter
- if (!Compile(buffer, lastStart, endIndex - lastStart, out p, ref error))
+ if (!Compile(buffer, lastStart, j - lastStart, out p, ref error))
{
return false;
}
parameters.Add(p);
+ lastStart = j + 1;
}
- if (!FunctionCall.GetCall(start, builder.ToString(), parameters.ToArray(), out FunctionCall? toReturn, ref error))
+ }
+ if (AnyNonWhitespace(buffer, lastStart, endIndex - lastStart))
+ {
+ // add the final parameter
+ if (!Compile(buffer, lastStart, endIndex - lastStart, out p, ref error))
{
return false;
}
- ex = toReturn;
- return true;
- }
- }
- break;
- default:
- first = false;
- builder.Append(buffer[i]);
- break;
- }
- }
- // deal with brackets
- for (int i = start; i < start + length; i++)
- {
- switch (buffer[i])
- {
- case '(':
- {
- int endIndex = FindEndOfBracket(buffer, i + 1, endPlusOne - (i + 1), ref error);
- if (endIndex < 0)
- {
- error = $"At position {i} we found a '(' character without an accompanying ')'";
- return false;
+ parameters.Add(p);
}
- var toReturn = new Bracket(i);
- if (!Compile(buffer, i + 1, (endIndex - i) - 1, out toReturn.InnerExpression, ref error))
+ if (!FunctionCall.GetCall(start, builder.ToString(), parameters.ToArray(), out FunctionCall? toReturn, ref error))
{
return false;
}
ex = toReturn;
return true;
}
- }
+ }
+ break;
+ default:
+ first = false;
+ builder.Append(buffer[i]);
+ break;
}
- // try to extract literal / variable name
- builder.Clear();
- first = true;
- complete = false;
- int index = -1;
- for (int i = start; i < endPlusOne && !complete; i++)
+ }
+ // deal with brackets
+ for (int i = start; i < start + length; i++)
+ {
+ switch (buffer[i])
{
- switch (buffer[i])
- {
- case ' ':
- if (first)
- {
- // just skip
- }
- else
+ case '(':
+ {
+ int endIndex = FindEndOfBracket(buffer, i + 1, endPlusOne - (i + 1), ref error);
+ if (endIndex < 0)
{
- complete = true;
- // end of string
+ error = $"At position {i} we found a '(' character without an accompanying ')'";
+ return false;
}
- break;
- default:
- if (first)
+ var toReturn = new Bracket(i);
+ if (!Compile(buffer, i + 1, (endIndex - i) - 1, out toReturn.InnerExpression, ref error))
{
- first = false;
- index = i;
+ return false;
}
- builder.Append(buffer[i]);
- break;
- }
- }
- var value = builder.ToString();
- if (value.Length <= 0)
- {
- error = "We were unable to read in a value at position " + start;
- return false;
- }
- if (float.TryParse(value, out float f))
- {
- // if we can read it in as a floating point number
- ex = new Literal(index, f);
+ ex = toReturn;
+ return true;
+ }
}
- else
+ }
+ // try to extract literal / variable name
+ builder.Clear();
+ first = true;
+ complete = false;
+ int index = -1;
+ for (int i = start; i < endPlusOne && !complete; i++)
+ {
+ switch (buffer[i])
{
- ex = new Variable(index, value);
+ case ' ':
+ if (first)
+ {
+ // just skip
+ }
+ else
+ {
+ complete = true;
+ // end of string
+ }
+ break;
+ default:
+ if (first)
+ {
+ first = false;
+ index = i;
+ }
+ builder.Append(buffer[i]);
+ break;
}
- return true;
}
+ var value = builder.ToString();
+ if (value.Length <= 0)
+ {
+ error = "We were unable to read in a value at position " + start;
+ return false;
+ }
+ if (float.TryParse(value, out float f))
+ {
+ // if we can read it in as a floating point number
+ ex = new Literal(index, f);
+ }
+ else
+ {
+ ex = new Variable(index, value);
+ }
+ return true;
}
+}
- public abstract class MonoExpression : Expression
- {
- public Expression? InnerExpression;
+public abstract class MonoExpression : Expression
+{
+ public Expression? InnerExpression;
- public MonoExpression(int start) : base(start)
- {
+ public MonoExpression(int start) : base(start)
+ {
- }
+ }
- internal override bool OptimizeAst(
- ref Expression ex,
- [NotNullWhen(false)] ref string? error)
+ internal override bool OptimizeAst(
+ ref Expression ex,
+ [NotNullWhen(false)] ref string? error)
+ {
+ if (InnerExpression is null)
{
- if (InnerExpression is null)
- {
- error = "MonoExpression at position " + Start + " has no inner expression!";
- return false;
- }
- return InnerExpression.OptimizeAst(ref InnerExpression, ref error);
+ error = "MonoExpression at position " + Start + " has no inner expression!";
+ return false;
}
+ return InnerExpression.OptimizeAst(ref InnerExpression, ref error);
}
+}
+
+public abstract class BinaryExpression : Expression
+{
+ public Expression? Lhs;
+ public Expression? Rhs;
- public abstract class BinaryExpression : Expression
+ public BinaryExpression(int start) : base(start)
{
- public Expression? Lhs;
- public Expression? Rhs;
- public BinaryExpression(int start) : base(start)
- {
+ }
+ public override ComputationResult Evaluate(IModule[] dataSources)
+ {
+ ComputationResult lhs = null!;
+ ComputationResult rhs = null!;
+ if (Lhs is null)
+ {
+ return new ComputationResult($"BinaryExpression at position {Start} has no LHS!");
}
-
- public override ComputationResult Evaluate(IModule[] dataSources)
+ if (Rhs is null)
{
- ComputationResult lhs = null!;
- ComputationResult rhs = null!;
- if (Lhs is null)
- {
- return new ComputationResult($"BinaryExpression at position {Start} has no LHS!");
- }
- if (Rhs is null)
- {
- return new ComputationResult($"BinaryExpression at position {Start} has no RHS!");
- }
- Parallel.Invoke(
- () => lhs = Lhs.Evaluate(dataSources),
- () => rhs = Rhs.Evaluate(dataSources));
- if (lhs.Error)
- {
- return lhs;
- }
- else if (rhs.Error)
- {
- return rhs;
- }
- if (!ValidateSizes(lhs, rhs, Start, out var errorResult))
- {
- return errorResult;
- }
- return Evaluate(lhs, rhs);
+ return new ComputationResult($"BinaryExpression at position {Start} has no RHS!");
}
-
- public abstract ComputationResult Evaluate(ComputationResult lhs, ComputationResult rhs);
-
- internal override bool OptimizeAst(ref Expression ex,
- [NotNullWhen(false)] ref string? error)
+ Parallel.Invoke(
+ () => lhs = Lhs.Evaluate(dataSources),
+ () => rhs = Rhs.Evaluate(dataSources));
+ if (lhs.Error)
{
- if (Lhs is null)
- {
- error = "BinaryExpression at position " + Start + " has no LHS!";
- return false;
- }
- if (Rhs is null)
- {
- error = "BinaryExpression at position " + Start + " has no RHS!";
- return false;
- }
- if (!Lhs.OptimizeAst(ref Lhs, ref error) || !Rhs.OptimizeAst(ref Rhs, ref error))
- {
- return false;
- }
- return true;
+ return lhs;
}
- }
-
- public abstract class Value : Expression
- {
- public Value(int start) : base(start)
+ else if (rhs.Error)
{
-
+ return rhs;
}
-
- internal override bool OptimizeAst(ref Expression ex,
- [NotNullWhen(false)] ref string? error)
+ if (!ValidateSizes(lhs, rhs, Start, out var errorResult))
{
- return true;
+ return errorResult;
}
+ return Evaluate(lhs, rhs);
}
- public class Bracket : MonoExpression
+ public abstract ComputationResult Evaluate(ComputationResult lhs, ComputationResult rhs);
+
+ internal override bool OptimizeAst(ref Expression ex,
+ [NotNullWhen(false)] ref string? error)
{
- public Bracket(int start) : base(start)
+ if (Lhs is null)
{
-
+ error = "BinaryExpression at position " + Start + " has no LHS!";
+ return false;
}
-
- public override ComputationResult Evaluate(IModule[] dataSources)
+ if (Rhs is null)
{
- if (InnerExpression is null)
- {
- return new ComputationResult($"Bracket at position {Start} has no inner expression!");
- }
- return InnerExpression.Evaluate(dataSources);
+ error = "BinaryExpression at position " + Start + " has no RHS!";
+ return false;
}
-
- internal override bool OptimizeAst(ref Expression ex,
- [NotNullWhen(false)] ref string? error)
+ if (!Lhs.OptimizeAst(ref Lhs, ref error) || !Rhs.OptimizeAst(ref Rhs, ref error))
{
- if (InnerExpression is null)
- {
- error = "MonoExpression at position " + Start + " has no inner expression!";
- return false;
- }
- if (!InnerExpression.OptimizeAst(ref ex, ref error))
- {
- return false;
- }
- return true;
+ return false;
}
+ return true;
}
+}
- public class Literal : Value
+public abstract class Value : Expression
+{
+ public Value(int start) : base(start)
{
- public readonly float Value;
- public Literal(int start, float value) : base(start)
+ }
+
+ internal override bool OptimizeAst(ref Expression ex,
+ [NotNullWhen(false)] ref string? error)
+ {
+ return true;
+ }
+}
+
+public class Bracket : MonoExpression
+{
+ public Bracket(int start) : base(start)
+ {
+
+ }
+
+ public override ComputationResult Evaluate(IModule[] dataSources)
+ {
+ if (InnerExpression is null)
{
- Value = value;
+ return new ComputationResult($"Bracket at position {Start} has no inner expression!");
}
+ return InnerExpression.Evaluate(dataSources);
+ }
- public override ComputationResult Evaluate(IModule[] dataSources)
+ internal override bool OptimizeAst(ref Expression ex,
+ [NotNullWhen(false)] ref string? error)
+ {
+ if (InnerExpression is null)
+ {
+ error = "MonoExpression at position " + Start + " has no inner expression!";
+ return false;
+ }
+ if (!InnerExpression.OptimizeAst(ref ex, ref error))
{
- return new ComputationResult(Value);
+ return false;
}
+ return true;
+ }
+}
+
+public class Literal : Value
+{
+ public readonly float Value;
+
+ public Literal(int start, float value) : base(start)
+ {
+ Value = value;
+ }
+
+ public override ComputationResult Evaluate(IModule[] dataSources)
+ {
+ return new ComputationResult(Value);
}
}
diff --git a/src/TMG-Framework/Processing/AST/FunctionCall.cs b/src/TMG-Framework/Processing/AST/FunctionCall.cs
index 118e7b4..d0a79a0 100644
--- a/src/TMG-Framework/Processing/AST/FunctionCall.cs
+++ b/src/TMG-Framework/Processing/AST/FunctionCall.cs
@@ -16,956 +16,952 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
You should have received a copy of the GNU General Public License
along with XTMF. If not, see .
*/
-using System;
-using System.Diagnostics.CodeAnalysis;
-using System.Linq;
+
using TMG.Utilities;
-using XTMF2;
-namespace TMG.Frameworks.Data.Processing.AST
+namespace TMG.Frameworks.Data.Processing.AST;
+
+public sealed class FunctionCall : Value
{
- public sealed class FunctionCall : Value
+
+ public enum FunctionType
{
+ Undefined,
+ Transpose,
+ SumRows,
+ SumColumns,
+ AsHorizontal,
+ AsVertical,
+ Sum,
+ Abs,
+ Avg,
+ AvgRows,
+ AvgColumns,
+ E,
+ Pi,
+ Length,
+ LengthColumns,
+ LengthRows,
+ ZeroMatrix,
+ Matrix,
+ IdentityMatrix,
+ Log,
+ Sqrt,
+ If,
+ IfNaN,
+ Normalize,
+ NormalizeColumns,
+ NormalizeRows
+ }
- public enum FunctionType
- {
- Undefined,
- Transpose,
- SumRows,
- SumColumns,
- AsHorizontal,
- AsVertical,
- Sum,
- Abs,
- Avg,
- AvgRows,
- AvgColumns,
- E,
- Pi,
- Length,
- LengthColumns,
- LengthRows,
- ZeroMatrix,
- Matrix,
- IdentityMatrix,
- Log,
- Sqrt,
- If,
- IfNaN,
- Normalize,
- NormalizeColumns,
- NormalizeRows
- }
-
- private readonly FunctionType _type;
-
- private readonly Expression[] _parameters;
-
- private FunctionCall(int start, FunctionType call, Expression[] parameters) : base(start)
- {
- _parameters = parameters;
- _type = call;
- }
-
- internal override bool OptimizeAst(ref Expression ex,
- [NotNullWhen(false)] ref string? error)
- {
- for (int i = 0; i < _parameters.Length; i++)
- {
- if (!_parameters[i].OptimizeAst(ref _parameters[i], ref error))
- {
- return false;
- }
- }
- return true;
- }
+ private readonly FunctionType _type;
+
+ private readonly Expression[] _parameters;
- public static bool GetCall(int start, string call, Expression[] parameters,
- [NotNullWhen(true)] out FunctionCall? ex,
- [NotNullWhen(false)] ref string? error)
+ private FunctionCall(int start, FunctionType call, Expression[] parameters) : base(start)
+ {
+ _parameters = parameters;
+ _type = call;
+ }
+
+ internal override bool OptimizeAst(ref Expression ex,
+ [NotNullWhen(false)] ref string? error)
+ {
+ for (int i = 0; i < _parameters.Length; i++)
{
- //decode the call to a type
- ex = null;
- if (!Decode(call, ref error, out FunctionType type))
+ if (!_parameters[i].OptimizeAst(ref _parameters[i], ref error))
{
return false;
}
- ex = new FunctionCall(start, type, parameters);
- return true;
}
+ return true;
+ }
+
+ public static bool GetCall(int start, string call, Expression[] parameters,
+ [NotNullWhen(true)] out FunctionCall? ex,
+ [NotNullWhen(false)] ref string? error)
+ {
+ //decode the call to a type
+ ex = null;
+ if (!Decode(call, ref error, out FunctionType type))
+ {
+ return false;
+ }
+ ex = new FunctionCall(start, type, parameters);
+ return true;
+ }
- private static bool Decode(string call,
- [NotNullWhen(false)] ref string? error,
- out FunctionType type)
+ private static bool Decode(string call,
+ [NotNullWhen(false)] ref string? error,
+ out FunctionType type)
+ {
+ type = FunctionType.Undefined;
+ call = call.ToLowerInvariant();
+ switch (call)
{
- type = FunctionType.Undefined;
- call = call.ToLowerInvariant();
- switch (call)
- {
- case "ashorizontal":
- type = FunctionType.AsHorizontal;
- return true;
- case "asvertical":
- type = FunctionType.AsVertical;
- return true;
- case "transpose":
- type = FunctionType.Transpose;
- return true;
- case "sumrows":
- type = FunctionType.SumRows;
- return true;
- case "sumcolumns":
- type = FunctionType.SumColumns;
- return true;
- case "sum":
- type = FunctionType.Sum;
- return true;
- case "abs":
- type = FunctionType.Abs;
- return true;
- case "avg":
- type = FunctionType.Avg;
- return true;
- case "avgrows":
- type = FunctionType.AvgRows;
- return true;
- case "avgcolumns":
- type = FunctionType.AvgColumns;
- return true;
- case "e":
- type = FunctionType.E;
- return true;
- case "pi":
- type = FunctionType.Pi;
- return true;
- case "length":
- type = FunctionType.Length;
- return true;
- case "lengthrows":
- type = FunctionType.LengthRows;
- return true;
- case "lengthcolumns":
- type = FunctionType.LengthColumns;
- return true;
- case "zeromatrix":
- type = FunctionType.ZeroMatrix;
- return true;
- case "matrix":
- type = FunctionType.Matrix;
- return true;
- case "identitymatrix":
- type = FunctionType.IdentityMatrix;
- return true;
- case "log":
- type = FunctionType.Log;
- return true;
- case "sqrt":
- type = FunctionType.Sqrt;
- return true;
- case "if":
- type = FunctionType.If;
- return true;
- case "ifnan":
- type = FunctionType.IfNaN;
- return true;
- case "normalize":
- type = FunctionType.Normalize;
- return true;
- case "normalizecolumns":
- type = FunctionType.NormalizeColumns;
- return true;
- case "normalizerows":
- type = FunctionType.NormalizeRows;
- return true;
- default:
- error = "The function '" + call + "' is undefined!";
- return false;
- }
+ case "ashorizontal":
+ type = FunctionType.AsHorizontal;
+ return true;
+ case "asvertical":
+ type = FunctionType.AsVertical;
+ return true;
+ case "transpose":
+ type = FunctionType.Transpose;
+ return true;
+ case "sumrows":
+ type = FunctionType.SumRows;
+ return true;
+ case "sumcolumns":
+ type = FunctionType.SumColumns;
+ return true;
+ case "sum":
+ type = FunctionType.Sum;
+ return true;
+ case "abs":
+ type = FunctionType.Abs;
+ return true;
+ case "avg":
+ type = FunctionType.Avg;
+ return true;
+ case "avgrows":
+ type = FunctionType.AvgRows;
+ return true;
+ case "avgcolumns":
+ type = FunctionType.AvgColumns;
+ return true;
+ case "e":
+ type = FunctionType.E;
+ return true;
+ case "pi":
+ type = FunctionType.Pi;
+ return true;
+ case "length":
+ type = FunctionType.Length;
+ return true;
+ case "lengthrows":
+ type = FunctionType.LengthRows;
+ return true;
+ case "lengthcolumns":
+ type = FunctionType.LengthColumns;
+ return true;
+ case "zeromatrix":
+ type = FunctionType.ZeroMatrix;
+ return true;
+ case "matrix":
+ type = FunctionType.Matrix;
+ return true;
+ case "identitymatrix":
+ type = FunctionType.IdentityMatrix;
+ return true;
+ case "log":
+ type = FunctionType.Log;
+ return true;
+ case "sqrt":
+ type = FunctionType.Sqrt;
+ return true;
+ case "if":
+ type = FunctionType.If;
+ return true;
+ case "ifnan":
+ type = FunctionType.IfNaN;
+ return true;
+ case "normalize":
+ type = FunctionType.Normalize;
+ return true;
+ case "normalizecolumns":
+ type = FunctionType.NormalizeColumns;
+ return true;
+ case "normalizerows":
+ type = FunctionType.NormalizeRows;
+ return true;
+ default:
+ error = "The function '" + call + "' is undefined!";
+ return false;
}
+ }
- public override ComputationResult Evaluate(IModule[] dataSources)
+ public override ComputationResult Evaluate(IModule[] dataSources)
+ {
+ // first evaluate the parameters
+ var values = new ComputationResult[_parameters.Length];
+ switch (_parameters.Length)
{
- // first evaluate the parameters
- var values = new ComputationResult[_parameters.Length];
- switch (_parameters.Length)
- {
- case 0:
- break;
- case 1:
+ case 0:
+ break;
+ case 1:
+ {
+ values[0] = _parameters[0].Evaluate(dataSources);
+ if (values[0].Error)
{
- values[0] = _parameters[0].Evaluate(dataSources);
- if (values[0].Error)
- {
- return values[0];
- }
+ return values[0];
}
- break;
- default:
+ }
+ break;
+ default:
+ {
+ System.Threading.Tasks.Parallel.For(0, values.Length, (int i) =>
{
- System.Threading.Tasks.Parallel.For(0, values.Length, (int i) =>
- {
- values[i] = _parameters[i].Evaluate(dataSources);
- });
- for (int i = 0; i < values.Length; i++)
+ values[i] = _parameters[i].Evaluate(dataSources);
+ });
+ for (int i = 0; i < values.Length; i++)
+ {
+ if (values[i].Error)
{
- if (values[i].Error)
- {
- return values[i];
- }
+ return values[i];
}
}
- break;
- }
+ }
+ break;
+ }
- switch (_type)
- {
- case FunctionType.AsHorizontal:
- if (values.Length != 1)
- {
- return new ComputationResult("AsHorizontal at position " + Start + " was executed with the wrong number of parameters!");
- }
- if (!values[0].IsVectorResult)
- {
- return new ComputationResult("AsHorizontal at position " + Start + " was executed with a parameter that was not a vector!");
- }
- return new ComputationResult(values[0], ComputationResult.VectorDirection.Horizontal);
- case FunctionType.AsVertical:
+ switch (_type)
+ {
+ case FunctionType.AsHorizontal:
+ if (values.Length != 1)
+ {
+ return new ComputationResult("AsHorizontal at position " + Start + " was executed with the wrong number of parameters!");
+ }
+ if (!values[0].IsVectorResult)
+ {
+ return new ComputationResult("AsHorizontal at position " + Start + " was executed with a parameter that was not a vector!");
+ }
+ return new ComputationResult(values[0], ComputationResult.VectorDirection.Horizontal);
+ case FunctionType.AsVertical:
+ if (values.Length != 1)
+ {
+ return new ComputationResult("AsVertical at position " + Start + " was executed with the wrong number of parameters!");
+ }
+ if (!values[0].IsVectorResult)
+ {
+ return new ComputationResult("AsVertical at position " + Start + " was executed with a parameter that was not a vector!");
+ }
+ return new ComputationResult(values[0], ComputationResult.VectorDirection.Vertical);
+ case FunctionType.Transpose:
+ {
if (values.Length != 1)
{
- return new ComputationResult("AsVertical at position " + Start + " was executed with the wrong number of parameters!");
- }
- if (!values[0].IsVectorResult)
- {
- return new ComputationResult("AsVertical at position " + Start + " was executed with a parameter that was not a vector!");
+ return new ComputationResult("Transpose at position " + Start + " was executed with the wrong number of parameters!");
}
- return new ComputationResult(values[0], ComputationResult.VectorDirection.Vertical);
- case FunctionType.Transpose:
+ if (values[0].IsVectorResult)
{
- if (values.Length != 1)
+ switch (values[0].Direction)
{
- return new ComputationResult("Transpose at position " + Start + " was executed with the wrong number of parameters!");
+ case ComputationResult.VectorDirection.Horizontal:
+ return new ComputationResult(values[0], ComputationResult.VectorDirection.Vertical);
+ case ComputationResult.VectorDirection.Vertical:
+ return new ComputationResult(values[0], ComputationResult.VectorDirection.Horizontal);
+ case ComputationResult.VectorDirection.Unassigned:
+ return new ComputationResult("Unable to transpose an vector that does not have a directionality!");
}
- if (values[0].IsVectorResult)
- {
- switch (values[0].Direction)
- {
- case ComputationResult.VectorDirection.Horizontal:
- return new ComputationResult(values[0], ComputationResult.VectorDirection.Vertical);
- case ComputationResult.VectorDirection.Vertical:
- return new ComputationResult(values[0], ComputationResult.VectorDirection.Horizontal);
- case ComputationResult.VectorDirection.Unassigned:
- return new ComputationResult("Unable to transpose an vector that does not have a directionality!");
- }
- }
- if (values[0].IsValue)
- {
- return new ComputationResult("The parameter to Transpose at position " + Start + " was executed against a scalar!");
- }
- if (values[0].IsOdResult)
- {
- return TransposeOd(values[0]);
- }
- return new ComputationResult("Unsupported data type for Transpose at position " + Start + ".");
- }
- case FunctionType.SumRows:
- if (values.Length != 1)
- {
- return new ComputationResult("SumRows was executed with the wrong number of parameters!");
- }
- if (!values[0].IsOdResult)
- {
- return new ComputationResult("SumRows was executed with a parameter that was not a matrix!");
- }
- return SumRows(values[0]);
- case FunctionType.SumColumns:
- if (values.Length != 1)
- {
- return new ComputationResult("SumColumns was executed with the wrong number of parameters!");
- }
- if (!values[0].IsOdResult)
- {
- return new ComputationResult("SumColumns was executed with a parameter that was not a matrix!");
- }
- return SumColumns(values[0]);
- case FunctionType.AvgRows:
- if (values.Length != 1)
- {
- return new ComputationResult("AvgRows was executed with the wrong number of parameters!");
- }
- if (!values[0].IsOdResult)
- {
- return new ComputationResult("AvgRows was executed with a parameter that was not a matrix!");
- }
- return AvgRows(values[0]);
- case FunctionType.AvgColumns:
- if (values.Length != 1)
- {
- return new ComputationResult("AvgColumns was executed with the wrong number of parameters!");
- }
- if (!values[0].IsOdResult)
- {
- return new ComputationResult("AvgColumns was executed with a parameter that was not a matrix!");
- }
- return AvgColumns(values[0]);
- case FunctionType.Sum:
- if (values.Length != 1)
- {
- return new ComputationResult("Sum was executed with the wrong number of parameters!");
}
if (values[0].IsValue)
{
- return new ComputationResult("Sum was executed with a parameter that was already a scalar value!");
- }
- return Sum(values[0]);
- case FunctionType.Abs:
- if (values.Length != 1)
- {
- return new ComputationResult("Abs was executed with the wrong number of parameters!");
- }
- return Abs(values[0]);
- case FunctionType.Avg:
- if (values.Length != 1)
- {
- return new ComputationResult("Avg was executed with the wrong number of parameters!");
- }
- if (values[0].IsValue)
- {
- return new ComputationResult("Avg was executed with a parameter that was already a scalar value!");
- }
- return Avg(values[0]);
- case FunctionType.E:
- return new ComputationResult((float)Math.E);
- case FunctionType.Pi:
- return new ComputationResult((float)Math.PI);
- case FunctionType.Length:
- if (values.Length != 1)
- {
- return new ComputationResult("Length was executed with the wrong number of parameters!");
- }
- if (values[0].IsValue)
- {
- return new ComputationResult("Length can not be applied to a scalar!");
- }
- return Length(values[0]);
- case FunctionType.LengthColumns:
- if (values.Length != 1)
- {
- return new ComputationResult("LengthColumns was executed with the wrong number of parameters!");
- }
- if (values[0].IsOdResult)
- {
- return new ComputationResult("LengthColumns must be applied to a Matrix!");
- }
- return LengthColumns(values[0]);
- case FunctionType.LengthRows:
- if (values.Length != 1)
- {
- return new ComputationResult("LengthRows was executed with the wrong number of parameters!");
+ return new ComputationResult("The parameter to Transpose at position " + Start + " was executed against a scalar!");
}
if (values[0].IsOdResult)
{
- return new ComputationResult("LengthRows must be applied to a Matrix!");
- }
- return LengthRows(values[0]);
- case FunctionType.ZeroMatrix:
- if (values.Length != 1)
- {
- return new ComputationResult("ZeroMatrix was executed with the wrong number of parameters!");
- }
- if (values[0].IsValue)
- {
- return new ComputationResult("ZeroMatrix must be applied to a vector, or a matrix!");
- }
- return ZeroMatrix(values);
- case FunctionType.Matrix:
- if (values.Length != 1)
- {
- return new ComputationResult("Matrix was executed with the wrong number of parameters!");
- }
- if (!values[0].IsVectorResult)
- {
- return new ComputationResult("Matrix must be applied to a vector!");
- }
- return Matrix(values[0]);
- case FunctionType.IdentityMatrix:
- if (values.Length != 1)
- {
- return new ComputationResult("IdentityMatrix was executed with the wrong number of parameters!");
- }
- if (values[0].IsValue)
- {
- return new ComputationResult("IdentityMatrix must be applied to a vector, or a matrix!");
- }
- return IdentityMatrix(values[0]);
- case FunctionType.Log:
- if (values.Length != 1)
- {
- return new ComputationResult("Log must be executed with one parameter!");
- }
- return Log(values);
- case FunctionType.Sqrt:
- if (values.Length != 1)
- {
- return new ComputationResult("Sqrt must be executed with one parameter!");
- }
- return Sqrt(values);
- case FunctionType.If:
- if (values.Length != 3)
- {
- return new ComputationResult("If requires at 3 parameters (condition, valueIfTrue, valueIfFalse)!");
- }
- return ComputeIf(values);
- case FunctionType.IfNaN:
- if (values.Length != 2)
- {
- return new ComputationResult("IfNaN requires 2 parameters (original,replacement)!");
- }
- return ComputeIfNaN(values);
- case FunctionType.Normalize:
- if (values.Length != 1)
- {
- return new ComputationResult("Normalize requires 1 parameter, a matrix to be normalized.");
+ return TransposeOd(values[0]);
}
- return ComputeNormalize(values);
- case FunctionType.NormalizeColumns:
- if (values.Length != 1)
- {
- return new ComputationResult("NormalizeColumns requires 1 parameter, a matrix to be normalized.");
- }
- return ComputeNormalizeColumns(values);
- case FunctionType.NormalizeRows:
- if (values.Length != 1)
- {
- return new ComputationResult("NormalizeRows requires 1 parameter, a matrix to be normalized.");
- }
- return ComputeNormalizeRows(values);
-
- }
- return new ComputationResult("An undefined function was executed!");
- }
-
- private ComputationResult ComputeNormalizeColumns(ComputationResult[] values)
- {
- var toNormalize = values[0];
- if (toNormalize.IsValue)
- {
- return new ComputationResult($"{Start + 1}:Normalize requires its parameter to be of type Matrix, not a scalar.");
- }
- if (toNormalize.IsVectorResult)
- {
- return new ComputationResult($"{Start + 1}:Normalize requires its parameter to be of type Matrix, not a vector.");
- }
- var writeTo = toNormalize.Accumulator ? toNormalize.OdData : new Matrix(toNormalize.OdData);
- var readFrom = toNormalize.OdData;
- var rowLength = readFrom.RowCategories.Count;
- // This could be executed in parallel if proved to be more efficient
- var columnTotals = new float[readFrom.ColumnCategories.Count];
- var columnSpan = columnTotals.AsSpan();
- for (int i = 0; i < rowLength; i++)
- {
- var readRow = readFrom.GetRow(i);
- VectorHelper.Add(columnSpan, 0, columnSpan, 0, readRow, 0, readRow.Length);
- }
- System.Threading.Tasks.Parallel.For(0, rowLength, (int i) =>
- {
- var writeRow = writeTo.GetRow(i);
- var readRow = readFrom.GetRow(i);
- for (int j = 0; j < writeRow.Length; j++)
+ return new ComputationResult("Unsupported data type for Transpose at position " + Start + ".");
+ }
+ case FunctionType.SumRows:
+ if (values.Length != 1)
{
- writeRow[j] = columnTotals[j] != 0f ? readRow[j] / columnTotals[j] : 0f;
+ return new ComputationResult("SumRows was executed with the wrong number of parameters!");
}
- });
- return new ComputationResult(writeTo, true);
- }
-
- private ComputationResult ComputeNormalizeRows(ComputationResult[] values)
- {
- var toNormalize = values[0];
- if (toNormalize.IsValue)
- {
- return new ComputationResult($"{Start + 1}:Normalize requires its parameter to be of type Matrix, not a scalar.");
- }
- if (toNormalize.IsVectorResult)
- {
- return new ComputationResult($"{Start + 1}:Normalize requires its parameter to be of type Matrix, not a vector.");
- }
- var rowLength = toNormalize.OdData.RowCategories.Count;
- var writeTo = toNormalize.Accumulator ? toNormalize.OdData : new Matrix(toNormalize.OdData);
- var readFrom = toNormalize.OdData;
- System.Threading.Tasks.Parallel.For(0, rowLength, (int i) =>
- {
- var flatWrite = writeTo.GetRow(i);
- var flatRead = readFrom.GetRow(i);
- var denominator = VectorHelper.Sum(flatRead);
- if (denominator != 0f)
+ if (!values[0].IsOdResult)
{
- VectorHelper.Divide(flatWrite, flatRead, denominator);
+ return new ComputationResult("SumRows was executed with a parameter that was not a matrix!");
}
- else if (flatRead == flatWrite)
+ return SumRows(values[0]);
+ case FunctionType.SumColumns:
+ if (values.Length != 1)
{
- // we only need to accumulate if we are going to return a previously accumulated matrix.
- flatWrite.Fill(0f);
+ return new ComputationResult("SumColumns was executed with the wrong number of parameters!");
}
- });
- return new ComputationResult(writeTo, true);
+ if (!values[0].IsOdResult)
+ {
+ return new ComputationResult("SumColumns was executed with a parameter that was not a matrix!");
+ }
+ return SumColumns(values[0]);
+ case FunctionType.AvgRows:
+ if (values.Length != 1)
+ {
+ return new ComputationResult("AvgRows was executed with the wrong number of parameters!");
+ }
+ if (!values[0].IsOdResult)
+ {
+ return new ComputationResult("AvgRows was executed with a parameter that was not a matrix!");
+ }
+ return AvgRows(values[0]);
+ case FunctionType.AvgColumns:
+ if (values.Length != 1)
+ {
+ return new ComputationResult("AvgColumns was executed with the wrong number of parameters!");
+ }
+ if (!values[0].IsOdResult)
+ {
+ return new ComputationResult("AvgColumns was executed with a parameter that was not a matrix!");
+ }
+ return AvgColumns(values[0]);
+ case FunctionType.Sum:
+ if (values.Length != 1)
+ {
+ return new ComputationResult("Sum was executed with the wrong number of parameters!");
+ }
+ if (values[0].IsValue)
+ {
+ return new ComputationResult("Sum was executed with a parameter that was already a scalar value!");
+ }
+ return Sum(values[0]);
+ case FunctionType.Abs:
+ if (values.Length != 1)
+ {
+ return new ComputationResult("Abs was executed with the wrong number of parameters!");
+ }
+ return Abs(values[0]);
+ case FunctionType.Avg:
+ if (values.Length != 1)
+ {
+ return new ComputationResult("Avg was executed with the wrong number of parameters!");
+ }
+ if (values[0].IsValue)
+ {
+ return new ComputationResult("Avg was executed with a parameter that was already a scalar value!");
+ }
+ return Avg(values[0]);
+ case FunctionType.E:
+ return new ComputationResult((float)Math.E);
+ case FunctionType.Pi:
+ return new ComputationResult((float)Math.PI);
+ case FunctionType.Length:
+ if (values.Length != 1)
+ {
+ return new ComputationResult("Length was executed with the wrong number of parameters!");
+ }
+ if (values[0].IsValue)
+ {
+ return new ComputationResult("Length can not be applied to a scalar!");
+ }
+ return Length(values[0]);
+ case FunctionType.LengthColumns:
+ if (values.Length != 1)
+ {
+ return new ComputationResult("LengthColumns was executed with the wrong number of parameters!");
+ }
+ if (values[0].IsOdResult)
+ {
+ return new ComputationResult("LengthColumns must be applied to a Matrix!");
+ }
+ return LengthColumns(values[0]);
+ case FunctionType.LengthRows:
+ if (values.Length != 1)
+ {
+ return new ComputationResult("LengthRows was executed with the wrong number of parameters!");
+ }
+ if (values[0].IsOdResult)
+ {
+ return new ComputationResult("LengthRows must be applied to a Matrix!");
+ }
+ return LengthRows(values[0]);
+ case FunctionType.ZeroMatrix:
+ if (values.Length != 1)
+ {
+ return new ComputationResult("ZeroMatrix was executed with the wrong number of parameters!");
+ }
+ if (values[0].IsValue)
+ {
+ return new ComputationResult("ZeroMatrix must be applied to a vector, or a matrix!");
+ }
+ return ZeroMatrix(values);
+ case FunctionType.Matrix:
+ if (values.Length != 1)
+ {
+ return new ComputationResult("Matrix was executed with the wrong number of parameters!");
+ }
+ if (!values[0].IsVectorResult)
+ {
+ return new ComputationResult("Matrix must be applied to a vector!");
+ }
+ return Matrix(values[0]);
+ case FunctionType.IdentityMatrix:
+ if (values.Length != 1)
+ {
+ return new ComputationResult("IdentityMatrix was executed with the wrong number of parameters!");
+ }
+ if (values[0].IsValue)
+ {
+ return new ComputationResult("IdentityMatrix must be applied to a vector, or a matrix!");
+ }
+ return IdentityMatrix(values[0]);
+ case FunctionType.Log:
+ if (values.Length != 1)
+ {
+ return new ComputationResult("Log must be executed with one parameter!");
+ }
+ return Log(values);
+ case FunctionType.Sqrt:
+ if (values.Length != 1)
+ {
+ return new ComputationResult("Sqrt must be executed with one parameter!");
+ }
+ return Sqrt(values);
+ case FunctionType.If:
+ if (values.Length != 3)
+ {
+ return new ComputationResult("If requires at 3 parameters (condition, valueIfTrue, valueIfFalse)!");
+ }
+ return ComputeIf(values);
+ case FunctionType.IfNaN:
+ if (values.Length != 2)
+ {
+ return new ComputationResult("IfNaN requires 2 parameters (original,replacement)!");
+ }
+ return ComputeIfNaN(values);
+ case FunctionType.Normalize:
+ if (values.Length != 1)
+ {
+ return new ComputationResult("Normalize requires 1 parameter, a matrix to be normalized.");
+ }
+ return ComputeNormalize(values);
+ case FunctionType.NormalizeColumns:
+ if (values.Length != 1)
+ {
+ return new ComputationResult("NormalizeColumns requires 1 parameter, a matrix to be normalized.");
+ }
+ return ComputeNormalizeColumns(values);
+ case FunctionType.NormalizeRows:
+ if (values.Length != 1)
+ {
+ return new ComputationResult("NormalizeRows requires 1 parameter, a matrix to be normalized.");
+ }
+ return ComputeNormalizeRows(values);
+
}
+ return new ComputationResult("An undefined function was executed!");
+ }
- private ComputationResult ComputeNormalize(ComputationResult[] values)
+ private ComputationResult ComputeNormalizeColumns(ComputationResult[] values)
+ {
+ var toNormalize = values[0];
+ if (toNormalize.IsValue)
{
- var toNormalize = values[0];
- if (toNormalize.IsValue)
- {
- return new ComputationResult($"{Start + 1}:Normalize requires its parameter to be of type Matrix, not a scalar.");
- }
- if (toNormalize.IsVectorResult)
+ return new ComputationResult($"{Start + 1}:Normalize requires its parameter to be of type Matrix, not a scalar.");
+ }
+ if (toNormalize.IsVectorResult)
+ {
+ return new ComputationResult($"{Start + 1}:Normalize requires its parameter to be of type Matrix, not a vector.");
+ }
+ var writeTo = toNormalize.Accumulator ? toNormalize.OdData : new Matrix(toNormalize.OdData);
+ var readFrom = toNormalize.OdData;
+ var rowLength = readFrom.RowCategories.Count;
+ // This could be executed in parallel if proved to be more efficient
+ var columnTotals = new float[readFrom.ColumnCategories.Count];
+ var columnSpan = columnTotals.AsSpan();
+ for (int i = 0; i < rowLength; i++)
+ {
+ var readRow = readFrom.GetRow(i);
+ VectorHelper.Add(columnSpan, 0, columnSpan, 0, readRow, 0, readRow.Length);
+ }
+ System.Threading.Tasks.Parallel.For(0, rowLength, (int i) =>
+ {
+ var writeRow = writeTo.GetRow(i);
+ var readRow = readFrom.GetRow(i);
+ for (int j = 0; j < writeRow.Length; j++)
{
- return new ComputationResult($"{Start + 1}:Normalize requires its parameter to be of type Matrix, not a vector.");
+ writeRow[j] = columnTotals[j] != 0f ? readRow[j] / columnTotals[j] : 0f;
}
- var writeTo = toNormalize.Accumulator ? toNormalize.OdData : new Matrix(toNormalize.OdData);
- var flatWrite = writeTo.Data;
- var flatRead = toNormalize.OdData.Data;
- // sum the whole matrix in parallel using SIMD for each array
+ });
+ return new ComputationResult(writeTo, true);
+ }
+
+ private ComputationResult ComputeNormalizeRows(ComputationResult[] values)
+ {
+ var toNormalize = values[0];
+ if (toNormalize.IsValue)
+ {
+ return new ComputationResult($"{Start + 1}:Normalize requires its parameter to be of type Matrix, not a scalar.");
+ }
+ if (toNormalize.IsVectorResult)
+ {
+ return new ComputationResult($"{Start + 1}:Normalize requires its parameter to be of type Matrix, not a vector.");
+ }
+ var rowLength = toNormalize.OdData.RowCategories.Count;
+ var writeTo = toNormalize.Accumulator ? toNormalize.OdData : new Matrix(toNormalize.OdData);
+ var readFrom = toNormalize.OdData;
+ System.Threading.Tasks.Parallel.For(0, rowLength, (int i) =>
+ {
+ var flatWrite = writeTo.GetRow(i);
+ var flatRead = readFrom.GetRow(i);
var denominator = VectorHelper.Sum(flatRead);
- if (denominator == 0f)
+ if (denominator != 0f)
{
- // only clear the write array if it was an accumulator
- if (flatRead == flatWrite)
- {
- flatWrite.Clear();
- }
+ VectorHelper.Divide(flatWrite, flatRead, denominator);
}
- else
+ else if (flatRead == flatWrite)
{
- VectorHelper.Divide(flatWrite, flatRead, denominator);
+ // we only need to accumulate if we are going to return a previously accumulated matrix.
+ flatWrite.Fill(0f);
}
- return new ComputationResult(writeTo, true);
- }
+ });
+ return new ComputationResult(writeTo, true);
+ }
- private ComputationResult ComputeIfNaN(ComputationResult[] values)
+ private ComputationResult ComputeNormalize(ComputationResult[] values)
+ {
+ var toNormalize = values[0];
+ if (toNormalize.IsValue)
{
- var condition = values[0];
- var replacement = values[1];
- // both must be the same size
- if (condition.IsValue && replacement.IsValue)
- {
- return new ComputationResult(!float.IsNaN(condition.LiteralValue) ? condition.LiteralValue : replacement.LiteralValue);
- }
- else if (condition.IsVectorResult && replacement.IsVectorResult)
- {
- var saveTo = values[0].Accumulator ? values[0].VectorData : new Vector(values[0].VectorData);
- VectorHelper.ReplaceIfNaN(saveTo.Data, condition.VectorData.Data, replacement.VectorData.Data);
- return new ComputationResult(saveTo, true, condition.Direction);
- }
- else if (condition.IsOdResult && replacement.IsOdResult)
+ return new ComputationResult($"{Start + 1}:Normalize requires its parameter to be of type Matrix, not a scalar.");
+ }
+ if (toNormalize.IsVectorResult)
+ {
+ return new ComputationResult($"{Start + 1}:Normalize requires its parameter to be of type Matrix, not a vector.");
+ }
+ var writeTo = toNormalize.Accumulator ? toNormalize.OdData : new Matrix(toNormalize.OdData);
+ var flatWrite = writeTo.Data;
+ var flatRead = toNormalize.OdData.Data;
+ // sum the whole matrix in parallel using SIMD for each array
+ var denominator = VectorHelper.Sum(flatRead);
+ if (denominator == 0f)
+ {
+ // only clear the write array if it was an accumulator
+ if (flatRead == flatWrite)
{
- var saveTo = values[0].Accumulator ? values[0].OdData : new Matrix(values[0].OdData);
- int rows = values[0].OdData.RowCategories.Count;
- var flatSave = saveTo.Data;
- var flatCond = condition.OdData.Data;
- var flatRep = replacement.OdData.Data;
- VectorHelper.ReplaceIfNaN(flatSave, flatCond, flatRep);
- return new ComputationResult(saveTo, true);
+ flatWrite.Clear();
}
- return new ComputationResult($"{Start + 1}:The Condition and Replacement case of an IfNaN expression must be of the same dimensionality.");
}
+ else
+ {
+ VectorHelper.Divide(flatWrite, flatRead, denominator);
+ }
+ return new ComputationResult(writeTo, true);
+ }
- private ComputationResult ComputeIf(ComputationResult[] values)
+ private ComputationResult ComputeIfNaN(ComputationResult[] values)
+ {
+ var condition = values[0];
+ var replacement = values[1];
+ // both must be the same size
+ if (condition.IsValue && replacement.IsValue)
{
- var condition = values[0];
- var ifTrue = values[1];
- var ifFalse = values[2];
- if ((ifTrue.IsValue & !ifFalse.IsValue)
- || (ifTrue.IsVectorResult & !ifFalse.IsVectorResult)
- || (ifTrue.IsOdResult & !ifFalse.IsOdResult))
- {
- return new ComputationResult($"{Start + 1}:The True and False case of an if expression must be of the same dimensionality.");
- }
- if (condition.IsValue)
+ return new ComputationResult(!float.IsNaN(condition.LiteralValue) ? condition.LiteralValue : replacement.LiteralValue);
+ }
+ else if (condition.IsVectorResult && replacement.IsVectorResult)
+ {
+ var saveTo = values[0].Accumulator ? values[0].VectorData : new Vector(values[0].VectorData);
+ VectorHelper.ReplaceIfNaN(saveTo.Data, condition.VectorData.Data, replacement.VectorData.Data);
+ return new ComputationResult(saveTo, true, condition.Direction);
+ }
+ else if (condition.IsOdResult && replacement.IsOdResult)
+ {
+ var saveTo = values[0].Accumulator ? values[0].OdData : new Matrix(values[0].OdData);
+ int rows = values[0].OdData.RowCategories.Count;
+ var flatSave = saveTo.Data;
+ var flatCond = condition.OdData.Data;
+ var flatRep = replacement.OdData.Data;
+ VectorHelper.ReplaceIfNaN(flatSave, flatCond, flatRep);
+ return new ComputationResult(saveTo, true);
+ }
+ return new ComputationResult($"{Start + 1}:The Condition and Replacement case of an IfNaN expression must be of the same dimensionality.");
+ }
+
+ private ComputationResult ComputeIf(ComputationResult[] values)
+ {
+ var condition = values[0];
+ var ifTrue = values[1];
+ var ifFalse = values[2];
+ if ((ifTrue.IsValue & !ifFalse.IsValue)
+ || (ifTrue.IsVectorResult & !ifFalse.IsVectorResult)
+ || (ifTrue.IsOdResult & !ifFalse.IsOdResult))
+ {
+ return new ComputationResult($"{Start + 1}:The True and False case of an if expression must be of the same dimensionality.");
+ }
+ if (condition.IsValue)
+ {
+ // in all cases we can just move the result to the next level
+ return condition.LiteralValue > 0f ? ifTrue : ifFalse;
+ }
+ else if (condition.IsVectorResult)
+ {
+ if (ifTrue.IsValue)
{
- // in all cases we can just move the result to the next level
- return condition.LiteralValue > 0f ? ifTrue : ifFalse;
+ var saveTo = values[0].Accumulator ? values[0].VectorData : new Vector(values[0].VectorData);
+ var result = saveTo.Data;
+ var cond = condition.VectorData.Data;
+ var t = ifTrue.LiteralValue;
+ var f = ifFalse.LiteralValue;
+ for (int i = 0; i < result.Length; i++)
+ {
+ result[i] = cond[i] > 0f ? t : f;
+ }
+ return new ComputationResult(saveTo, true, condition.Direction);
}
- else if (condition.IsVectorResult)
+ else if (ifTrue.IsVectorResult)
{
- if (ifTrue.IsValue)
- {
- var saveTo = values[0].Accumulator ? values[0].VectorData : new Vector(values[0].VectorData);
- var result = saveTo.Data;
- var cond = condition.VectorData.Data;
- var t = ifTrue.LiteralValue;
- var f = ifFalse.LiteralValue;
- for (int i = 0; i < result.Length; i++)
- {
- result[i] = cond[i] > 0f ? t : f;
- }
- return new ComputationResult(saveTo, true, condition.Direction);
- }
- else if (ifTrue.IsVectorResult)
+ var saveTo = values[0].Accumulator ? values[0].VectorData : new Vector(values[0].VectorData);
+ var result = saveTo.Data;
+ var cond = condition.VectorData.Data;
+ var t = ifTrue.VectorData.Data;
+ var f = ifFalse.VectorData.Data;
+ for (int i = 0; i < result.Length; i++)
{
- var saveTo = values[0].Accumulator ? values[0].VectorData : new Vector(values[0].VectorData);
- var result = saveTo.Data;
- var cond = condition.VectorData.Data;
- var t = ifTrue.VectorData.Data;
- var f = ifFalse.VectorData.Data;
- for (int i = 0; i < result.Length; i++)
- {
- result[i] = cond[i] > 0f ? t[i] : f[i];
- }
- return new ComputationResult(saveTo, true, condition.Direction);
+ result[i] = cond[i] > 0f ? t[i] : f[i];
}
- else
+ return new ComputationResult(saveTo, true, condition.Direction);
+ }
+ else
+ {
+ switch (condition.Direction)
{
- switch (condition.Direction)
- {
- case ComputationResult.VectorDirection.Unassigned:
- return new ComputationResult($"{Start + 1}:The directionality of the condition vector is required when working with a matrix values.");
- case ComputationResult.VectorDirection.Vertical:
+ case ComputationResult.VectorDirection.Unassigned:
+ return new ComputationResult($"{Start + 1}:The directionality of the condition vector is required when working with a matrix values.");
+ case ComputationResult.VectorDirection.Vertical:
+ {
+ var saveTo = values[1].Accumulator ? values[1].OdData : new Matrix(values[1].OdData);
+ var result = saveTo.Data;
+ var cond = condition.VectorData.Data;
+ var t = ifTrue.OdData.Data;
+ var f = ifFalse.OdData.Data;
+ for (int i = 0; i < cond.Length; i++)
{
- var saveTo = values[1].Accumulator ? values[1].OdData : new Matrix(values[1].OdData);
- var result = saveTo.Data;
- var cond = condition.VectorData.Data;
- var t = ifTrue.OdData.Data;
- var f = ifFalse.OdData.Data;
- for (int i = 0; i < cond.Length; i++)
- {
- var toAssign = cond[i] > 0 ? t : f;
- var rowOffset = i * cond.Length;
- toAssign.Slice(rowOffset, cond.Length).CopyTo(result.Slice(rowOffset, cond.Length));
- }
- return new ComputationResult(saveTo, true);
+ var toAssign = cond[i] > 0 ? t : f;
+ var rowOffset = i * cond.Length;
+ toAssign.Slice(rowOffset, cond.Length).CopyTo(result.Slice(rowOffset, cond.Length));
}
- case ComputationResult.VectorDirection.Horizontal:
+ return new ComputationResult(saveTo, true);
+ }
+ case ComputationResult.VectorDirection.Horizontal:
+ {
+ var saveTo = values[1].Accumulator ? values[1].OdData : new Matrix(values[1].OdData);
+ var result = saveTo.Data;
+ var cond = condition.VectorData.Data;
+ var t = ifTrue.OdData.Data;
+ var f = ifFalse.OdData.Data;
+ for (int i = 0; i < cond.Length; i++)
{
- var saveTo = values[1].Accumulator ? values[1].OdData : new Matrix(values[1].OdData);
- var result = saveTo.Data;
- var cond = condition.VectorData.Data;
- var t = ifTrue.OdData.Data;
- var f = ifFalse.OdData.Data;
- for (int i = 0; i < cond.Length; i++)
+ int rowOffset = i * cond.Length;
+ for (int j = 0; j < cond.Length; j++)
{
- int rowOffset = i * cond.Length;
- for (int j = 0; j < cond.Length; j++)
- {
- result[rowOffset + j] = cond[j] > 0 ? t[rowOffset + j] : f[rowOffset + j];
- }
+ result[rowOffset + j] = cond[j] > 0 ? t[rowOffset + j] : f[rowOffset + j];
}
- return new ComputationResult(saveTo, true);
}
- }
+ return new ComputationResult(saveTo, true);
+ }
}
}
- if (condition.IsOdResult)
- {
- if (!ifTrue.IsOdResult)
- {
- return new ComputationResult($"{Start + 1}:The True and False cases must be a Matrix when the condition is a matrix.");
- }
- var saveTo = values[0].Accumulator ? values[0].OdData : new Matrix(values[0].OdData);
- // this will never have a remainder
- System.Threading.Tasks.Parallel.For(0, condition.OdData.NumberOfRows, (int row) =>
- {
- var cond = condition.OdData.Data;
- var tr = ifTrue.OdData.Data;
- var fa = ifFalse.OdData.Data;
- var sa = saveTo.Data;
- var columnSize = condition.OdData.NumberOfColumns;
- var start = columnSize * row;
- var end = columnSize * (row + 1);
- for (int i = start; i < end; i++)
- {
- sa[i] = cond[i] > 0f ? tr[i] : fa[i];
- }
- });
+ }
+ if (condition.IsOdResult)
+ {
+ if (!ifTrue.IsOdResult)
+ {
+ return new ComputationResult($"{Start + 1}:The True and False cases must be a Matrix when the condition is a matrix.");
+ }
+ var saveTo = values[0].Accumulator ? values[0].OdData : new Matrix(values[0].OdData);
+ // this will never have a remainder
+ System.Threading.Tasks.Parallel.For(0, condition.OdData.NumberOfRows, (int row) =>
+ {
+ var cond = condition.OdData.Data;
+ var tr = ifTrue.OdData.Data;
+ var fa = ifFalse.OdData.Data;
+ var sa = saveTo.Data;
+ var columnSize = condition.OdData.NumberOfColumns;
+ var start = columnSize * row;
+ var end = columnSize * (row + 1);
+ for (int i = start; i < end; i++)
+ {
+ sa[i] = cond[i] > 0f ? tr[i] : fa[i];
+ }
+ });
- return new ComputationResult(saveTo, true);
- }
- return new ComputationResult($"{Start + 1}:This combination of parameter types has not been implemented for if!");
+ return new ComputationResult(saveTo, true);
}
+ return new ComputationResult($"{Start + 1}:This combination of parameter types has not been implemented for if!");
+ }
- private ComputationResult Log(ComputationResult[] values)
+ private ComputationResult Log(ComputationResult[] values)
+ {
+ if (values[0].IsValue)
{
- if (values[0].IsValue)
- {
- return new ComputationResult((float)Math.Log(values[0].LiteralValue));
- }
- else if (values[0].IsVectorResult)
- {
- var saveTo = values[0].Accumulator ? values[0].VectorData : new Vector(values[0].VectorData);
- var flat = saveTo.Data;
- var source = values[0].VectorData.Data;
- VectorHelper.Log(flat, source);
- return new ComputationResult(saveTo, true);
- }
- else
- {
- var saveTo = values[0].Accumulator ? values[0].OdData : new Matrix(values[0].OdData);
- var flat = saveTo.Data;
- var source = values[0].OdData.Data;
- VectorHelper.Log(flat, source);
- return new ComputationResult(saveTo, true);
- }
+ return new ComputationResult((float)Math.Log(values[0].LiteralValue));
}
+ else if (values[0].IsVectorResult)
+ {
+ var saveTo = values[0].Accumulator ? values[0].VectorData : new Vector(values[0].VectorData);
+ var flat = saveTo.Data;
+ var source = values[0].VectorData.Data;
+ VectorHelper.Log(flat, source);
+ return new ComputationResult(saveTo, true);
+ }
+ else
+ {
+ var saveTo = values[0].Accumulator ? values[0].OdData : new Matrix(values[0].OdData);
+ var flat = saveTo.Data;
+ var source = values[0].OdData.Data;
+ VectorHelper.Log(flat, source);
+ return new ComputationResult(saveTo, true);
+ }
+ }
- private ComputationResult Sqrt(ComputationResult[] values)
+ private ComputationResult Sqrt(ComputationResult[] values)
+ {
+ if (values[0].IsValue)
{
- if (values[0].IsValue)
- {
- return new ComputationResult((float)Math.Sqrt(values[0].LiteralValue));
- }
- else if (values[0].IsVectorResult)
- {
- var saveTo = values[0].Accumulator ? values[0].VectorData : new Vector(values[0].VectorData);
- var source = values[0].VectorData.Data;
- var flat = saveTo.Data;
- // x^0.5 is sqrt
- VectorHelper.Pow(flat, source, 0.5f);
- return new ComputationResult(saveTo, true);
- }
- else
- {
- var saveTo = values[0].Accumulator ? values[0].OdData : new Matrix(values[0].OdData);
- var source = values[0].OdData.Data;
- var flat = saveTo.Data;
- // x^0.5 is sqrt
- VectorHelper.Pow(flat, source, 0.5f);
- return new ComputationResult(saveTo, true);
- }
+ return new ComputationResult((float)Math.Sqrt(values[0].LiteralValue));
+ }
+ else if (values[0].IsVectorResult)
+ {
+ var saveTo = values[0].Accumulator ? values[0].VectorData : new Vector(values[0].VectorData);
+ var source = values[0].VectorData.Data;
+ var flat = saveTo.Data;
+ // x^0.5 is sqrt
+ VectorHelper.Pow(flat, source, 0.5f);
+ return new ComputationResult(saveTo, true);
}
+ else
+ {
+ var saveTo = values[0].Accumulator ? values[0].OdData : new Matrix(values[0].OdData);
+ var source = values[0].OdData.Data;
+ var flat = saveTo.Data;
+ // x^0.5 is sqrt
+ VectorHelper.Pow(flat, source, 0.5f);
+ return new ComputationResult(saveTo, true);
+ }
+ }
- private ComputationResult IdentityMatrix(ComputationResult computationResult)
+ private ComputationResult IdentityMatrix(ComputationResult computationResult)
+ {
+ Matrix ret;
+ if (computationResult.IsVectorResult)
{
- Matrix ret;
- if (computationResult.IsVectorResult)
- {
- var vector = computationResult.VectorData;
- ret = new Matrix(vector);
- }
- else
- {
- var matrix = computationResult.OdData;
- ret = new Matrix(matrix);
- }
- var step = ret.RowCategories.Count + 1;
- var flatRet = ret.Data;
- for (int i = 0; i < flatRet.Length; i += step)
- {
- flatRet[i] = 1.0f;
- }
- return new ComputationResult(ret, true);
+ var vector = computationResult.VectorData;
+ ret = new Matrix(vector);
+ }
+ else
+ {
+ var matrix = computationResult.OdData;
+ ret = new Matrix(matrix);
}
+ var step = ret.RowCategories.Count + 1;
+ var flatRet = ret.Data;
+ for (int i = 0; i < flatRet.Length; i += step)
+ {
+ flatRet[i] = 1.0f;
+ }
+ return new ComputationResult(ret, true);
+ }
- private ComputationResult Matrix(ComputationResult computationResult)
+ private ComputationResult Matrix(ComputationResult computationResult)
+ {
+ var vectorData = computationResult.VectorData;
+ var newMatrix = new Matrix(vectorData);
+ var rowSize = newMatrix.RowCategories.Count;
+ var flatVector = vectorData.Data;
+ var flatMatrix = newMatrix.Data;
+ switch (computationResult.Direction)
{
- var vectorData = computationResult.VectorData;
- var newMatrix = new Matrix(vectorData);
- var rowSize = newMatrix.RowCategories.Count;
- var flatVector = vectorData.Data;
- var flatMatrix = newMatrix.Data;
- switch (computationResult.Direction)
- {
- case ComputationResult.VectorDirection.Unassigned:
- return new ComputationResult("Matrix was executed with an unassigned orientation vector!");
- case ComputationResult.VectorDirection.Vertical:
- // each row is the single value
- for (int i = 0; i < flatVector.Length; i++)
- {
- VectorHelper.Set(flatMatrix.Slice(i * rowSize, rowSize), flatVector[i]);
- }
- break;
- case ComputationResult.VectorDirection.Horizontal:
- // each column is the single value
- for (int i = 0; i < newMatrix.NumberOfRows; i++)
- {
- flatVector.CopyTo(newMatrix.GetRow(i));
- }
- break;
- }
- return new ComputationResult(newMatrix, true);
+ case ComputationResult.VectorDirection.Unassigned:
+ return new ComputationResult("Matrix was executed with an unassigned orientation vector!");
+ case ComputationResult.VectorDirection.Vertical:
+ // each row is the single value
+ for (int i = 0; i < flatVector.Length; i++)
+ {
+ VectorHelper.Set(flatMatrix.Slice(i * rowSize, rowSize), flatVector[i]);
+ }
+ break;
+ case ComputationResult.VectorDirection.Horizontal:
+ // each column is the single value
+ for (int i = 0; i < newMatrix.NumberOfRows; i++)
+ {
+ flatVector.CopyTo(newMatrix.GetRow(i));
+ }
+ break;
}
+ return new ComputationResult(newMatrix, true);
+ }
- private ComputationResult ZeroMatrix(ComputationResult[] values)
+ private ComputationResult ZeroMatrix(ComputationResult[] values)
+ {
+ if (values[0].VectorData != null)
{
- if (values[0].VectorData != null)
- {
- return new ComputationResult(new Matrix(values[0].VectorData), true);
- }
- else
- {
- return new ComputationResult(new Matrix(values[0].OdData), true);
- }
+ return new ComputationResult(new Matrix(values[0].VectorData), true);
+ }
+ else
+ {
+ return new ComputationResult(new Matrix(values[0].OdData), true);
}
+ }
- private ComputationResult Avg(ComputationResult computationResult)
+ private ComputationResult Avg(ComputationResult computationResult)
+ {
+ if (computationResult.IsVectorResult)
{
- if (computationResult.IsVectorResult)
- {
- var flat = computationResult.VectorData.Data;
- return new ComputationResult(VectorHelper.Sum(flat) / flat.Length);
- }
- else
- {
- var flat = computationResult.OdData.Data;
- return new ComputationResult(VectorHelper.Sum(flat) / flat.Length);
- }
+ var flat = computationResult.VectorData.Data;
+ return new ComputationResult(VectorHelper.Sum(flat) / flat.Length);
}
+ else
+ {
+ var flat = computationResult.OdData.Data;
+ return new ComputationResult(VectorHelper.Sum(flat) / flat.Length);
+ }
+ }
- private ComputationResult Abs(ComputationResult computationResult)
+ private ComputationResult Abs(ComputationResult computationResult)
+ {
+ if (computationResult.IsValue)
{
- if (computationResult.IsValue)
- {
- return new ComputationResult(Math.Abs(computationResult.LiteralValue));
- }
- else if (computationResult.IsVectorResult)
- {
- var retVector = computationResult.Accumulator ? computationResult.VectorData : new Vector(computationResult.VectorData);
- var flat = retVector.Data;
- VectorHelper.Abs(flat, computationResult.VectorData.Data);
- return new ComputationResult(retVector, true);
- }
- else
- {
- var retMatrix = computationResult.Accumulator ? computationResult.OdData : new Matrix(computationResult.OdData);
- var flat = retMatrix.Data;
- VectorHelper.Abs(flat, computationResult.OdData.Data);
- return new ComputationResult(retMatrix, true);
- }
+ return new ComputationResult(Math.Abs(computationResult.LiteralValue));
+ }
+ else if (computationResult.IsVectorResult)
+ {
+ var retVector = computationResult.Accumulator ? computationResult.VectorData : new Vector(computationResult.VectorData);
+ var flat = retVector.Data;
+ VectorHelper.Abs(flat, computationResult.VectorData.Data);
+ return new ComputationResult(retVector, true);
+ }
+ else
+ {
+ var retMatrix = computationResult.Accumulator ? computationResult.OdData : new Matrix(computationResult.OdData);
+ var flat = retMatrix.Data;
+ VectorHelper.Abs(flat, computationResult.OdData.Data);
+ return new ComputationResult(retMatrix, true);
}
+ }
- private ComputationResult Sum(ComputationResult computationResult)
+ private ComputationResult Sum(ComputationResult computationResult)
+ {
+ if (computationResult.IsVectorResult)
{
- if (computationResult.IsVectorResult)
- {
- return new ComputationResult(VectorHelper.Sum(computationResult.VectorData.Data));
- }
- else if (computationResult.IsOdResult)
- {
- var data = computationResult.OdData.Data;
- var total = VectorHelper.Sum(data);
- return new ComputationResult(total);
- }
- return new ComputationResult("Unknown data type to sum!");
+ return new ComputationResult(VectorHelper.Sum(computationResult.VectorData.Data));
+ }
+ else if (computationResult.IsOdResult)
+ {
+ var data = computationResult.OdData.Data;
+ var total = VectorHelper.Sum(data);
+ return new ComputationResult(total);
}
+ return new ComputationResult("Unknown data type to sum!");
+ }
- private ComputationResult TransposeOd(ComputationResult computationResult)
+ private ComputationResult TransposeOd(ComputationResult computationResult)
+ {
+ var ret = computationResult.Accumulator ? computationResult.OdData : new Matrix(computationResult.OdData);
+ var flatRet = ret.Data;
+ var flatOrigin = computationResult.OdData.Data;
+ var rowLength = ret.RowCategories.Count;
+ for (int i = 0; i < rowLength; i++)
{
- var ret = computationResult.Accumulator ? computationResult.OdData : new Matrix(computationResult.OdData);
- var flatRet = ret.Data;
- var flatOrigin = computationResult.OdData.Data;
- var rowLength = ret.RowCategories.Count;
- for (int i = 0; i < rowLength; i++)
+ for (int j = i + 1; j < rowLength; j++)
{
- for (int j = i + 1; j < rowLength; j++)
- {
- var temp = flatOrigin[i * rowLength + j];
- flatRet[i * rowLength + j] = flatOrigin[j * rowLength + i];
- flatRet[j * rowLength + i] = temp;
- }
+ var temp = flatOrigin[i * rowLength + j];
+ flatRet[i * rowLength + j] = flatOrigin[j * rowLength + i];
+ flatRet[j * rowLength + i] = temp;
}
- // if this is a new matrix copy the diagonal
- if (!computationResult.Accumulator)
+ }
+ // if this is a new matrix copy the diagonal
+ if (!computationResult.Accumulator)
+ {
+ for (int i = 0; i < rowLength; i++)
{
- for (int i = 0; i < rowLength; i++)
- {
- flatRet[i * rowLength] = flatOrigin[i * rowLength];
- }
+ flatRet[i * rowLength] = flatOrigin[i * rowLength];
}
- return new ComputationResult(ret, true);
}
+ return new ComputationResult(ret, true);
+ }
- private ComputationResult SumColumns(ComputationResult computationResult)
+ private ComputationResult SumColumns(ComputationResult computationResult)
+ {
+ var ret = new Vector(computationResult.OdData.RowCategories);
+ var flatRet = ret.Data;
+ var flatData = computationResult.OdData.Data;
+ var rowSize = ret.Categories.Count;
+ for (int i = 0; i < flatRet.Length; i++)
{
- var ret = new Vector(computationResult.OdData.RowCategories);
- var flatRet = ret.Data;
- var flatData = computationResult.OdData.Data;
- var rowSize = ret.Categories.Count;
- for (int i = 0; i < flatRet.Length; i++)
- {
- VectorHelper.Add(flatRet, 0, flatRet, 0, flatData, i * rowSize, rowSize);
- }
- return new ComputationResult(ret, true, ComputationResult.VectorDirection.Horizontal);
+ VectorHelper.Add(flatRet, 0, flatRet, 0, flatData, i * rowSize, rowSize);
}
+ return new ComputationResult(ret, true, ComputationResult.VectorDirection.Horizontal);
+ }
- private ComputationResult SumRows(ComputationResult computationResult)
+ private ComputationResult SumRows(ComputationResult computationResult)
+ {
+ var ret = new Vector(computationResult.OdData.RowCategories);
+ var flatRet = ret.Data;
+ var flatData = computationResult.OdData;
+ var rowSize = ret.Categories.Count;
+ for (int i = 0; i < flatRet.Length; i++)
{
- var ret = new Vector(computationResult.OdData.RowCategories);
- var flatRet = ret.Data;
- var flatData = computationResult.OdData;
- var rowSize = ret.Categories.Count;
- for (int i = 0; i < flatRet.Length; i++)
- {
- flatRet[i] = VectorHelper.Sum(flatData.GetRow(i));
- }
- return new ComputationResult(ret, true, ComputationResult.VectorDirection.Vertical);
+ flatRet[i] = VectorHelper.Sum(flatData.GetRow(i));
}
+ return new ComputationResult(ret, true, ComputationResult.VectorDirection.Vertical);
+ }
- private ComputationResult AvgColumns(ComputationResult computationResult)
+ private ComputationResult AvgColumns(ComputationResult computationResult)
+ {
+ var data = computationResult.OdData;
+ var ret = new Vector(data.RowCategories);
+ var flatRet = ret.Data;
+ var flatData = data.Data;
+ var rowSize = ret.Categories.Count;
+ for (int i = 0; i < flatRet.Length; i++)
{
- var data = computationResult.OdData;
- var ret = new Vector(data.RowCategories);
- var flatRet = ret.Data;
- var flatData = data.Data;
- var rowSize = ret.Categories.Count;
- for (int i = 0; i < flatRet.Length; i++)
- {
- VectorHelper.Add(flatRet, 0, flatRet, 0, flatData, i * rowSize, rowSize);
- }
- VectorHelper.Multiply(flatRet, flatRet, 1.0f / flatRet.Length);
- return new ComputationResult(ret, true, ComputationResult.VectorDirection.Horizontal);
+ VectorHelper.Add(flatRet, 0, flatRet, 0, flatData, i * rowSize, rowSize);
}
+ VectorHelper.Multiply(flatRet, flatRet, 1.0f / flatRet.Length);
+ return new ComputationResult(ret, true, ComputationResult.VectorDirection.Horizontal);
+ }
- private ComputationResult AvgRows(ComputationResult computationResult)
+ private ComputationResult AvgRows(ComputationResult computationResult)
+ {
+ var data = computationResult.OdData;
+ var ret = new Vector(data.RowCategories);
+ var flatRet = ret.Data;
+ var rowSize = ret.Categories.Count;
+ for (int i = 0; i < flatRet.Length; i++)
{
- var data = computationResult.OdData;
- var ret = new Vector(data.RowCategories);
- var flatRet = ret.Data;
- var rowSize = ret.Categories.Count;
- for (int i = 0; i < flatRet.Length; i++)
- {
- flatRet[i] = VectorHelper.Sum(data.GetRow(i));
- }
- VectorHelper.Multiply(flatRet, flatRet, 1.0f / flatRet.Length);
- return new ComputationResult(ret, true, ComputationResult.VectorDirection.Vertical);
+ flatRet[i] = VectorHelper.Sum(data.GetRow(i));
}
+ VectorHelper.Multiply(flatRet, flatRet, 1.0f / flatRet.Length);
+ return new ComputationResult(ret, true, ComputationResult.VectorDirection.Vertical);
+ }
- private ComputationResult Length(ComputationResult computationResult)
+ private ComputationResult Length(ComputationResult computationResult)
+ {
+ if (computationResult.IsOdResult)
{
- if (computationResult.IsOdResult)
- {
- return new ComputationResult(computationResult.OdData.Data.Length);
- }
- if (computationResult.IsVectorResult)
- {
- return new ComputationResult(computationResult.VectorData.Data.Length);
- }
- return new ComputationResult("An unknown data type was processed through Length!");
+ return new ComputationResult(computationResult.OdData.Data.Length);
+ }
+ if (computationResult.IsVectorResult)
+ {
+ return new ComputationResult(computationResult.VectorData.Data.Length);
}
+ return new ComputationResult("An unknown data type was processed through Length!");
+ }
- private ComputationResult LengthRows(ComputationResult computationResult)
+ private ComputationResult LengthRows(ComputationResult computationResult)
+ {
+ if (computationResult.IsOdResult)
{
- if (computationResult.IsOdResult)
- {
- var data = computationResult.OdData;
- var ret = new Vector(data.RowCategories);
- var flatRet = ret.Data;
- var flatData = data.Data;
- VectorHelper.Set(flatData, flatRet.Length);
- return new ComputationResult(ret, true, ComputationResult.VectorDirection.Vertical);
- }
- return new ComputationResult("An unknown data type was processed through LengthRows!");
+ var data = computationResult.OdData;
+ var ret = new Vector(data.RowCategories);
+ var flatRet = ret.Data;
+ var flatData = data.Data;
+ VectorHelper.Set(flatData, flatRet.Length);
+ return new ComputationResult(ret, true, ComputationResult.VectorDirection.Vertical);
}
+ return new ComputationResult("An unknown data type was processed through LengthRows!");
+ }
- private ComputationResult LengthColumns(ComputationResult computationResult)
+ private ComputationResult LengthColumns(ComputationResult computationResult)
+ {
+ if (computationResult.IsOdResult)
{
- if (computationResult.IsOdResult)
- {
- var data = computationResult.OdData;
- var ret = new Vector(data.RowCategories);
- var flatRet = ret.Data;
- var flatData = data.Data;
- VectorHelper.Set(flatData, flatRet.Length);
- return new ComputationResult(ret, true, ComputationResult.VectorDirection.Horizontal);
- }
- return new ComputationResult("An unknown data type was processed through LengthColumns!");
+ var data = computationResult.OdData;
+ var ret = new Vector(data.RowCategories);
+ var flatRet = ret.Data;
+ var flatData = data.Data;
+ VectorHelper.Set(flatData, flatRet.Length);
+ return new ComputationResult(ret, true, ComputationResult.VectorDirection.Horizontal);
}
+ return new ComputationResult("An unknown data type was processed through LengthColumns!");
}
}
diff --git a/src/TMG-Framework/Processing/AST/FusedMultiplyAdd.cs b/src/TMG-Framework/Processing/AST/FusedMultiplyAdd.cs
index ecd19e7..335acc3 100644
--- a/src/TMG-Framework/Processing/AST/FusedMultiplyAdd.cs
+++ b/src/TMG-Framework/Processing/AST/FusedMultiplyAdd.cs
@@ -17,436 +17,289 @@ You should have received a copy of the GNU General Public License
along with XTMF. If not, see .
*/
-using XTMF2;
using TMG.Utilities;
-using System;
-using System.Threading.Tasks;
-using System.Security.Cryptography;
-using System.Diagnostics.CodeAnalysis;
-namespace TMG.Frameworks.Data.Processing.AST
+namespace TMG.Frameworks.Data.Processing.AST;
+
+public sealed class FusedMultiplyAdd : Expression
{
- public sealed class FusedMultiplyAdd : Expression
- {
- public Expression? MulLhs;
- public Expression? MulRhs;
- public Expression? Add;
- private int AddStart;
+ public Expression? MulLhs;
+ public Expression? MulRhs;
+ public Expression? Add;
+ private int AddStart;
- public FusedMultiplyAdd(int mulStart, int addStart) : base(mulStart)
- {
- AddStart = addStart;
- }
+ public FusedMultiplyAdd(int mulStart, int addStart) : base(mulStart)
+ {
+ AddStart = addStart;
+ }
- public override ComputationResult Evaluate(IModule[] dataSources)
+ public override ComputationResult Evaluate(IModule[] dataSources)
+ {
+ ComputationResult mulLhs = null!;
+ ComputationResult mulRhs = null!;
+ ComputationResult add = null!;
+ if (MulLhs is null || MulRhs is null || Add is null)
{
- ComputationResult mulLhs = null!;
- ComputationResult mulRhs = null!;
- ComputationResult add = null!;
- if (MulLhs is null || MulRhs is null || Add is null)
- {
- return new ComputationResult("Unable to evaluate FusedMultiplyAdd with null operands starting at position " + Start + "!");
- }
- Parallel.Invoke(
- () => mulLhs = MulLhs.Evaluate(dataSources),
- () => mulRhs = MulRhs.Evaluate(dataSources),
- () => add = Add.Evaluate(dataSources));
+ return new ComputationResult("Unable to evaluate FusedMultiplyAdd with null operands starting at position " + Start + "!");
+ }
+ Parallel.Invoke(
+ () => mulLhs = MulLhs.Evaluate(dataSources),
+ () => mulRhs = MulRhs.Evaluate(dataSources),
+ () => add = Add.Evaluate(dataSources));
- // mulLhs = MulLhs.Evaluate(dataSources);
- // mulRhs = MulRhs.Evaluate(dataSources);
- // add = Add.Evaluate(dataSources);
+ // mulLhs = MulLhs.Evaluate(dataSources);
+ // mulRhs = MulRhs.Evaluate(dataSources);
+ // add = Add.Evaluate(dataSources);
- if (mulLhs.Error)
- {
- return mulLhs;
- }
- else if (mulRhs.Error)
- {
- return mulRhs;
- }
- else if (add.Error)
- {
- return add;
- }
- if (!ValidateSizes(mulLhs, mulRhs, Start, out var error))
- {
- return error;
- }
- if (!ValidateSizes(mulRhs, add, AddStart, out var error2))
- {
- return error2;
- }
- return Evaluate(mulLhs, mulRhs, add);
+ if (mulLhs.Error)
+ {
+ return mulLhs;
+ }
+ else if (mulRhs.Error)
+ {
+ return mulRhs;
+ }
+ else if (add.Error)
+ {
+ return add;
}
+ if (!ValidateSizes(mulLhs, mulRhs, Start, out var error))
+ {
+ return error;
+ }
+ if (!ValidateSizes(mulRhs, add, AddStart, out var error2))
+ {
+ return error2;
+ }
+ return Evaluate(mulLhs, mulRhs, add);
+ }
- private ComputationResult Evaluate(ComputationResult mulLhs, ComputationResult mulRhs, ComputationResult add)
+ private ComputationResult Evaluate(ComputationResult mulLhs, ComputationResult mulRhs, ComputationResult add)
+ {
+ if (add.IsValue)
{
- if (add.IsValue)
- {
- return EvaluateAddIsValue(mulLhs, mulRhs, add);
- }
- else if (add.IsVectorResult)
- {
- return EvaluateAddIsVector(mulLhs, mulRhs, add);
- }
- else
- {
- return EvaluateAddIsMatrix(mulLhs, mulRhs, add);
- }
+ return EvaluateAddIsValue(mulLhs, mulRhs, add);
+ }
+ else if (add.IsVectorResult)
+ {
+ return EvaluateAddIsVector(mulLhs, mulRhs, add);
+ }
+ else
+ {
+ return EvaluateAddIsMatrix(mulLhs, mulRhs, add);
}
+ }
- private ComputationResult EvaluateAddIsValue(ComputationResult lhs, ComputationResult rhs, ComputationResult add)
+ private ComputationResult EvaluateAddIsValue(ComputationResult lhs, ComputationResult rhs, ComputationResult add)
+ {
+ if (add.IsValue && lhs.IsValue && rhs.IsValue)
+ {
+ return new ComputationResult(lhs.LiteralValue * rhs.LiteralValue + add.LiteralValue);
+ }
+ // float / matrix
+ if (lhs.IsValue)
{
- if (add.IsValue && lhs.IsValue && rhs.IsValue)
+ if (rhs.IsVectorResult)
{
- return new ComputationResult(lhs.LiteralValue * rhs.LiteralValue + add.LiteralValue);
+ var retVector = rhs.Accumulator ? rhs.VectorData : new Vector(rhs.VectorData);
+ var flat = retVector.Data;
+ VectorHelper.FusedMultiplyAdd(flat, rhs.VectorData.Data, lhs.LiteralValue, add.LiteralValue);
+ return new ComputationResult(retVector, true);
}
- // float / matrix
- if (lhs.IsValue)
+ else
{
- if (rhs.IsVectorResult)
- {
- var retVector = rhs.Accumulator ? rhs.VectorData : new Vector(rhs.VectorData);
- var flat = retVector.Data;
- VectorHelper.FusedMultiplyAdd(flat, rhs.VectorData.Data, lhs.LiteralValue, add.LiteralValue);
- return new ComputationResult(retVector, true);
- }
- else
+ var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData);
+ // inverted lhs, rhs since order does not matter
+ var flatRet = retMatrix.Data;
+ var flatLhs = lhs.LiteralValue;
+ var flatRhs = rhs.OdData.Data;
+ var flatAdd = add.LiteralValue;
+ var rowSize = retMatrix.RowCategories.Count;
+ for (int i = 0; i < rowSize; i++)
{
- var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData);
- // inverted lhs, rhs since order does not matter
- var flatRet = retMatrix.Data;
- var flatLhs = lhs.LiteralValue;
- var flatRhs = rhs.OdData.Data;
- var flatAdd = add.LiteralValue;
- var rowSize = retMatrix.RowCategories.Count;
- for (int i = 0; i < rowSize; i++)
- {
- VectorHelper.FusedMultiplyAdd(flatRet, flatRhs,
- flatLhs, flatAdd);
- }
- return new ComputationResult(retMatrix, true);
+ VectorHelper.FusedMultiplyAdd(flatRet, flatRhs,
+ flatLhs, flatAdd);
}
+ return new ComputationResult(retMatrix, true);
}
- else if (rhs.IsValue)
+ }
+ else if (rhs.IsValue)
+ {
+ if (lhs.IsVectorResult)
{
- if (lhs.IsVectorResult)
- {
- var retVector = lhs.Accumulator ? lhs.VectorData : new Vector(lhs.VectorData);
- var flat = retVector.Data;
- VectorHelper.FusedMultiplyAdd(flat, lhs.VectorData.Data, lhs.LiteralValue, add.LiteralValue);
- return new ComputationResult(retVector, true);
- }
- else
- {
- // matrix / float
- var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
- VectorHelper.FusedMultiplyAdd(retMatrix.Data, lhs.OdData.Data, rhs.LiteralValue, add.LiteralValue);
- return new ComputationResult(retMatrix, true);
- }
+ var retVector = lhs.Accumulator ? lhs.VectorData : new Vector(lhs.VectorData);
+ var flat = retVector.Data;
+ VectorHelper.FusedMultiplyAdd(flat, lhs.VectorData.Data, lhs.LiteralValue, add.LiteralValue);
+ return new ComputationResult(retVector, true);
}
else
{
- if (lhs.IsVectorResult || rhs.IsVectorResult)
- {
- if (lhs.IsVectorResult && rhs.IsVectorResult)
- {
- var retVector = lhs.Accumulator ? lhs.VectorData : (rhs.Accumulator ? rhs.VectorData : new Vector(lhs.VectorData));
- VectorHelper.FusedMultiplyAdd(retVector.Data, lhs.VectorData.Data, rhs.VectorData.Data, add.LiteralValue);
- return new ComputationResult(retVector, true, lhs.Direction);
- }
- else if (lhs.IsVectorResult)
- {
- var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData);
- var flatLhs = lhs.VectorData.Data;
- var rowSize = flatLhs.Length;
- if (lhs.Direction == ComputationResult.VectorDirection.Vertical)
- {
- for (int i = 0; i < rowSize; i++)
- {
- var retRow = retMatrix.GetRow(i);
- var rhsRow = rhs.OdData.GetRow(i);
- VectorHelper.FusedMultiplyAdd(retRow, rhsRow, flatLhs[i], add.LiteralValue);
- }
- }
- else if (lhs.Direction == ComputationResult.VectorDirection.Horizontal)
- {
- for (int i = 0; i < rowSize; i++)
- {
- var retRow = retMatrix.GetRow(i);
- var rhsRow = rhs.OdData.GetRow(i);
- VectorHelper.FusedMultiplyAdd(retRow, rhsRow, flatLhs, add.LiteralValue);
- }
- }
- else
- {
- return new ComputationResult("Unable to add vector without directionality starting at position " + (MulLhs?.Start ?? -1) + "!");
- }
- return new ComputationResult(retMatrix, true);
- }
- else
- {
- var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
- var flatRhs = rhs.VectorData.Data;
- var rowSize = flatRhs.Length;
- if (rhs.Direction == ComputationResult.VectorDirection.Vertical)
- {
- for (int i = 0; i < rowSize; i++)
- {
- var retRow = retMatrix.GetRow(i);
- var lhsRow = lhs.OdData.GetRow(i);
- VectorHelper.FusedMultiplyAdd(retRow, lhsRow, flatRhs[i], add.LiteralValue);
- }
- }
- else if (rhs.Direction == ComputationResult.VectorDirection.Horizontal)
- {
- for (int i = 0; i < rowSize; i++)
- {
- var retRow = retMatrix.GetRow(i);
- var lhsRow = lhs.OdData.GetRow(i);
- VectorHelper.FusedMultiplyAdd(retRow, lhsRow, flatRhs, add.LiteralValue);
- }
- }
- else
- {
- return new ComputationResult("Unable to add vector without directionality starting at position " + (MulLhs?.Start ?? -1) + "!");
- }
- return new ComputationResult(retMatrix, true);
- }
- }
- else
- {
- var retMatrix = lhs.Accumulator ? lhs.OdData : (rhs.Accumulator ? rhs.OdData : new Matrix(lhs.OdData));
- var flatAdd = add.LiteralValue;
- var rowSize = retMatrix.RowCategories.Count;
-
- VectorHelper.FusedMultiplyAdd(retMatrix.Data, lhs.OdData.Data,
- rhs.OdData.Data, flatAdd);
-
- return new ComputationResult(retMatrix, true);
- }
+ // matrix / float
+ var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
+ VectorHelper.FusedMultiplyAdd(retMatrix.Data, lhs.OdData.Data, rhs.LiteralValue, add.LiteralValue);
+ return new ComputationResult(retMatrix, true);
}
}
-
- private static void Swap(ref T first, ref T second) where T : class
- {
- var temp = first;
- first = second;
- second = temp;
- }
-
- private ComputationResult EvaluateAddIsVector(ComputationResult lhs, ComputationResult rhs, ComputationResult add)
+ else
{
- // Test the simple case of this really just being an add with a constant multiply
- if (lhs.IsValue && rhs.IsValue)
+ if (lhs.IsVectorResult || rhs.IsVectorResult)
{
- var retVector = add.Accumulator ? add.VectorData : new Vector(add.VectorData);
- VectorHelper.Add(retVector.Data, add.VectorData.Data, lhs.LiteralValue * rhs.LiteralValue);
- return new ComputationResult(retVector, true, add.Direction);
- }
- if (lhs.IsOdResult || rhs.IsOdResult)
- {
- if (lhs.IsVectorResult && lhs.Direction == ComputationResult.VectorDirection.Unassigned)
+ if (lhs.IsVectorResult && rhs.IsVectorResult)
{
- return new ComputationResult("Unable to multiply vector without directionality starting at position " + (MulLhs?.Start ?? -1) + "!");
+ var retVector = lhs.Accumulator ? lhs.VectorData : (rhs.Accumulator ? rhs.VectorData : new Vector(lhs.VectorData));
+ VectorHelper.FusedMultiplyAdd(retVector.Data, lhs.VectorData.Data, rhs.VectorData.Data, add.LiteralValue);
+ return new ComputationResult(retVector, true, lhs.Direction);
}
- if (rhs.IsVectorResult && lhs.Direction == ComputationResult.VectorDirection.Unassigned)
+ else if (lhs.IsVectorResult)
{
- return new ComputationResult("Unable to multiply vector without directionality starting at position " + (MulRhs?.Start ?? -1) + "!");
- }
- if (add.Direction == ComputationResult.VectorDirection.Unassigned)
- {
- return new ComputationResult("Unable to add vector without directionality starting at position " + (Add?.Start ?? -1) + "!");
- }
- // if the lhs is a value just swap the two around
- if (!lhs.IsOdResult)
- {
- Swap(ref lhs, ref rhs);
- }
- //LHS is a matrix
- if (rhs.IsOdResult)
- {
- var retMatrix = rhs.Accumulator ? rhs.OdData :
- (lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData));
- var rowSize = add.VectorData.Data.Length;
- if (add.Direction == ComputationResult.VectorDirection.Vertical)
+ var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData);
+ var flatLhs = lhs.VectorData.Data;
+ var rowSize = flatLhs.Length;
+ if (lhs.Direction == ComputationResult.VectorDirection.Vertical)
{
for (int i = 0; i < rowSize; i++)
{
var retRow = retMatrix.GetRow(i);
- var lhsRow = lhs.OdData.GetRow(i);
var rhsRow = rhs.OdData.GetRow(i);
- VectorHelper.FusedMultiplyAdd(retRow, lhsRow, rhsRow, add.VectorData[i]);
+ VectorHelper.FusedMultiplyAdd(retRow, rhsRow, flatLhs[i], add.LiteralValue);
}
}
- else
+ else if (lhs.Direction == ComputationResult.VectorDirection.Horizontal)
{
for (int i = 0; i < rowSize; i++)
{
var retRow = retMatrix.GetRow(i);
- var lhsRow = lhs.OdData.GetRow(i);
var rhsRow = rhs.OdData.GetRow(i);
- VectorHelper.FusedMultiplyAdd(retRow, lhsRow, rhsRow, add.VectorData.Data);
- }
- }
- return new ComputationResult(retMatrix, true);
- }
- else if (rhs.IsVectorResult)
- {
- var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
- var rowSize = add.VectorData.Data.Length;
- if (rhs.Direction == ComputationResult.VectorDirection.Vertical)
- {
- if (add.Direction == ComputationResult.VectorDirection.Vertical)
- {
- for (int i = 0; i < rowSize; i++)
- {
- var retRow = retMatrix.GetRow(i);
- var lhsRow = lhs.OdData.GetRow(i);
- VectorHelper.FusedMultiplyAdd(retRow, lhsRow, rhs.VectorData.Data[i], add.VectorData.Data[i]);
- }
- }
- else
- {
- for (int i = 0; i < rowSize; i++)
- {
- var retRow = retMatrix.GetRow(i);
- var lhsRow = lhs.OdData.GetRow(i);
- VectorHelper.FusedMultiplyAdd(retRow, lhsRow, rhs.VectorData.Data[i], add.VectorData.Data);
- }
+ VectorHelper.FusedMultiplyAdd(retRow, rhsRow, flatLhs, add.LiteralValue);
}
}
else
{
- if (add.Direction == ComputationResult.VectorDirection.Vertical)
- {
- for (int i = 0; i < rowSize; i++)
- {
- var retRow = retMatrix.GetRow(i);
- var lhsRow = lhs.OdData.GetRow(i);
- VectorHelper.FusedMultiplyAdd(retRow, lhsRow, rhs.VectorData.Data, add.VectorData.Data[i]);
- }
- }
- else
- {
- for (int i = 0; i < rowSize; i++)
- {
- var retRow = retMatrix.GetRow(i);
- var lhsRow = lhs.OdData.GetRow(i);
- VectorHelper.FusedMultiplyAdd(retRow, lhsRow, rhs.VectorData.Data, add.VectorData.Data);
- }
- }
+ return new ComputationResult("Unable to add vector without directionality starting at position " + (MulLhs?.Start ?? -1) + "!");
}
return new ComputationResult(retMatrix, true);
}
else
{
- //RHS is a scalar
var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
- var rowSize = add.VectorData.Data.Length;
- if (add.Direction == ComputationResult.VectorDirection.Vertical)
+ var flatRhs = rhs.VectorData.Data;
+ var rowSize = flatRhs.Length;
+ if (rhs.Direction == ComputationResult.VectorDirection.Vertical)
{
for (int i = 0; i < rowSize; i++)
{
var retRow = retMatrix.GetRow(i);
var lhsRow = lhs.OdData.GetRow(i);
- VectorHelper.FusedMultiplyAdd(retRow, lhsRow, rhs.LiteralValue, add.VectorData.Data[i]);
+ VectorHelper.FusedMultiplyAdd(retRow, lhsRow, flatRhs[i], add.LiteralValue);
}
}
- else
+ else if (rhs.Direction == ComputationResult.VectorDirection.Horizontal)
{
for (int i = 0; i < rowSize; i++)
{
var retRow = retMatrix.GetRow(i);
var lhsRow = lhs.OdData.GetRow(i);
- VectorHelper.FusedMultiplyAdd(retRow, lhsRow, rhs.LiteralValue, add.VectorData.Data);
+ VectorHelper.FusedMultiplyAdd(retRow, lhsRow, flatRhs, add.LiteralValue);
}
}
+ else
+ {
+ return new ComputationResult("Unable to add vector without directionality starting at position " + (MulLhs?.Start ?? -1) + "!");
+ }
return new ComputationResult(retMatrix, true);
}
}
- // vector cases
else
{
- // if the lhs is a value just swap the two around
- if (lhs.IsValue)
- {
- Swap(ref lhs, ref rhs);
- }
- // vector * vector + vector
- if (rhs.IsVectorResult)
- {
- var retVector = add.Accumulator ? add.VectorData :
- (rhs.Accumulator ? rhs.VectorData :
- (lhs.Accumulator ? lhs.VectorData : new Vector(lhs.VectorData)));
- VectorHelper.FusedMultiplyAdd(retVector.Data, lhs.VectorData.Data, rhs.VectorData.Data, add.VectorData.Data);
- return new ComputationResult(retVector, true, add.Direction == lhs.Direction && add.Direction == rhs.Direction ? add.Direction : ComputationResult.VectorDirection.Unassigned);
- }
- // vector * lit + vector
- else
- {
- var retVector = add.Accumulator ? add.VectorData :
- (lhs.Accumulator ? lhs.VectorData : new Vector(lhs.VectorData));
- VectorHelper.FusedMultiplyAdd(retVector.Data, lhs.VectorData.Data, rhs.LiteralValue,
- add.VectorData.Data);
- return new ComputationResult(retVector, true, add.Direction == lhs.Direction && add.Direction == rhs.Direction ? add.Direction : ComputationResult.VectorDirection.Unassigned);
- }
+ var retMatrix = lhs.Accumulator ? lhs.OdData : (rhs.Accumulator ? rhs.OdData : new Matrix(lhs.OdData));
+ var flatAdd = add.LiteralValue;
+ var rowSize = retMatrix.RowCategories.Count;
+
+ VectorHelper.FusedMultiplyAdd(retMatrix.Data, lhs.OdData.Data,
+ rhs.OdData.Data, flatAdd);
+
+ return new ComputationResult(retMatrix, true);
}
}
+ }
- private ComputationResult EvaluateAddIsMatrix(ComputationResult lhs, ComputationResult rhs, ComputationResult add)
+ private static void Swap(ref T first, ref T second) where T : class
+ {
+ var temp = first;
+ first = second;
+ second = temp;
+ }
+
+ private ComputationResult EvaluateAddIsVector(ComputationResult lhs, ComputationResult rhs, ComputationResult add)
+ {
+ // Test the simple case of this really just being an add with a constant multiply
+ if (lhs.IsValue && rhs.IsValue)
+ {
+ var retVector = add.Accumulator ? add.VectorData : new Vector(add.VectorData);
+ VectorHelper.Add(retVector.Data, add.VectorData.Data, lhs.LiteralValue * rhs.LiteralValue);
+ return new ComputationResult(retVector, true, add.Direction);
+ }
+ if (lhs.IsOdResult || rhs.IsOdResult)
{
if (lhs.IsVectorResult && lhs.Direction == ComputationResult.VectorDirection.Unassigned)
{
return new ComputationResult("Unable to multiply vector without directionality starting at position " + (MulLhs?.Start ?? -1) + "!");
}
- if (rhs.IsVectorResult && rhs.Direction == ComputationResult.VectorDirection.Unassigned)
+ if (rhs.IsVectorResult && lhs.Direction == ComputationResult.VectorDirection.Unassigned)
{
return new ComputationResult("Unable to multiply vector without directionality starting at position " + (MulRhs?.Start ?? -1) + "!");
}
- // Ensure that the LHS is a higher or equal order to the RHS (Matrix > Vector > Scalar)
- if (!lhs.IsOdResult)
+ if (add.Direction == ComputationResult.VectorDirection.Unassigned)
{
- Swap(ref lhs, ref rhs);
+ return new ComputationResult("Unable to add vector without directionality starting at position " + (Add?.Start ?? -1) + "!");
}
- if (lhs.IsValue)
+ // if the lhs is a value just swap the two around
+ if (!lhs.IsOdResult)
{
Swap(ref lhs, ref rhs);
}
- // LHS is now a higher or equal to the order of RHS
- if (lhs.IsOdResult)
+ //LHS is a matrix
+ if (rhs.IsOdResult)
{
- if (rhs.IsOdResult)
+ var retMatrix = rhs.Accumulator ? rhs.OdData :
+ (lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData));
+ var rowSize = add.VectorData.Data.Length;
+ if (add.Direction == ComputationResult.VectorDirection.Vertical)
{
- var retMatrix = add.Accumulator ? add.OdData :
- (lhs.Accumulator ? lhs.OdData :
- (rhs.Accumulator ? rhs.OdData : new Matrix(add.OdData)));
- var flatRet = retMatrix.Data;
- var flatLhs = lhs.OdData.Data;
- var flatRhs = rhs.OdData.Data;
- var flatAdd = add.OdData.Data;
- var rowSize = retMatrix.RowCategories.Count;
- VectorHelper.FusedMultiplyAdd(flatRet, flatLhs, flatRhs, flatAdd);
- return new ComputationResult(retMatrix, true);
+ for (int i = 0; i < rowSize; i++)
+ {
+ var retRow = retMatrix.GetRow(i);
+ var lhsRow = lhs.OdData.GetRow(i);
+ var rhsRow = rhs.OdData.GetRow(i);
+ VectorHelper.FusedMultiplyAdd(retRow, lhsRow, rhsRow, add.VectorData[i]);
+ }
}
- else if (rhs.IsVectorResult)
+ else
{
- var retMatrix = add.Accumulator ? add.OdData :
- (lhs.Accumulator ? lhs.OdData : new Matrix(add.OdData));
- var flatRet = retMatrix.Data;
- var flatLhs = lhs.OdData.Data;
- var flatRhs = rhs.VectorData.Data;
- var flatAdd = add.OdData.Data;
- var rowSize = retMatrix.RowCategories.Count;
- if (rhs.Direction == ComputationResult.VectorDirection.Vertical)
+ for (int i = 0; i < rowSize; i++)
+ {
+ var retRow = retMatrix.GetRow(i);
+ var lhsRow = lhs.OdData.GetRow(i);
+ var rhsRow = rhs.OdData.GetRow(i);
+ VectorHelper.FusedMultiplyAdd(retRow, lhsRow, rhsRow, add.VectorData.Data);
+ }
+ }
+ return new ComputationResult(retMatrix, true);
+ }
+ else if (rhs.IsVectorResult)
+ {
+ var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
+ var rowSize = add.VectorData.Data.Length;
+ if (rhs.Direction == ComputationResult.VectorDirection.Vertical)
+ {
+ if (add.Direction == ComputationResult.VectorDirection.Vertical)
{
for (int i = 0; i < rowSize; i++)
{
var retRow = retMatrix.GetRow(i);
var lhsRow = lhs.OdData.GetRow(i);
- var addRow = add.OdData.GetRow(i);
- VectorHelper.FusedMultiplyAdd(retRow, lhsRow, flatRhs[i], addRow);
+ VectorHelper.FusedMultiplyAdd(retRow, lhsRow, rhs.VectorData.Data[i], add.VectorData.Data[i]);
}
}
else
@@ -455,85 +308,227 @@ private ComputationResult EvaluateAddIsMatrix(ComputationResult lhs, Computation
{
var retRow = retMatrix.GetRow(i);
var lhsRow = lhs.OdData.GetRow(i);
- var addRow = add.OdData.GetRow(i);
- VectorHelper.FusedMultiplyAdd(retRow, lhsRow, flatRhs, addRow);
+ VectorHelper.FusedMultiplyAdd(retRow, lhsRow, rhs.VectorData.Data[i], add.VectorData.Data);
}
}
- return new ComputationResult(retMatrix, true);
}
else
{
- //RHS is scalar
- var retMatrix = add.Accumulator ? add.OdData :
- (lhs.Accumulator ? lhs.OdData : new Matrix(add.OdData));
- VectorHelper.FusedMultiplyAdd(retMatrix.Data, lhs.OdData.Data, rhs.LiteralValue, add.OdData.Data);
- return new ComputationResult(retMatrix, true);
+ if (add.Direction == ComputationResult.VectorDirection.Vertical)
+ {
+ for (int i = 0; i < rowSize; i++)
+ {
+ var retRow = retMatrix.GetRow(i);
+ var lhsRow = lhs.OdData.GetRow(i);
+ VectorHelper.FusedMultiplyAdd(retRow, lhsRow, rhs.VectorData.Data, add.VectorData.Data[i]);
+ }
+ }
+ else
+ {
+ for (int i = 0; i < rowSize; i++)
+ {
+ var retRow = retMatrix.GetRow(i);
+ var lhsRow = lhs.OdData.GetRow(i);
+ VectorHelper.FusedMultiplyAdd(retRow, lhsRow, rhs.VectorData.Data, add.VectorData.Data);
+ }
+ }
}
+ return new ComputationResult(retMatrix, true);
}
- else if (lhs.IsVectorResult)
+ else
{
- var retMatrix = add.Accumulator ? add.OdData : new Matrix(add.OdData);
- var tempVector = lhs.Accumulator ? lhs.VectorData : (rhs.IsVectorResult && rhs.Accumulator ? rhs.VectorData : new Vector(lhs.VectorData));
- var flatRet = retMatrix.Data;
- var flatAdd = add.OdData.Data;
- var rowSize = tempVector.Data.Length;
- // compute the multiplication separately in this case for better performance (n multiplies instead of n^2)
- if (rhs.IsVectorResult)
+ //RHS is a scalar
+ var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
+ var rowSize = add.VectorData.Data.Length;
+ if (add.Direction == ComputationResult.VectorDirection.Vertical)
{
- if (lhs.Direction != rhs.Direction)
+ for (int i = 0; i < rowSize; i++)
{
- // if the directions don't add up then the sum operation would be undefined!
- return new ComputationResult("Unable to add vector without directionality starting at position " + (MulLhs?.Start ?? -1) + "!");
+ var retRow = retMatrix.GetRow(i);
+ var lhsRow = lhs.OdData.GetRow(i);
+ VectorHelper.FusedMultiplyAdd(retRow, lhsRow, rhs.LiteralValue, add.VectorData.Data[i]);
}
- VectorHelper.Multiply(tempVector.Data, lhs.VectorData.Data, rhs.VectorData.Data);
}
else
{
- VectorHelper.Multiply(tempVector.Data, lhs.VectorData.Data, rhs.LiteralValue);
+ for (int i = 0; i < rowSize; i++)
+ {
+ var retRow = retMatrix.GetRow(i);
+ var lhsRow = lhs.OdData.GetRow(i);
+ VectorHelper.FusedMultiplyAdd(retRow, lhsRow, rhs.LiteralValue, add.VectorData.Data);
+ }
}
-
- if (lhs.Direction == ComputationResult.VectorDirection.Vertical)
+ return new ComputationResult(retMatrix, true);
+ }
+ }
+ // vector cases
+ else
+ {
+ // if the lhs is a value just swap the two around
+ if (lhs.IsValue)
+ {
+ Swap(ref lhs, ref rhs);
+ }
+ // vector * vector + vector
+ if (rhs.IsVectorResult)
+ {
+ var retVector = add.Accumulator ? add.VectorData :
+ (rhs.Accumulator ? rhs.VectorData :
+ (lhs.Accumulator ? lhs.VectorData : new Vector(lhs.VectorData)));
+ VectorHelper.FusedMultiplyAdd(retVector.Data, lhs.VectorData.Data, rhs.VectorData.Data, add.VectorData.Data);
+ return new ComputationResult(retVector, true, add.Direction == lhs.Direction && add.Direction == rhs.Direction ? add.Direction : ComputationResult.VectorDirection.Unassigned);
+ }
+ // vector * lit + vector
+ else
+ {
+ var retVector = add.Accumulator ? add.VectorData :
+ (lhs.Accumulator ? lhs.VectorData : new Vector(lhs.VectorData));
+ VectorHelper.FusedMultiplyAdd(retVector.Data, lhs.VectorData.Data, rhs.LiteralValue,
+ add.VectorData.Data);
+ return new ComputationResult(retVector, true, add.Direction == lhs.Direction && add.Direction == rhs.Direction ? add.Direction : ComputationResult.VectorDirection.Unassigned);
+ }
+ }
+ }
+
+ private ComputationResult EvaluateAddIsMatrix(ComputationResult lhs, ComputationResult rhs, ComputationResult add)
+ {
+ if (lhs.IsVectorResult && lhs.Direction == ComputationResult.VectorDirection.Unassigned)
+ {
+ return new ComputationResult("Unable to multiply vector without directionality starting at position " + (MulLhs?.Start ?? -1) + "!");
+ }
+ if (rhs.IsVectorResult && rhs.Direction == ComputationResult.VectorDirection.Unassigned)
+ {
+ return new ComputationResult("Unable to multiply vector without directionality starting at position " + (MulRhs?.Start ?? -1) + "!");
+ }
+ // Ensure that the LHS is a higher or equal order to the RHS (Matrix > Vector > Scalar)
+ if (!lhs.IsOdResult)
+ {
+ Swap(ref lhs, ref rhs);
+ }
+ if (lhs.IsValue)
+ {
+ Swap(ref lhs, ref rhs);
+ }
+ // LHS is now a higher or equal to the order of RHS
+ if (lhs.IsOdResult)
+ {
+ if (rhs.IsOdResult)
+ {
+ var retMatrix = add.Accumulator ? add.OdData :
+ (lhs.Accumulator ? lhs.OdData :
+ (rhs.Accumulator ? rhs.OdData : new Matrix(add.OdData)));
+ var flatRet = retMatrix.Data;
+ var flatLhs = lhs.OdData.Data;
+ var flatRhs = rhs.OdData.Data;
+ var flatAdd = add.OdData.Data;
+ var rowSize = retMatrix.RowCategories.Count;
+ VectorHelper.FusedMultiplyAdd(flatRet, flatLhs, flatRhs, flatAdd);
+ return new ComputationResult(retMatrix, true);
+ }
+ else if (rhs.IsVectorResult)
+ {
+ var retMatrix = add.Accumulator ? add.OdData :
+ (lhs.Accumulator ? lhs.OdData : new Matrix(add.OdData));
+ var flatRet = retMatrix.Data;
+ var flatLhs = lhs.OdData.Data;
+ var flatRhs = rhs.VectorData.Data;
+ var flatAdd = add.OdData.Data;
+ var rowSize = retMatrix.RowCategories.Count;
+ if (rhs.Direction == ComputationResult.VectorDirection.Vertical)
{
- Parallel.For(0, rowSize, (int i) =>
+ for (int i = 0; i < rowSize; i++)
{
- var flatTemp = tempVector.Data;
var retRow = retMatrix.GetRow(i);
+ var lhsRow = lhs.OdData.GetRow(i);
var addRow = add.OdData.GetRow(i);
- VectorHelper.Add(retRow, addRow, flatTemp[i]);
- });
+ VectorHelper.FusedMultiplyAdd(retRow, lhsRow, flatRhs[i], addRow);
+ }
}
else
{
- Parallel.For(0, rowSize, (int i) =>
+ for (int i = 0; i < rowSize; i++)
{
- var flatTemp = tempVector.Data;
var retRow = retMatrix.GetRow(i);
+ var lhsRow = lhs.OdData.GetRow(i);
var addRow = add.OdData.GetRow(i);
- VectorHelper.Add(retRow, flatTemp, addRow);
- });
+ VectorHelper.FusedMultiplyAdd(retRow, lhsRow, flatRhs, addRow);
+ }
}
return new ComputationResult(retMatrix, true);
}
else
{
- // in this case LHS is a scalar, and therefore RHS is also a scalar
- var retMatrix = add.Accumulator ? add.OdData : new Matrix(add.OdData);
- VectorHelper.Add(retMatrix.Data, add.OdData.Data, lhs.LiteralValue * rhs.LiteralValue);
+ //RHS is scalar
+ var retMatrix = add.Accumulator ? add.OdData :
+ (lhs.Accumulator ? lhs.OdData : new Matrix(add.OdData));
+ VectorHelper.FusedMultiplyAdd(retMatrix.Data, lhs.OdData.Data, rhs.LiteralValue, add.OdData.Data);
return new ComputationResult(retMatrix, true);
}
}
-
- internal override bool OptimizeAst(ref Expression ex,
- [NotNullWhen(false)] ref string? error)
+ else if (lhs.IsVectorResult)
{
- if (MulLhs is null || MulRhs is null || Add is null)
+ var retMatrix = add.Accumulator ? add.OdData : new Matrix(add.OdData);
+ var tempVector = lhs.Accumulator ? lhs.VectorData : (rhs.IsVectorResult && rhs.Accumulator ? rhs.VectorData : new Vector(lhs.VectorData));
+ var flatRet = retMatrix.Data;
+ var flatAdd = add.OdData.Data;
+ var rowSize = tempVector.Data.Length;
+ // compute the multiplication separately in this case for better performance (n multiplies instead of n^2)
+ if (rhs.IsVectorResult)
+ {
+ if (lhs.Direction != rhs.Direction)
+ {
+ // if the directions don't add up then the sum operation would be undefined!
+ return new ComputationResult("Unable to add vector without directionality starting at position " + (MulLhs?.Start ?? -1) + "!");
+ }
+ VectorHelper.Multiply(tempVector.Data, lhs.VectorData.Data, rhs.VectorData.Data);
+ }
+ else
{
- error = "Unable to optimize FusedMultiplyAdd with null operands starting at position " + Start + "!";
- return false;
+ VectorHelper.Multiply(tempVector.Data, lhs.VectorData.Data, rhs.LiteralValue);
}
- return !(!MulLhs.OptimizeAst(ref MulLhs, ref error)
- || !MulLhs.OptimizeAst(ref MulRhs, ref error)
- || !MulLhs.OptimizeAst(ref Add, ref error));
+
+ if (lhs.Direction == ComputationResult.VectorDirection.Vertical)
+ {
+ Parallel.For(0, rowSize, (int i) =>
+ {
+ var flatTemp = tempVector.Data;
+ var retRow = retMatrix.GetRow(i);
+ var addRow = add.OdData.GetRow(i);
+ VectorHelper.Add(retRow, addRow, flatTemp[i]);
+ });
+ }
+ else
+ {
+ Parallel.For(0, rowSize, (int i) =>
+ {
+ var flatTemp = tempVector.Data;
+ var retRow = retMatrix.GetRow(i);
+ var addRow = add.OdData.GetRow(i);
+ VectorHelper.Add(retRow, flatTemp, addRow);
+ });
+ }
+ return new ComputationResult(retMatrix, true);
}
+ else
+ {
+ // in this case LHS is a scalar, and therefore RHS is also a scalar
+ var retMatrix = add.Accumulator ? add.OdData : new Matrix(add.OdData);
+ VectorHelper.Add(retMatrix.Data, add.OdData.Data, lhs.LiteralValue * rhs.LiteralValue);
+ return new ComputationResult(retMatrix, true);
+ }
+ }
+
+ internal override bool OptimizeAst(ref Expression ex,
+ [NotNullWhen(false)] ref string? error)
+ {
+ if (MulLhs is null || MulRhs is null || Add is null)
+ {
+ error = "Unable to optimize FusedMultiplyAdd with null operands starting at position " + Start + "!";
+ return false;
+ }
+ return !(!MulLhs.OptimizeAst(ref MulLhs, ref error)
+ || !MulLhs.OptimizeAst(ref MulRhs, ref error)
+ || !MulLhs.OptimizeAst(ref Add, ref error));
}
}
+
diff --git a/src/TMG-Framework/Processing/AST/Multiply.cs b/src/TMG-Framework/Processing/AST/Multiply.cs
index 6da478d..239acb7 100644
--- a/src/TMG-Framework/Processing/AST/Multiply.cs
+++ b/src/TMG-Framework/Processing/AST/Multiply.cs
@@ -17,151 +17,149 @@ You should have received a copy of the GNU General Public License
along with XTMF. If not, see .
*/
-using System;
-using System.Diagnostics.CodeAnalysis;
using TMG.Utilities;
-namespace TMG.Frameworks.Data.Processing.AST
+namespace TMG.Frameworks.Data.Processing.AST;
+
+public sealed class Multiply : BinaryExpression
{
- public sealed class Multiply : BinaryExpression
+ public Multiply(int start) : base(start)
{
- public Multiply(int start) : base(start)
- {
+ }
+
+ internal override bool OptimizeAst(ref Expression ex,
+ [NotNullWhen(false)] ref string? error)
+ {
+ if (!base.OptimizeAst(ref ex, ref error))
+ {
+ return false;
+ }
+ var lhs = Lhs as Literal;
+ var rhs = Rhs as Literal;
+ if (lhs is not null && rhs is not null)
+ {
+ ex = new Literal(Start, lhs.Value * rhs.Value);
}
+ return true;
+ }
- internal override bool OptimizeAst(ref Expression ex,
- [NotNullWhen(false)] ref string? error)
+ public override ComputationResult Evaluate(ComputationResult lhs, ComputationResult rhs)
+ {
+ // see if we have two values, in this case we can skip doing the matrix operation
+ if (lhs.IsValue && rhs.IsValue)
+ {
+ return new ComputationResult(lhs.LiteralValue * rhs.LiteralValue);
+ }
+ // float / matrix
+ if (lhs.IsValue)
{
- if (!base.OptimizeAst(ref ex, ref error))
+ if (rhs.IsVectorResult)
{
- return false;
+ var retVector = rhs.Accumulator ? rhs.VectorData : new Vector(rhs.VectorData);
+ var flat = retVector.Data;
+ VectorHelper.Multiply(flat, rhs.VectorData.Data, lhs.LiteralValue);
+ return new ComputationResult(retVector, true);
}
- var lhs = Lhs as Literal;
- var rhs = Rhs as Literal;
- if (lhs is not null && rhs is not null)
+ else
{
- ex = new Literal(Start, lhs.Value * rhs.Value);
+ var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData);
+ VectorHelper.Multiply(retMatrix.Data, rhs.OdData.Data, lhs.LiteralValue);
+ return new ComputationResult(retMatrix, true);
}
- return true;
}
-
- public override ComputationResult Evaluate(ComputationResult lhs, ComputationResult rhs)
+ else if (rhs.IsValue)
{
- // see if we have two values, in this case we can skip doing the matrix operation
- if (lhs.IsValue && rhs.IsValue)
+ if (lhs.IsVectorResult)
{
- return new ComputationResult(lhs.LiteralValue * rhs.LiteralValue);
+ var retVector = lhs.Accumulator ? lhs.VectorData : new Vector(lhs.VectorData);
+ var flat = retVector.Data;
+ VectorHelper.Multiply(flat, lhs.VectorData.Data, rhs.LiteralValue);
+ return new ComputationResult(retVector, true);
}
- // float / matrix
- if (lhs.IsValue)
+ else
{
- if (rhs.IsVectorResult)
- {
- var retVector = rhs.Accumulator ? rhs.VectorData : new Vector(rhs.VectorData);
- var flat = retVector.Data;
- VectorHelper.Multiply(flat, rhs.VectorData.Data, lhs.LiteralValue);
- return new ComputationResult(retVector, true);
- }
- else
- {
- var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData);
- VectorHelper.Multiply(retMatrix.Data, rhs.OdData.Data, lhs.LiteralValue);
- return new ComputationResult(retMatrix, true);
- }
+ // matrix / float
+ var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
+ VectorHelper.Multiply(retMatrix.Data, lhs.OdData.Data, rhs.LiteralValue);
+ return new ComputationResult(retMatrix, true);
}
- else if (rhs.IsValue)
+ }
+ else
+ {
+ if (lhs.IsVectorResult || rhs.IsVectorResult)
{
- if (lhs.IsVectorResult)
+ if (lhs.IsVectorResult && rhs.IsVectorResult)
{
- var retVector = lhs.Accumulator ? lhs.VectorData : new Vector(lhs.VectorData);
- var flat = retVector.Data;
- VectorHelper.Multiply(flat, lhs.VectorData.Data, rhs.LiteralValue);
- return new ComputationResult(retVector, true);
+ var retMatrix = lhs.Accumulator ? lhs.VectorData : (rhs.Accumulator ? rhs.VectorData : new Vector(lhs.VectorData));
+ VectorHelper.Multiply(retMatrix.Data, lhs.VectorData.Data, rhs.VectorData.Data);
+ return new ComputationResult(retMatrix, true, lhs.Direction);
}
- else
- {
- // matrix / float
- var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
- VectorHelper.Multiply(retMatrix.Data, lhs.OdData.Data, rhs.LiteralValue);
- return new ComputationResult(retMatrix, true);
- }
- }
- else
- {
- if (lhs.IsVectorResult || rhs.IsVectorResult)
+ else if (lhs.IsVectorResult)
{
- if (lhs.IsVectorResult && rhs.IsVectorResult)
- {
- var retMatrix = lhs.Accumulator ? lhs.VectorData : (rhs.Accumulator ? rhs.VectorData : new Vector(lhs.VectorData));
- VectorHelper.Multiply(retMatrix.Data, lhs.VectorData.Data, rhs.VectorData.Data);
- return new ComputationResult(retMatrix, true, lhs.Direction);
- }
- else if (lhs.IsVectorResult)
+ var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData);
+ var flatLhs = lhs.VectorData.Data;
+ if (lhs.Direction == ComputationResult.VectorDirection.Vertical)
{
- var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData);
- var flatLhs = lhs.VectorData.Data;
- if (lhs.Direction == ComputationResult.VectorDirection.Vertical)
- {
- for (int i = 0; i < flatLhs.Length; i++)
- {
- var retRow = retMatrix.GetRow(i);
- var retRight = rhs.OdData.GetRow(i);
- VectorHelper.Multiply(retRow, retRight, flatLhs[i]);
- }
- }
- else if (lhs.Direction == ComputationResult.VectorDirection.Horizontal)
+ for (int i = 0; i < flatLhs.Length; i++)
{
- for (int i = 0; i < flatLhs.Length; i++)
- {
- var retRow = retMatrix.GetRow(i);
- var retRight = rhs.OdData.GetRow(i);
- VectorHelper.Multiply(retRow, retRight, flatLhs);
- }
+ var retRow = retMatrix.GetRow(i);
+ var retRight = rhs.OdData.GetRow(i);
+ VectorHelper.Multiply(retRow, retRight, flatLhs[i]);
}
- else
+ }
+ else if (lhs.Direction == ComputationResult.VectorDirection.Horizontal)
+ {
+ for (int i = 0; i < flatLhs.Length; i++)
{
- return new ComputationResult("Unable to multiply vector without directionality starting at position " + (Lhs?.Start ?? -1) + "!");
+ var retRow = retMatrix.GetRow(i);
+ var retRight = rhs.OdData.GetRow(i);
+ VectorHelper.Multiply(retRow, retRight, flatLhs);
}
- return new ComputationResult(retMatrix, true);
}
else
{
- var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
- var flatLhs = lhs.OdData.Data;
- var flatRhs = rhs.VectorData.Data;
- if (rhs.Direction == ComputationResult.VectorDirection.Vertical)
- {
- for (int i = 0; i < flatRhs.Length; i++)
- {
- var retRow = retMatrix.GetRow(i);
- var leftRow = lhs.OdData.GetRow(i);
- VectorHelper.Multiply(retRow, leftRow, flatRhs[i]);
- }
- }
- else if (rhs.Direction == ComputationResult.VectorDirection.Horizontal)
+ return new ComputationResult("Unable to multiply vector without directionality starting at position " + (Lhs?.Start ?? -1) + "!");
+ }
+ return new ComputationResult(retMatrix, true);
+ }
+ else
+ {
+ var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
+ var flatLhs = lhs.OdData.Data;
+ var flatRhs = rhs.VectorData.Data;
+ if (rhs.Direction == ComputationResult.VectorDirection.Vertical)
+ {
+ for (int i = 0; i < flatRhs.Length; i++)
{
- for (int i = 0; i < flatRhs.Length; i++)
- {
- var retRow = retMatrix.GetRow(i);
- var leftRow = lhs.OdData.GetRow(i);
- VectorHelper.Multiply(retRow, leftRow, flatRhs);
- }
+ var retRow = retMatrix.GetRow(i);
+ var leftRow = lhs.OdData.GetRow(i);
+ VectorHelper.Multiply(retRow, leftRow, flatRhs[i]);
}
- else
+ }
+ else if (rhs.Direction == ComputationResult.VectorDirection.Horizontal)
+ {
+ for (int i = 0; i < flatRhs.Length; i++)
{
- return new ComputationResult("Unable to multiply vector without directionality starting at position " + (Lhs?.Start ?? -1) + "!");
+ var retRow = retMatrix.GetRow(i);
+ var leftRow = lhs.OdData.GetRow(i);
+ VectorHelper.Multiply(retRow, leftRow, flatRhs);
}
- return new ComputationResult(retMatrix, true);
}
- }
- else
- {
- var retMatrix = lhs.Accumulator ? lhs.OdData : (rhs.Accumulator ? rhs.OdData : new Matrix(lhs.OdData));
- VectorHelper.Multiply(retMatrix.Data, lhs.OdData.Data, rhs.OdData.Data);
+ else
+ {
+ return new ComputationResult("Unable to multiply vector without directionality starting at position " + (Lhs?.Start ?? -1) + "!");
+ }
return new ComputationResult(retMatrix, true);
}
}
+ else
+ {
+ var retMatrix = lhs.Accumulator ? lhs.OdData : (rhs.Accumulator ? rhs.OdData : new Matrix(lhs.OdData));
+ VectorHelper.Multiply(retMatrix.Data, lhs.OdData.Data, rhs.OdData.Data);
+ return new ComputationResult(retMatrix, true);
+ }
}
}
}
+
diff --git a/src/TMG-Framework/Processing/AST/Negate.cs b/src/TMG-Framework/Processing/AST/Negate.cs
index 7b38df5..7959783 100644
--- a/src/TMG-Framework/Processing/AST/Negate.cs
+++ b/src/TMG-Framework/Processing/AST/Negate.cs
@@ -16,71 +16,64 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
You should have received a copy of the GNU General Public License
along with XTMF2. If not, see .
*/
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Diagnostics.CodeAnalysis;
+
using TMG.Utilities;
-using XTMF2;
-namespace TMG.Frameworks.Data.Processing.AST
+namespace TMG.Frameworks.Data.Processing.AST;
+
+public sealed class Negate : MonoExpression
{
- public sealed class Negate : MonoExpression
+ public Negate(int start) : base(start)
+ {
+ }
+
+ internal override bool OptimizeAst(ref Expression ex,
+ [NotNullWhen(false)] ref string? error)
{
- public Negate(int start) : base(start)
+ if (InnerExpression is null)
{
+ error = "Unable to optimize Negate with null operand starting at position " + Start + "!";
+ return false;
}
- internal override bool OptimizeAst(ref Expression ex,
- [NotNullWhen(false)] ref string? error)
+ // Optimize our children first
+ if (!InnerExpression.OptimizeAst(ref InnerExpression, ref error))
{
- if (InnerExpression is null)
- {
- error = "Unable to optimize Negate with null operand starting at position " + Start + "!";
- return false;
- }
-
- // Optimize our children first
- if (!InnerExpression.OptimizeAst(ref InnerExpression, ref error))
- {
- return false;
- }
- // optimize the case that we are a negative literal
- if (ex is Literal l)
- {
- ex = new Literal(Start, -l.Value);
- }
- return true;
+ return false;
+ }
+ // optimize the case that we are a negative literal
+ if (ex is Literal l)
+ {
+ ex = new Literal(Start, -l.Value);
}
+ return true;
+ }
- public override ComputationResult Evaluate(IModule[] dataSources)
+ public override ComputationResult Evaluate(IModule[] dataSources)
+ {
+ if (InnerExpression is null)
{
- if (InnerExpression is null)
- {
- return new ComputationResult("Unable to evaluate Negate with null operand starting at position " + Start + "!");
- }
+ return new ComputationResult("Unable to evaluate Negate with null operand starting at position " + Start + "!");
+ }
- var inner = InnerExpression.Evaluate(dataSources);
- if (inner.IsValue)
- {
- return new ComputationResult(-inner.LiteralValue);
- }
- else if (inner.IsVectorResult)
- {
- var ret = inner.Accumulator ? inner.VectorData : new Vector(inner.VectorData);
- VectorHelper.Negate(ret.Data, inner.VectorData.Data);
- return new ComputationResult(ret, true, inner.Direction);
- }
- else
- {
- var ret = inner.Accumulator ? inner.OdData : new Matrix(inner.OdData);
- var flatRet = ret.Data;
- var flatInner = inner.OdData.Data;
- VectorHelper.Negate(flatRet, flatInner);
- return new ComputationResult(ret, true);
- }
+ var inner = InnerExpression.Evaluate(dataSources);
+ if (inner.IsValue)
+ {
+ return new ComputationResult(-inner.LiteralValue);
+ }
+ else if (inner.IsVectorResult)
+ {
+ var ret = inner.Accumulator ? inner.VectorData : new Vector(inner.VectorData);
+ VectorHelper.Negate(ret.Data, inner.VectorData.Data);
+ return new ComputationResult(ret, true, inner.Direction);
+ }
+ else
+ {
+ var ret = inner.Accumulator ? inner.OdData : new Matrix(inner.OdData);
+ var flatRet = ret.Data;
+ var flatInner = inner.OdData.Data;
+ VectorHelper.Negate(flatRet, flatInner);
+ return new ComputationResult(ret, true);
}
}
}
diff --git a/src/TMG-Framework/Processing/AST/Subtract.cs b/src/TMG-Framework/Processing/AST/Subtract.cs
index 5b3328b..85dfa6d 100644
--- a/src/TMG-Framework/Processing/AST/Subtract.cs
+++ b/src/TMG-Framework/Processing/AST/Subtract.cs
@@ -17,152 +17,149 @@ You should have received a copy of the GNU General Public License
along with XTMF. If not, see .
*/
-using System;
-using System.Diagnostics.CodeAnalysis;
using TMG.Utilities;
-namespace TMG.Frameworks.Data.Processing.AST
+namespace TMG.Frameworks.Data.Processing.AST;
+
+public sealed class Subtract : BinaryExpression
{
- public sealed class Subtract : BinaryExpression
+ public Subtract(int start) : base(start)
{
- public Subtract(int start) : base(start)
- {
+ }
+
+ internal override bool OptimizeAst(ref Expression ex,
+ [NotNullWhen(false)] ref string? error)
+ {
+ if (!base.OptimizeAst(ref ex, ref error))
+ {
+ return false;
+ }
+ var lhs = Lhs as Literal;
+ var rhs = Rhs as Literal;
+ if (lhs != null && rhs != null)
+ {
+ ex = new Literal(Start, lhs.Value - rhs.Value);
}
+ return true;
+ }
- internal override bool OptimizeAst(ref Expression ex,
- [NotNullWhen(false)] ref string? error)
+ public override ComputationResult Evaluate(ComputationResult lhs, ComputationResult rhs)
+ {
+ // see if we have two values, in this case we can skip doing the matrix operation
+ if (lhs.IsValue && rhs.IsValue)
+ {
+ return new ComputationResult(lhs.LiteralValue - rhs.LiteralValue);
+ }
+ // float / matrix
+ if (lhs.IsValue)
{
- if(!base.OptimizeAst(ref ex, ref error))
+ if (rhs.IsVectorResult)
{
- return false;
+ var retVector = rhs.Accumulator ? rhs.VectorData : new Vector(rhs.VectorData);
+ var flat = retVector.Data;
+ VectorHelper.Subtract(flat, lhs.LiteralValue, rhs.VectorData.Data);
+ return new ComputationResult(retVector, true);
}
- var lhs = Lhs as Literal;
- var rhs = Rhs as Literal;
- if (lhs != null && rhs != null)
+ else
{
- ex = new Literal(Start, lhs.Value - rhs.Value);
+ var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData);
+ VectorHelper.Subtract(retMatrix.Data, lhs.LiteralValue, rhs.OdData.Data);
+ return new ComputationResult(retMatrix, true);
}
- return true;
}
-
- public override ComputationResult Evaluate(ComputationResult lhs, ComputationResult rhs)
+ else if (rhs.IsValue)
{
- // see if we have two values, in this case we can skip doing the matrix operation
- if (lhs.IsValue && rhs.IsValue)
+ if (lhs.IsVectorResult)
{
- return new ComputationResult(lhs.LiteralValue - rhs.LiteralValue);
+ var retVector = lhs.Accumulator ? lhs.VectorData : new Vector(lhs.VectorData);
+ var flat = retVector.Data;
+ VectorHelper.Subtract(flat, lhs.VectorData.Data, rhs.LiteralValue);
+ return new ComputationResult(retVector, true);
}
- // float / matrix
- if (lhs.IsValue)
+ else
{
- if (rhs.IsVectorResult)
- {
- var retVector = rhs.Accumulator ? rhs.VectorData : new Vector(rhs.VectorData);
- var flat = retVector.Data;
- VectorHelper.Subtract(flat, lhs.LiteralValue, rhs.VectorData.Data);
- return new ComputationResult(retVector, true);
- }
- else
- {
- var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData);
- VectorHelper.Subtract(retMatrix.Data, lhs.LiteralValue, rhs.OdData.Data);
- return new ComputationResult(retMatrix, true);
- }
+ // matrix / float
+ var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
+ VectorHelper.Subtract(retMatrix.Data, lhs.OdData.Data, rhs.LiteralValue);
+ return new ComputationResult(retMatrix, true);
}
- else if (rhs.IsValue)
+ }
+ else
+ {
+ if (lhs.IsVectorResult || rhs.IsVectorResult)
{
- if (lhs.IsVectorResult)
+ if (lhs.IsVectorResult && rhs.IsVectorResult)
{
- var retVector = lhs.Accumulator ? lhs.VectorData : new Vector(lhs.VectorData);
- var flat = retVector.Data;
- VectorHelper.Subtract(flat, lhs.VectorData.Data, rhs.LiteralValue);
- return new ComputationResult(retVector, true);
+ var retMatrix = lhs.Accumulator ? lhs.VectorData : (rhs.Accumulator ? rhs.VectorData : new Vector(lhs.VectorData));
+ VectorHelper.Subtract(retMatrix.Data, lhs.VectorData.Data, rhs.VectorData.Data);
+ return new ComputationResult(retMatrix, true, lhs.Direction);
}
- else
+ else if (lhs.IsVectorResult)
{
- // matrix / float
- var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
- VectorHelper.Subtract(retMatrix.Data, lhs.OdData.Data, rhs.LiteralValue);
- return new ComputationResult(retMatrix, true);
- }
- }
- else
- {
- if (lhs.IsVectorResult || rhs.IsVectorResult)
- {
- if (lhs.IsVectorResult && rhs.IsVectorResult)
- {
- var retMatrix = lhs.Accumulator ? lhs.VectorData : (rhs.Accumulator ? rhs.VectorData : new Vector(lhs.VectorData));
- VectorHelper.Subtract(retMatrix.Data, lhs.VectorData.Data, rhs.VectorData.Data);
- return new ComputationResult(retMatrix, true, lhs.Direction);
- }
- else if (lhs.IsVectorResult)
+ var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData);
+ var flatLhs = lhs.VectorData.Data;
+ var rowSize = flatLhs.Length;
+ if (lhs.Direction == ComputationResult.VectorDirection.Vertical)
{
- var retMatrix = rhs.Accumulator ? rhs.OdData : new Matrix(rhs.OdData);
- var flatLhs = lhs.VectorData.Data;
- var rowSize = flatLhs.Length;
- if (lhs.Direction == ComputationResult.VectorDirection.Vertical)
- {
- for (int i = 0; i < rowSize; i++)
- {
- var retRow = retMatrix.GetRow(i);
- var rhsRow = rhs.OdData.GetRow(i);
- VectorHelper.Subtract(retRow, flatLhs[i], rhsRow);
- }
- }
- else if (lhs.Direction == ComputationResult.VectorDirection.Horizontal)
+ for (int i = 0; i < rowSize; i++)
{
- for (int i = 0; i < rowSize; i++)
- {
- var retRow = retMatrix.GetRow(i);
- var rhsRow = rhs.OdData.GetRow(i);
- VectorHelper.Subtract(retRow, flatLhs, rhsRow);
- }
+ var retRow = retMatrix.GetRow(i);
+ var rhsRow = rhs.OdData.GetRow(i);
+ VectorHelper.Subtract(retRow, flatLhs[i], rhsRow);
}
- else
+ }
+ else if (lhs.Direction == ComputationResult.VectorDirection.Horizontal)
+ {
+ for (int i = 0; i < rowSize; i++)
{
- return new ComputationResult("Unable to subtract vector without directionality starting at position " + (Lhs?.Start ?? -1) + "!");
+ var retRow = retMatrix.GetRow(i);
+ var rhsRow = rhs.OdData.GetRow(i);
+ VectorHelper.Subtract(retRow, flatLhs, rhsRow);
}
- return new ComputationResult(retMatrix, true);
}
else
{
- var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
- var flatRhs = rhs.VectorData.Data;
- var rowSize = retMatrix.RowCategories.Count;
- if (rhs.Direction == ComputationResult.VectorDirection.Vertical)
- {
- for (int i = 0; i < flatRhs.Length; i++)
- {
- var retRow = retMatrix.GetRow(i);
- var lhsRow = lhs.OdData.GetRow(i);
- VectorHelper.Subtract(retRow, lhsRow, flatRhs[i]);
- }
- }
- else if (rhs.Direction == ComputationResult.VectorDirection.Horizontal)
+ return new ComputationResult("Unable to subtract vector without directionality starting at position " + (Lhs?.Start ?? -1) + "!");
+ }
+ return new ComputationResult(retMatrix, true);
+ }
+ else
+ {
+ var retMatrix = lhs.Accumulator ? lhs.OdData : new Matrix(lhs.OdData);
+ var flatRhs = rhs.VectorData.Data;
+ var rowSize = retMatrix.RowCategories.Count;
+ if (rhs.Direction == ComputationResult.VectorDirection.Vertical)
+ {
+ for (int i = 0; i < flatRhs.Length; i++)
{
- for (int i = 0; i < flatRhs.Length; i++)
- {
- var retRow = retMatrix.GetRow(i);
- var lhsRow = lhs.OdData.GetRow(i);
- VectorHelper.Subtract(retRow, lhsRow, flatRhs);
- }
+ var retRow = retMatrix.GetRow(i);
+ var lhsRow = lhs.OdData.GetRow(i);
+ VectorHelper.Subtract(retRow, lhsRow, flatRhs[i]);
}
- else
+ }
+ else if (rhs.Direction == ComputationResult.VectorDirection.Horizontal)
+ {
+ for (int i = 0; i < flatRhs.Length; i++)
{
- return new ComputationResult("Unable to subtract vector without directionality starting at position " + (Lhs?.Start ?? -1) + "!");
+ var retRow = retMatrix.GetRow(i);
+ var lhsRow = lhs.OdData.GetRow(i);
+ VectorHelper.Subtract(retRow, lhsRow, flatRhs);
}
- return new ComputationResult(retMatrix, true);
}
- }
- else
- {
- var retMatrix = lhs.Accumulator ? lhs.OdData : (rhs.Accumulator ? rhs.OdData : new Matrix(lhs.OdData));
- VectorHelper.Subtract(retMatrix.Data, lhs.OdData.Data, rhs.OdData.Data);
+ else
+ {
+ return new ComputationResult("Unable to subtract vector without directionality starting at position " + (Lhs?.Start ?? -1) + "!");
+ }
return new ComputationResult(retMatrix, true);
}
}
+ else
+ {
+ var retMatrix = lhs.Accumulator ? lhs.OdData : (rhs.Accumulator ? rhs.OdData : new Matrix(lhs.OdData));
+ VectorHelper.Subtract(retMatrix.Data, lhs.OdData.Data, rhs.OdData.Data);
+ return new ComputationResult(retMatrix, true);
+ }
}
}
}
diff --git a/src/TMG-Framework/Processing/AST/Variable.cs b/src/TMG-Framework/Processing/AST/Variable.cs
index 75a9ad7..484fe78 100644
--- a/src/TMG-Framework/Processing/AST/Variable.cs
+++ b/src/TMG-Framework/Processing/AST/Variable.cs
@@ -16,44 +16,41 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
You should have received a copy of the GNU General Public License
along with XTMF. If not, see .
*/
-using System.Linq;
-using XTMF2;
-namespace TMG.Frameworks.Data.Processing.AST
+namespace TMG.Frameworks.Data.Processing.AST;
+
+public sealed class Variable : Value
{
- public sealed class Variable : Value
+ public readonly string Name;
+
+ public Variable(int start, string name) : base(start)
{
- public readonly string Name;
+ Name = name;
+ }
- public Variable(int start, string name) : base(start)
+ public override ComputationResult Evaluate(IModule[] dataSources)
+ {
+ var source = dataSources.FirstOrDefault(d => d.Name == Name);
+ if (source == null)
{
- Name = name;
+ return new ComputationResult("Unable to find a data source named '" + Name + "'!");
}
-
- public override ComputationResult Evaluate(IModule[] dataSources)
+ if (source is IFunction odSource)
+ {
+ return new ComputationResult(odSource.Invoke(), false);
+ }
+ if (source is IFunction vectorSource)
+ {
+ return new ComputationResult(vectorSource.Invoke(), false);
+ }
+ if (source is IFunction valueSource)
+ {
+ return new ComputationResult(valueSource.Invoke());
+ }
+ if (source is IFunction map)
{
- var source = dataSources.FirstOrDefault(d => d.Name == Name);
- if (source == null)
- {
- return new ComputationResult("Unable to find a data source named '" + Name + "'!");
- }
- if (source is IFunction odSource)
- {
- return new ComputationResult(odSource.Invoke(), false);
- }
- if (source is IFunction vectorSource)
- {
- return new ComputationResult(vectorSource.Invoke(), false);
- }
- if (source is IFunction valueSource)
- {
- return new ComputationResult(valueSource.Invoke());
- }
- if(source is IFunction map)
- {
- return new ComputationResult(new Vector(map.Invoke()), true, ComputationResult.VectorDirection.Unassigned);
- }
- return new ComputationResult("The data source '" + Name + "' was not of a valid resource type!");
+ return new ComputationResult(new Vector(map.Invoke()), true, ComputationResult.VectorDirection.Unassigned);
}
+ return new ComputationResult("The data source '" + Name + "' was not of a valid resource type!");
}
}
diff --git a/src/TMG-Framework/Processing/AppendMatrixValueToCSV.cs b/src/TMG-Framework/Processing/AppendMatrixValueToCSV.cs
index e32a164..70a5fe1 100644
--- a/src/TMG-Framework/Processing/AppendMatrixValueToCSV.cs
+++ b/src/TMG-Framework/Processing/AppendMatrixValueToCSV.cs
@@ -16,77 +16,72 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
You should have received a copy of the GNU General Public License
along with TMG-Framework for XTMF2. If not, see .
*/
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Text;
+
using TMG.Utilities;
-using XTMF2;
-namespace TMG.Processing
+namespace TMG.Processing;
+
+[Module(
+ Name = "Append Matrix Value To CSV",
+ Description = "Reading in a CSV it will append a new column at the end containing the result of looking up an row and column value from a matrix.",
+ DocumentationLink = "http://tmg.utoronto.ca/doc/2.0")]
+public class AppendMatrixValueToCSV : BaseAction
{
- [Module(
- Name = "Append Matrix Value To CSV",
- Description = "Reading in a CSV it will append a new column at the end containing the result of looking up an row and column value from a matrix.",
- DocumentationLink = "http://tmg.utoronto.ca/doc/2.0")]
- public class AppendMatrixValueToCSV : BaseAction
- {
- [Parameter(Name = "Column Name", DefaultValue = "Value", Description = "The name to use for the column", Index = 0)]
- public IFunction ColumnName = null!;
+ [Parameter(Name = "Column Name", DefaultValue = "Value", Description = "The name to use for the column", Index = 0)]
+ public IFunction ColumnName = null!;
- [Parameter(Name = "Row Index", DefaultValue = "1", Description = "The 0 indexed column containing the sparse map index for the row.", Index = 1)]
- public IFunction RowIndex = null!;
+ [Parameter(Name = "Row Index", DefaultValue = "1", Description = "The 0 indexed column containing the sparse map index for the row.", Index = 1)]
+ public IFunction RowIndex = null!;
- [Parameter(Name = "Column Index", DefaultValue = "2", Description = "The 0 indexed column containing the sparse map index for the column.", Index = 2)]
- public IFunction ColumnIndex = null!;
+ [Parameter(Name = "Column Index", DefaultValue = "2", Description = "The 0 indexed column containing the sparse map index for the column.", Index = 2)]
+ public IFunction ColumnIndex = null!;
- [SubModule(Name = "Matrix", Index = 3, Description = "The matrix to assign.", Required = true)]
- public IFunction Matrix = null!;
+ [SubModule(Name = "Matrix", Index = 3, Description = "The matrix to assign.", Required = true)]
+ public IFunction Matrix = null!;
- [SubModule(Name = "Input Stream", Index = 4, Description = "The stream contianing the CSV file.", Required = true)]
- public IFunction InputStream = null!;
+ [SubModule(Name = "Input Stream", Index = 4, Description = "The stream contianing the CSV file.", Required = true)]
+ public IFunction InputStream = null!;
- [SubModule(Name = "Output Stream", Index = 5, Description = "The stream to store the results.", Required = true)]
- public IFunction OutputStream = null!;
+ [SubModule(Name = "Output Stream", Index = 5, Description = "The stream to store the results.", Required = true)]
+ public IFunction OutputStream = null!;
- public override void Invoke()
+ public override void Invoke()
+ {
+ var matrix = Matrix!.Invoke();
+ var columnName = ColumnName?.Invoke();
+ // name sure we don't just have a blank header
+ columnName = String.IsNullOrEmpty(columnName) ? "Value" : columnName;
+ using var reader = new CsvReader(InputStream!.Invoke(), false);
+ using var writer = new StreamWriter(OutputStream!.Invoke());
+ int rowIndex = RowIndex!.Invoke();
+ int columnIndex = ColumnIndex!.Invoke();
+ int minimumRowSize = Math.Max(rowIndex, columnIndex) + 1;
+ // Process header
+ var headers = reader.Headers;
+ for (int i = 0; i < headers.Length; i++)
{
- var matrix = Matrix!.Invoke();
- var columnName = ColumnName?.Invoke();
- // name sure we don't just have a blank header
- columnName = String.IsNullOrEmpty(columnName) ? "Value" : columnName;
- using var reader = new CsvReader(InputStream!.Invoke(), false);
- using var writer = new StreamWriter(OutputStream!.Invoke());
- int rowIndex = RowIndex!.Invoke();
- int columnIndex = ColumnIndex!.Invoke();
- int minimumRowSize = Math.Max(rowIndex, columnIndex) + 1;
- // Process header
- var headers = reader.Headers;
- for (int i = 0; i < headers.Length; i++)
- {
- writer.Write(headers[i]);
- // it is safe to just have a comma after since we are adding a new column
- writer.Write(',');
- }
- writer.Write(columnName);
- writer.WriteLine();
- // Process main body
- while(reader.LoadLine(out var columns))
+ writer.Write(headers[i]);
+ // it is safe to just have a comma after since we are adding a new column
+ writer.Write(',');
+ }
+ writer.Write(columnName);
+ writer.WriteLine();
+ // Process main body
+ while (reader.LoadLine(out var columns))
+ {
+ if (columns >= minimumRowSize)
{
- if (columns >= minimumRowSize)
+ // copy all of the old values
+ for (int i = 0; i < columns; i++)
{
- // copy all of the old values
- for (int i = 0; i < columns; i++)
- {
- reader.Get(out string value, i);
- writer.Write(value);
- writer.Write(',');
- }
- reader.Get(out int o, rowIndex);
- reader.Get(out int d, columnIndex);
- writer.WriteLine(matrix.GetFromSparseIndexes(o, d));
+ reader.Get(out string value, i);
+ writer.Write(value);
+ writer.Write(',');
}
+ reader.Get(out int o, rowIndex);
+ reader.Get(out int d, columnIndex);
+ writer.WriteLine(matrix.GetFromSparseIndexes(o, d));
}
}
}
diff --git a/src/TMG-Framework/Processing/Evaluate2DGravityModel.cs b/src/TMG-Framework/Processing/Evaluate2DGravityModel.cs
index de3fb24..8bf2d83 100644
--- a/src/TMG-Framework/Processing/Evaluate2DGravityModel.cs
+++ b/src/TMG-Framework/Processing/Evaluate2DGravityModel.cs
@@ -16,115 +16,110 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
You should have received a copy of the GNU General Public License
along with TMG-Framework for XTMF2. If not, see .
*/
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.Threading.Tasks;
+
using TMG.Utilities;
-using XTMF2;
-namespace TMG.Processing
+namespace TMG.Processing;
+
+[Module(Name = "Evaluate 2D Gravity Model", Description = "Evaluate the result of the 2D Gravity model.",
+DocumentationLink = "http://tmg.utoronto.ca/doc/2.0")]
+public sealed class Evaluate2DGravityModel : BaseFunction
{
- [Module(Name = "Evaluate 2D Gravity Model", Description = "Evaluate the result of the 2D Gravity model.",
- DocumentationLink = "http://tmg.utoronto.ca/doc/2.0")]
- public sealed class Evaluate2DGravityModel : BaseFunction
- {
- [SubModule(Name = "Production", Required = true, Index = 0, Description = "")]
- public IFunction Production = null!;
+ [SubModule(Name = "Production", Required = true, Index = 0, Description = "")]
+ public IFunction Production = null!;
- [SubModule(Name = "Attraction", Required = true, Index = 1, Description = "")]
- public IFunction Attraction = null!;
+ [SubModule(Name = "Attraction", Required = true, Index = 1, Description = "")]
+ public IFunction Attraction = null!;
- [SubModule(Name = "Friction", Required = true, Index = 2, Description = "")]
- public IFunction Friction = null!;
+ [SubModule(Name = "Friction", Required = true, Index = 2, Description = "")]
+ public IFunction Friction = null!;
- [Parameter(Name = "Max Iterations", Index = 3, DefaultValue = "100", Description = "The maximum number of iterations before terminating.")]
- public IFunction MaxIterations = null!;
+ [Parameter(Name = "Max Iterations", Index = 3, DefaultValue = "100", Description = "The maximum number of iterations before terminating.")]
+ public IFunction MaxIterations = null!;
- [Parameter(Name = "Max Error", Index = 4, DefaultValue = "0.05", Description = "The maximum amount of error before terminating.")]
- public IFunction MaxError = null!;
+ [Parameter(Name = "Max Error", Index = 4, DefaultValue = "0.05", Description = "The maximum amount of error before terminating.")]
+ public IFunction MaxError = null!;
- private static void Apply(Matrix ret, Matrix friction, Vector production,
- Vector attraction, Vector attractionStar, float[] columnTotals)
- {
- Parallel.For(0, production.Count, new ParallelOptions() { MaxDegreeOfParallelism = Environment.ProcessorCount },
- () => new float[columnTotals.Length],
- (flatOrigin, state, localTotals) =>
+ private static void Apply(Matrix ret, Matrix friction, Vector production,
+ Vector attraction, Vector attractionStar, float[] columnTotals)
+ {
+ Parallel.For(0, production.Count, new ParallelOptions() { MaxDegreeOfParallelism = Environment.ProcessorCount },
+ () => new float[columnTotals.Length],
+ (flatOrigin, state, localTotals) =>
+ {
+ var sProduction = production.Data;
+ var length = sProduction.Length;
+ var rowIndex = length * flatOrigin;
+ var sAttraction = attraction.Data;
+ var sFriction = friction.Data.Slice(rowIndex, length);
+ var sRet = ret.Data.Slice(rowIndex, length);
+ var sAttractionStar = attractionStar.Data;
+
+ // check to see if there is no production, if not skip this
+ if (sProduction[flatOrigin] > 0)
{
- var sProduction = production.Data;
- var length = sProduction.Length;
- var rowIndex = length * flatOrigin;
- var sAttraction = attraction.Data;
- var sFriction = friction.Data.Slice(rowIndex, length);
- var sRet = ret.Data.Slice(rowIndex, length);
- var sAttractionStar = attractionStar.Data;
-
- // check to see if there is no production, if not skip this
- if (sProduction[flatOrigin] > 0)
+ var sumAf = VectorHelper.Multiply3AndSum(sFriction, sAttraction, sAttractionStar);
+ sumAf = (sProduction[flatOrigin] / sumAf);
+ if (float.IsInfinity(sumAf) | float.IsNaN(sumAf))
{
- var sumAf = VectorHelper.Multiply3AndSum(sFriction, sAttraction, sAttractionStar);
- sumAf = (sProduction[flatOrigin] / sumAf);
- if (float.IsInfinity(sumAf) | float.IsNaN(sumAf))
- {
- // this needs to be 0f, otherwise we will be making the attractions have to be balanced higher
- sumAf = 0f;
- }
- VectorHelper.Multiply3Scalar1AndColumnSum(sRet, sFriction, sAttraction, sAttractionStar, sumAf, localTotals.AsSpan());
+ // this needs to be 0f, otherwise we will be making the attractions have to be balanced higher
+ sumAf = 0f;
}
- return localTotals;
- },
- localTotals =>
- {
- lock (columnTotals)
- {
- VectorHelper.Add(columnTotals, 0, columnTotals, 0, localTotals, 0, columnTotals.Length);
+ VectorHelper.Multiply3Scalar1AndColumnSum(sRet, sFriction, sAttraction, sAttractionStar, sumAf, localTotals.AsSpan());
}
- });
- }
+ return localTotals;
+ },
+ localTotals =>
+ {
+ lock (columnTotals)
+ {
+ VectorHelper.Add(columnTotals, 0, columnTotals, 0, localTotals, 0, columnTotals.Length);
+ }
+ });
+ }
- private bool Balance(Vector flatAttractions, Vector flatAttractionStar, float epsilon, float[] columnTotals)
+ private bool Balance(Vector flatAttractions, Vector flatAttractionStar, float epsilon, float[] columnTotals)
+ {
+ VectorHelper.Divide(columnTotals.AsSpan(), flatAttractions.Data, columnTotals.AsSpan());
+ VectorHelper.Multiply(flatAttractionStar.Data, flatAttractionStar.Data, columnTotals);
+ VectorHelper.ReplaceIfNotFinite(flatAttractionStar.Data, 1.0f);
+ return VectorHelper.AreBoundedBy(columnTotals, 0, 1.0f, epsilon, columnTotals.Length);
+ }
+
+ public override Matrix Invoke()
+ {
+ var production = Production.Invoke();
+ var attraction = Attraction.Invoke();
+ var friction = Friction.Invoke();
+ var attractionStar = new Vector(attraction);
+ SetToOne(attractionStar);
+ var ret = new Matrix(friction);
+ var maxIterations = MaxIterations.Invoke();
+ var maxError = MaxError.Invoke();
+ if (production.Categories != attraction.Categories)
{
- VectorHelper.Divide(columnTotals.AsSpan(), flatAttractions.Data, columnTotals.AsSpan());
- VectorHelper.Multiply(flatAttractionStar.Data, flatAttractionStar.Data, columnTotals);
- VectorHelper.ReplaceIfNotFinite(flatAttractionStar.Data, 1.0f);
- return VectorHelper.AreBoundedBy(columnTotals, 0, 1.0f, epsilon, columnTotals.Length);
+ throw new XTMFRuntimeException(this, "The production and attraction are not of the same type.");
}
-
- public override Matrix Invoke()
+ if (production.Categories != friction.RowCategories)
{
- var production = Production.Invoke();
- var attraction = Attraction.Invoke();
- var friction = Friction.Invoke();
- var attractionStar = new Vector(attraction);
- SetToOne(attractionStar);
- var ret = new Matrix(friction);
- var maxIterations = MaxIterations.Invoke();
- var maxError = MaxError.Invoke();
- if (production.Categories != attraction.Categories)
- {
- throw new XTMFRuntimeException(this, "The production and attraction are not of the same type.");
- }
- if (production.Categories != friction.RowCategories)
- {
- throw new XTMFRuntimeException(this, "The production and friction are not of the same type.");
- }
- float[] columnTotals = new float[attraction.Data.Length];
- int iteration = 0;
- do
- {
- Array.Clear(columnTotals, 0, columnTotals.Length);
- Apply(ret, friction, production, attraction, attractionStar, columnTotals);
- } while (!Balance(attraction, attractionStar, maxError, columnTotals) || (++iteration < maxIterations));
- return ret;
+ throw new XTMFRuntimeException(this, "The production and friction are not of the same type.");
}
+ float[] columnTotals = new float[attraction.Data.Length];
+ int iteration = 0;
+ do
+ {
+ Array.Clear(columnTotals, 0, columnTotals.Length);
+ Apply(ret, friction, production, attraction, attractionStar, columnTotals);
+ } while (!Balance(attraction, attractionStar, maxError, columnTotals) || (++iteration < maxIterations));
+ return ret;
+ }
- private static void SetToOne(Vector attractionStar)
+ private static void SetToOne(Vector attractionStar)
+ {
+ var aStarData = attractionStar.Data;
+ for (int i = 0; i < aStarData.Length; i++)
{
- var aStarData = attractionStar.Data;
- for (int i = 0; i < aStarData.Length; i++)
- {
- aStarData[i] = 1.0f;
- }
+ aStarData[i] = 1.0f;
}
}
}
diff --git a/src/TMG-Framework/Processing/EvaluateMatrix.cs b/src/TMG-Framework/Processing/EvaluateMatrix.cs
index 50104b0..910cf53 100644
--- a/src/TMG-Framework/Processing/EvaluateMatrix.cs
+++ b/src/TMG-Framework/Processing/EvaluateMatrix.cs
@@ -16,71 +16,67 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
You should have received a copy of the GNU General Public License
along with TMG-Framework for XTMF2. If not, see .
*/
-using System;
-using System.Collections.Generic;
-using System.Text;
-using XTMF2;
+
using TMG.Frameworks.Data.Processing.AST;
-namespace TMG.Processing
+namespace TMG.Processing;
+
+[Module(Name = "Evaluate Matrix", Description = "Evaluates a matrix given the expression.",
+ DocumentationLink = "http://tmg.utoronto.ca/doc/2.0")]
+public class EvaluateMatrix : BaseFunction
{
- [Module(Name = "Evaluate Matrix", Description = "Evaluates a matrix given the expression.",
- DocumentationLink = "http://tmg.utoronto.ca/doc/2.0")]
- public class EvaluateMatrix : BaseFunction
- {
- [Parameter(Name = "Expression", Index = 0, Description = "The expression to compute using the following variables.")]
- public IFunction Expression = null!;
+ [Parameter(Name = "Expression", Index = 0, Description = "The expression to compute using the following variables.")]
+ public IFunction Expression = null!;
- [SubModule(Name = "Variables", Description = "The variables to use in our expression", Index = 1)]
- public IModule[] Variables = null!;
+ [SubModule(Name = "Variables", Description = "The variables to use in our expression", Index = 1)]
+ public IModule[] Variables = null!;
- private string? PreviousExpressionString = null;
- private Expression? PreviousExpression = null;
+ private string? PreviousExpressionString = null;
+ private Expression? PreviousExpression = null;
- public override Matrix Invoke()
+ public override Matrix Invoke()
+ {
+ string? error = null;
+ // compile and optimize the expression
+ var expressionString = Expression.Invoke();
+ if (PreviousExpression == null || expressionString != PreviousExpressionString)
{
- string? error = null;
- // compile and optimize the expression
- var expressionString = Expression.Invoke();
- if (PreviousExpression == null || expressionString != PreviousExpressionString)
- {
- PreviousExpressionString = expressionString;
- if (!TMG.Frameworks.Data.Processing.AST.Compiler.Compile(expressionString, out var expression, ref error))
- {
- throw new XTMFRuntimeException(this, error);
- }
- PreviousExpression = expression;
- }
- var result = PreviousExpression.Evaluate(Variables);
- if(result.Error)
- {
- throw new XTMFRuntimeException(this, result.ErrorMessage);
- }
- // this easy case, the expression was of the correct type
- if(result.IsOdResult)
- {
- return result.OdData;
- }
- // if the result ended up being a
- if(result.IsVectorResult)
+ PreviousExpressionString = expressionString;
+ if (!TMG.Frameworks.Data.Processing.AST.Compiler.Compile(expressionString, out var expression, ref error))
{
- throw new XTMFRuntimeException(this, "The expression resulted in a vector instead of a matrix!");
+ throw new XTMFRuntimeException(this, error);
}
- throw new XTMFRuntimeException(this, "The expression resulted in a scalar instead of a matrix!");
+ PreviousExpression = expression;
+ }
+ var result = PreviousExpression.Evaluate(Variables);
+ if (result.Error)
+ {
+ throw new XTMFRuntimeException(this, result.ErrorMessage);
+ }
+ // this easy case, the expression was of the correct type
+ if (result.IsOdResult)
+ {
+ return result.OdData;
}
+ // if the result ended up being a
+ if (result.IsVectorResult)
+ {
+ throw new XTMFRuntimeException(this, "The expression resulted in a vector instead of a matrix!");
+ }
+ throw new XTMFRuntimeException(this, "The expression resulted in a scalar instead of a matrix!");
+ }
- public override bool RuntimeValidation(ref string? error)
+ public override bool RuntimeValidation(ref string? error)
+ {
+ foreach (var module in Variables)
{
- foreach(var module in Variables)
+ if (!(module is IFunction || module is IFunction || module is IFunction
+ || module is IFunction))
{
- if(!(module is IFunction || module is IFunction || module is IFunction
- || module is IFunction))
- {
- error = $"Invalid variable module type {module.GetType().Name} from module {module.Name}!";
- return false;
- }
+ error = $"Invalid variable module type {module.GetType().Name} from module {module.Name}!";
+ return false;
}
- return true;
}
+ return true;
}
}
diff --git a/src/TMG-Framework/Processing/EvaluateScalar.cs b/src/TMG-Framework/Processing/EvaluateScalar.cs
index db146a6..2b17362 100644
--- a/src/TMG-Framework/Processing/EvaluateScalar.cs
+++ b/src/TMG-Framework/Processing/EvaluateScalar.cs
@@ -16,61 +16,55 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
You should have received a copy of the GNU General Public License
along with TMG-Framework for XTMF2. If not, see .
*/
-using System;
-using System.Collections.Generic;
-using System.Text;
-using XTMF2;
-using TMG.Frameworks.Data.Processing.AST;
-namespace TMG.Processing
+namespace TMG.Processing;
+
+[Module(Name = "Evaluate Scalar", Description = "Evaluate a scalar given the expression.",
+ DocumentationLink = "http://tmg.utoronto.ca/doc/2.0")]
+public class EvaluateScalar : BaseFunction
{
- [Module(Name = "Evaluate Scalar", Description = "Evaluate a scalar given the expression.",
- DocumentationLink = "http://tmg.utoronto.ca/doc/2.0")]
- public class EvaluateScalar : BaseFunction
- {
- [Parameter(Name = "Expression", Index = 0, Description = "The expression to compute using the following variables.")]
- public IFunction Expression = null!;
+ [Parameter(Name = "Expression", Index = 0, Description = "The expression to compute using the following variables.")]
+ public IFunction Expression = null!;
- [SubModule(Name = "Variables", Description = "The variables to use in our expression", Index = 1)]
- public IModule[] Variables = null!;
+ [SubModule(Name = "Variables", Description = "The variables to use in our expression", Index = 1)]
+ public IModule[] Variables = null!;
- public override float Invoke()
+ public override float Invoke()
+ {
+ string? error = null;
+ // compile and optimize the expression
+ if (!TMG.Frameworks.Data.Processing.AST.Compiler.Compile(Expression.Invoke(), out var expression, ref error))
{
- string? error = null;
- // compile and optimize the expression
- if (!TMG.Frameworks.Data.Processing.AST.Compiler.Compile(Expression.Invoke(), out var expression, ref error))
- {
- throw new XTMFRuntimeException(this, error);
- }
- var result = expression.Evaluate(Variables);
- if (result.Error)
- {
- throw new XTMFRuntimeException(this, result.ErrorMessage);
- }
- if (result.IsVectorResult)
- {
- throw new XTMFRuntimeException(this, "The expression resulted in a vector instead of a scalar!");
- }
- if (result.IsOdResult)
- {
- throw new XTMFRuntimeException(this, "The expression resulted in a matrix instead of a scalar!");
- }
- return result.LiteralValue;
-
+ throw new XTMFRuntimeException(this, error);
+ }
+ var result = expression.Evaluate(Variables);
+ if (result.Error)
+ {
+ throw new XTMFRuntimeException(this, result.ErrorMessage);
+ }
+ if (result.IsVectorResult)
+ {
+ throw new XTMFRuntimeException(this, "The expression resulted in a vector instead of a scalar!");
}
+ if (result.IsOdResult)
+ {
+ throw new XTMFRuntimeException(this, "The expression resulted in a matrix instead of a scalar!");
+ }
+ return result.LiteralValue;
- public override bool RuntimeValidation(ref string? error)
+ }
+
+ public override bool RuntimeValidation(ref string? error)
+ {
+ foreach (var module in Variables)
{
- foreach (var module in Variables)
+ if (!(module is IFunction || module is IFunction || module is IFunction
+ || module is IFunction))
{
- if (!(module is IFunction || module is IFunction || module is IFunction
- || module is IFunction))
- {
- error = $"Invalid variable module type {module.GetType().Name} from module {module.Name}!";
- return false;
- }
+ error = $"Invalid variable module type {module.GetType().Name} from module {module.Name}!";
+ return false;
}
- return true;
}
+ return true;
}
}
diff --git a/src/TMG-Framework/Processing/EvaluateVector.cs b/src/TMG-Framework/Processing/EvaluateVector.cs
index 783d845..32ad012 100644
--- a/src/TMG-Framework/Processing/EvaluateVector.cs
+++ b/src/TMG-Framework/Processing/EvaluateVector.cs
@@ -16,61 +16,55 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
You should have received a copy of the GNU General Public License
along with TMG-Framework for XTMF2. If not, see .
*/
-using System;
-using System.Collections.Generic;
-using System.Text;
-using XTMF2;
-using TMG.Frameworks.Data.Processing.AST;
-namespace TMG.Processing
+namespace TMG.Processing;
+
+[Module(Name = "Evaluate Vector", Description = "Evaluate a vector given the expression.",
+ DocumentationLink = "http://tmg.utoronto.ca/doc/2.0")]
+public class EvaluateVector : BaseFunction
{
- [Module(Name = "Evaluate Vector", Description = "Evaluate a vector given the expression.",
- DocumentationLink = "http://tmg.utoronto.ca/doc/2.0")]
- public class EvaluateVector : BaseFunction
- {
- [Parameter(Name = "Expression", Index = 0, Description = "The expression to compute using the following variables.")]
- public IFunction Expression = null!;
+ [Parameter(Name = "Expression", Index = 0, Description = "The expression to compute using the following variables.")]
+ public IFunction Expression = null!;
- [SubModule(Name = "Variables", Description = "The variables to use in our expression", Index = 1)]
- public IModule[] Variables = null!;
+ [SubModule(Name = "Variables", Description = "The variables to use in our expression", Index = 1)]
+ public IModule[] Variables = null!;
- public override Vector Invoke()
+ public override Vector Invoke()
+ {
+ string? error = null;
+ // compile and optimize the expression
+ if (!TMG.Frameworks.Data.Processing.AST.Compiler.Compile(Expression.Invoke(), out var expression, ref error))
{
- string? error = null;
- // compile and optimize the expression
- if (!TMG.Frameworks.Data.Processing.AST.Compiler.Compile(Expression.Invoke(), out var expression, ref error))
- {
- throw new XTMFRuntimeException(this, error);
- }
- var result = expression.Evaluate(Variables);
- if (result.Error)
- {
- throw new XTMFRuntimeException(this, result.ErrorMessage);
- }
- // this easy case, the expression was of the correct type
- if (result.IsVectorResult)
- {
- return result.VectorData;
- }
- if (result.IsOdResult)
- {
- throw new XTMFRuntimeException(this, "The expression resulted in a matrix instead of a vector!");
- }
- throw new XTMFRuntimeException(this, "The expression resulted in a scalar instead of a vector!");
+ throw new XTMFRuntimeException(this, error);
+ }
+ var result = expression.Evaluate(Variables);
+ if (result.Error)
+ {
+ throw new XTMFRuntimeException(this, result.ErrorMessage);
+ }
+ // this easy case, the expression was of the correct type
+ if (result.IsVectorResult)
+ {
+ return result.VectorData;
}
+ if (result.IsOdResult)
+ {
+ throw new XTMFRuntimeException(this, "The expression resulted in a matrix instead of a vector!");
+ }
+ throw new XTMFRuntimeException(this, "The expression resulted in a scalar instead of a vector!");
+ }
- public override bool RuntimeValidation(ref string? error)
+ public override bool RuntimeValidation(ref string? error)
+ {
+ foreach (var module in Variables)
{
- foreach (var module in Variables)
+ if (!(module is IFunction || module is IFunction || module is IFunction
+ || module is IFunction))
{
- if (!(module is IFunction || module is IFunction || module is IFunction
- || module is IFunction))
- {
- error = $"Invalid variable module type {module.GetType().Name} from module {module.Name}!";
- return false;
- }
+ error = $"Invalid variable module type {module.GetType().Name} from module {module.Name}!";
+ return false;
}
- return true;
}
+ return true;
}
}
diff --git a/src/TMG-Framework/Processing/ExecutePipelineInOrderParallel.cs b/src/TMG-Framework/Processing/ExecutePipelineInOrderParallel.cs
index 9c082df..125fe16 100644
--- a/src/TMG-Framework/Processing/ExecutePipelineInOrderParallel.cs
+++ b/src/TMG-Framework/Processing/ExecutePipelineInOrderParallel.cs
@@ -16,33 +16,27 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
You should have received a copy of the GNU General Public License
along with TMG-Framework for XTMF2. If not, see .
*/
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.Linq;
-using XTMF2;
-namespace TMG.Processing
+namespace TMG.Processing;
+
+[Module(Name = "Execute Pipeline In Order Parallel", Description = "Execute a given pipeline",
+ DocumentationLink = "http://tmg.utoronto.ca/doc/2.0")]
+public sealed class ExecutePipelineInOrderParallel : BaseFunction, IEnumerable>
{
- [Module(Name = "Execute Pipeline In Order Parallel", Description = "Execute a given pipeline",
- DocumentationLink = "http://tmg.utoronto.ca/doc/2.0")]
- public sealed class ExecutePipelineInOrderParallel : BaseFunction, IEnumerable>
- {
- [SubModule(Index = 0, Name = "To Execute In Parallel", Required = true, Description = "The functions in order to execute the data through in parallel.")]
- public IFunction ToExecuteInParallel = null!;
+ [SubModule(Index = 0, Name = "To Execute In Parallel", Required = true, Description = "The functions in order to execute the data through in parallel.")]
+ public IFunction ToExecuteInParallel = null!;
- [SubModule(Index = 1, Name = "To Execute In Serial", Required = false, Description = "The functions in order to execute the data through in parallel.")]
- public IFunction[] ToExecuteNotInParallel = null!;
+ [SubModule(Index = 1, Name = "To Execute In Serial", Required = false, Description = "The functions in order to execute the data through in parallel.")]
+ public IFunction[] ToExecuteNotInParallel = null!;
- public override IEnumerable Invoke(IEnumerable context)
+ public override IEnumerable Invoke(IEnumerable context)
+ {
+ var current = context.AsParallel().AsOrdered().Select(element => ToExecuteInParallel.Invoke(element)).AsSequential();
+ for (int i = 0; i < ToExecuteNotInParallel.Length; i++)
{
- var current = context.AsParallel().AsOrdered().Select(element => ToExecuteInParallel.Invoke(element)).AsSequential();
- for (int i = 0; i < ToExecuteNotInParallel.Length; i++)
- {
- int localI = i;
- current = current.Select(element => ToExecuteNotInParallel[localI].Invoke(element));
- }
- return current.AsEnumerable();
+ int localI = i;
+ current = current.Select(element => ToExecuteNotInParallel[localI].Invoke(element));
}
+ return current.AsEnumerable();
}
}
diff --git a/src/TMG-Framework/Processing/IntegerizeMatrix.cs b/src/TMG-Framework/Processing/IntegerizeMatrix.cs
index afa4326..eda7504 100644
--- a/src/TMG-Framework/Processing/IntegerizeMatrix.cs
+++ b/src/TMG-Framework/Processing/IntegerizeMatrix.cs
@@ -16,156 +16,148 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
You should have received a copy of the GNU General Public License
along with TMG-Framework for XTMF2. If not, see .
*/
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.Linq;
-using XTMF2;
-using TMG;
-using System.Threading.Tasks;
-
-namespace TMG.Processing
+
+namespace TMG.Processing;
+
+[Module(Name = "Integerize Matrix", Description = "Takes in a matrix and then integerizes it trying to keep the total by planning district.",
+ DocumentationLink = "http://tmg.utoronto.ca/doc/2.0")]
+public class IntegerizeMatrix : BaseFunction
{
- [Module(Name = "Integerize Matrix", Description = "Takes in a matrix and then integerizes it trying to keep the total by planning district.",
- DocumentationLink = "http://tmg.utoronto.ca/doc/2.0")]
- public class IntegerizeMatrix : BaseFunction
- {
- [SubModule(Required = true, Index = 0, Name = "Input Matrix", Description = "The matrix that will be integerized.")]
- public IFunction InputMatrix = null!;
+ [SubModule(Required = true, Index = 0, Name = "Input Matrix", Description = "The matrix that will be integerized.")]
+ public IFunction InputMatrix = null!;
- [Parameter(Index = 1, Name = "Random Seed", Description = "The number used to initialize the random number generator.")]
- public IFunction RandomSeed = null!;
+ [Parameter(Index = 1, Name = "Random Seed", Description = "The number used to initialize the random number generator.")]
+ public IFunction RandomSeed = null!;
- [SubModule(Required = true, Index = 2, Name = "Zone To PD Map", Description = "A mapping between zone numbers and")]
- public IFunction ZoneToPDMap = null!;
+ [SubModule(Required = true, Index = 2, Name = "Zone To PD Map", Description = "A mapping between zone numbers and")]
+ public IFunction ZoneToPDMap = null!;
- ///
- /// Computes an integer matrix given the input matrix, randomly assigning the remainders within
- /// the planning district for the zones.
- ///
- /// The integerized matrix.
- public override Matrix Invoke()
- {
- var baseMatrix = InputMatrix!.Invoke();
- var pdMap = ZoneToPDMap!.Invoke();
- var zoneToPD = pdMap.CreateIndex();
- var remainders = SplitIntegerAndRemainderMatrix(baseMatrix, pdMap, zoneToPD, out var pdRemainders);
- AssignIntegerRemainders(baseMatrix, remainders, pdRemainders, zoneToPD);
- return baseMatrix;
- }
+ ///
+ /// Computes an integer matrix given the input matrix, randomly assigning the remainders within
+ /// the planning district for the zones.
+ ///
+ /// The integerized matrix.
+ public override Matrix Invoke()
+ {
+ var baseMatrix = InputMatrix!.Invoke();
+ var pdMap = ZoneToPDMap!.Invoke();
+ var zoneToPD = pdMap.CreateIndex();
+ var remainders = SplitIntegerAndRemainderMatrix(baseMatrix, pdMap, zoneToPD, out var pdRemainders);
+ AssignIntegerRemainders(baseMatrix, remainders, pdRemainders, zoneToPD);
+ return baseMatrix;
+ }
- ///
- /// Splits the integer portion of the matrix from the remainders.
- /// The rawMatrix will be integerized.
- ///
- /// The matrix containing both the integer and remainder data
- /// The mapping between zone indexes and pd indexes
- /// The
- /// A new matrix containing the remainders
- private static Matrix SplitIntegerAndRemainderMatrix(Matrix rawMatrix, CategoryMap pdMap, Dictionary zoneToPd, out Matrix pdRemainderTotals)
- {
- var remainders = new Matrix(rawMatrix.RowCategories, rawMatrix.ColumnCategories);
- var pdMatrix = new Matrix(pdMap.Destination, pdMap.Destination);
+ ///
+ /// Splits the integer portion of the matrix from the remainders.
+ /// The rawMatrix will be integerized.
+ ///
+ /// The matrix containing both the integer and remainder data
+ /// The mapping between zone indexes and pd indexes
+ /// The
+ /// A new matrix containing the remainders
+ private static Matrix SplitIntegerAndRemainderMatrix(Matrix rawMatrix, CategoryMap pdMap, Dictionary zoneToPd, out Matrix pdRemainderTotals)
+ {
+ var remainders = new Matrix(rawMatrix.RowCategories, rawMatrix.ColumnCategories);
+ var pdMatrix = new Matrix(pdMap.Destination, pdMap.Destination);
- // Split the integer and remainders while also accumulating the remainders into a PDxPD matrix
- Parallel.For(0, rawMatrix.RowCategories.Count,
- () =>
+ // Split the integer and remainders while also accumulating the remainders into a PDxPD matrix
+ Parallel.For(0, rawMatrix.RowCategories.Count,
+ () =>
+ {
+ return new Matrix(pdMap.Destination, pdMap.Destination);
+ }
+ , (int i, ParallelLoopState _, Matrix pdRemainders) =>
+ {
+ int pdI = zoneToPd[i];
+ var iData = rawMatrix.GetRow(i);
+ var rData = remainders.GetRow(i);
+ var pdRow = pdRemainders.GetRow(pdI);
+ for (int j = 0; j < rawMatrix.ColumnCategories.Count; j++)
{
- return new Matrix(pdMap.Destination, pdMap.Destination);
+ int pdJ = zoneToPd[j];
+ var original = iData[j];
+ iData[j] = (float)Math.Truncate(original);
+ rData[j] = original - iData[j];
+ pdRow[pdJ] += rData[j];
}
- , (int i, ParallelLoopState _, Matrix pdRemainders) =>
- {
- int pdI = zoneToPd[i];
- var iData = rawMatrix.GetRow(i);
- var rData = remainders.GetRow(i);
- var pdRow = pdRemainders.GetRow(pdI);
- for (int j = 0; j < rawMatrix.ColumnCategories.Count; j++)
- {
- int pdJ = zoneToPd[j];
- var original = iData[j];
- iData[j] = (float)Math.Truncate(original);
- rData[j] = original - iData[j];
- pdRow[pdJ] += rData[j];
- }
- return pdRemainders;
- }, (pdRemainders) =>
- {
- lock (pdMatrix)
- {
- Utilities.VectorHelper.Add(pdMatrix.Data, pdMatrix.Data, pdRemainders.Data);
- }
- });
- pdRemainderTotals = pdMatrix;
- return remainders;
- }
-
- private void AssignIntegerRemainders(Matrix integers, Matrix remainders, Matrix pdRemainders, Dictionary zoneToPD)
- {
- var flatZones = integers.RowCategories;
- var pdIndexes = flatZones.Select((z, i) => zoneToPD[i]).ToArray();
- var numberOfPDs = pdRemainders.RowCategories.Count;
- // Create indexes to look for each PDxPD
- var pairs = new List[numberOfPDs * numberOfPDs];
- for (int i = 0; i < flatZones.Count; i++)
+ return pdRemainders;
+ }, (pdRemainders) =>
{
- var row = new Span>(pairs, pdIndexes[i] * numberOfPDs, numberOfPDs);
- for (int j = 0; j < flatZones.Count; j++)
+ lock (pdMatrix)
{
- var list = row[pdIndexes[j]];
- if (list == null)
- {
- list = row[pdIndexes[j]] = new List(100);
- }
- list.Add(new ODPair() { Origin = i, Destination = j });
+ Utilities.VectorHelper.Add(pdMatrix.Data, pdMatrix.Data, pdRemainders.Data);
}
- }
-
- var random = new Random(RandomSeed!.Invoke());
+ });
+ pdRemainderTotals = pdMatrix;
+ return remainders;
+ }
- // Method to assign an additional trip to the integer matrix based on the remainders for the given pd of origin and destination
- void Assign(List zoneList, double pop, ref float pdTotal)
+ private void AssignIntegerRemainders(Matrix integers, Matrix remainders, Matrix pdRemainders, Dictionary zoneToPD)
+ {
+ var flatZones = integers.RowCategories;
+ var pdIndexes = flatZones.Select((z, i) => zoneToPD[i]).ToArray();
+ var numberOfPDs = pdRemainders.RowCategories.Count;
+ // Create indexes to look for each PDxPD
+ var pairs = new List[numberOfPDs * numberOfPDs];
+ for (int i = 0; i < flatZones.Count; i++)
+ {
+ var row = new Span>(pairs, pdIndexes[i] * numberOfPDs, numberOfPDs);
+ for (int j = 0; j < flatZones.Count; j++)
{
- for (int z = 0; z < zoneList.Count; z++)
+ var list = row[pdIndexes[j]];
+ if (list == null)
{
- int i = zoneList[z].Origin;
- int j = zoneList[z].Destination;
- var index = i * flatZones.Count + j;
- pop -= remainders.Data[index];
- if (pop <= 0)
- {
- integers.Data[index] += 1.0f;
- pdTotal -= remainders.Data[index];
- remainders.Data[index] = 0.0f;
- return;
- }
+ list = row[pdIndexes[j]] = new List