diff --git a/VectoCommon/VectoCommon/Utils/EnumerableExtensionMethods.cs b/VectoCommon/VectoCommon/Utils/EnumerableExtensionMethods.cs index f68bd93aae2a16634313f745317646c9c9b4a401..6ccdbe2f4b6aedad66ecf7758064e3d1747acdcd 100644 --- a/VectoCommon/VectoCommon/Utils/EnumerableExtensionMethods.cs +++ b/VectoCommon/VectoCommon/Utils/EnumerableExtensionMethods.cs @@ -32,6 +32,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.CompilerServices; using TUGraz.VectoCommon.Models; namespace TUGraz.VectoCommon.Utils @@ -43,6 +44,7 @@ namespace TUGraz.VectoCommon.Utils return self.Select(s => s.ToDouble(defaultValue)); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool SequenceEqualFast<T>(this T[] self, T[] other) where T : IComparable { if (self.Equals(other)) { diff --git a/VectoCommon/VectoCommon/Utils/SI.cs b/VectoCommon/VectoCommon/Utils/SI.cs index 19764d912cc26903d991a4037f2545438cb12c28..04d232b4fb4c0d95ea95432670fa6a4b5479c810 100644 --- a/VectoCommon/VectoCommon/Utils/SI.cs +++ b/VectoCommon/VectoCommon/Utils/SI.cs @@ -37,6 +37,7 @@ using System.Globalization; using System.Linq; using System.Linq.Expressions; using System.Reflection; +using System.Runtime.CompilerServices; using TUGraz.VectoCommon.Exceptions; // ReSharper disable ClassNeverInstantiated.Global @@ -828,7 +829,10 @@ namespace TUGraz.VectoCommon.Utils /// <param name="val">The value of the SI object.</param> public static T Create(double val) { - return val == 0 ? ZeroPrototype : Constructor(val); + if (val == 0) + return ZeroPrototype; + + return Constructor(val); } [DebuggerHidden] @@ -1081,7 +1085,8 @@ namespace TUGraz.VectoCommon.Utils Denominator = new Unit[0]; _exponent = 1; - if (double.IsNaN(Val)) { + // check for NaN works like this: val != val + if (val != val) { throw new VectoException("NaN [{0}] is not allowed for SI-Values in Vecto.", GetUnitString()); } @@ -1099,8 +1104,7 @@ namespace TUGraz.VectoCommon.Utils /// <param name="reciproc">if set to <c>true</c> then the object is in reciproc mode (1/...)</param> /// <param name="reverse">if set to <c>true</c> then the object is in reverse convertion mode (e.g. rpm/min => rad/s).</param> /// <param name="exponent">The exponent for further conversions (e.g. Square.Meter).</param> - [DebuggerHidden] - protected SI(double val, IEnumerable<Unit> numerator, IEnumerable<Unit> denominator, bool reciproc = false, + protected SI(double val, Unit[] numerator, Unit[] denominator, bool reciproc = false, bool reverse = false, int exponent = 1) { Val = val; @@ -1233,16 +1237,21 @@ namespace TUGraz.VectoCommon.Utils /// <summary> /// Converts the derived SI units to the basic units and returns this as a new SI object. /// </summary> - [DebuggerHidden] public SI ToBasicUnits() { - var numerator = new List<Unit>(); - var denominator = new List<Unit>(); + var numerator = new List<Unit>(10); + var denominator = new List<Unit>(10); + var numeratorFactor = 1.0; - Numerator.ToList().ForEach(unit => ConvertToBasicUnits(unit, numerator, denominator, ref numeratorFactor)); + for (var i = 0; i < Numerator.Length; i++) { + numeratorFactor *= ConvertToBasicUnits(Numerator[i], numerator, denominator); + } var denominatorFactor = 1.0; - Denominator.ToList().ForEach(unit => ConvertToBasicUnits(unit, denominator, numerator, ref denominatorFactor)); - return new SI(Val * numeratorFactor / denominatorFactor, numerator, denominator); + for (var i = 0; i < Denominator.Length; i++) { + denominatorFactor *= ConvertToBasicUnits(Denominator[i], denominator, numerator); + } + + return new SI(Val * numeratorFactor / denominatorFactor, numerator.ToArray(), denominator.ToArray()); } /// <summary> @@ -1251,48 +1260,33 @@ namespace TUGraz.VectoCommon.Utils /// <param name="unit">The unit.</param> /// <param name="numerator">The numerator.</param> /// <param name="denominator">The denominator.</param> - /// <param name="factor">The factor.</param> - private static void ConvertToBasicUnits(Unit unit, ICollection<Unit> numerator, - ICollection<Unit> denominator, ref double factor) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static double ConvertToBasicUnits(Unit unit, List<Unit> numerator, List<Unit> denominator) { switch (unit) { case Unit.W: - numerator.Add(Unit.k); - numerator.Add(Unit.g); - numerator.Add(Unit.m); - numerator.Add(Unit.m); - denominator.Add(Unit.s); - denominator.Add(Unit.s); - denominator.Add(Unit.s); + numerator.AddRange(new[] { Unit.k, Unit.g, Unit.m, Unit.m }); + denominator.AddRange(new[] { Unit.s, Unit.s, Unit.s }); break; case Unit.N: - numerator.Add(Unit.k); - numerator.Add(Unit.g); - numerator.Add(Unit.m); - denominator.Add(Unit.s); - denominator.Add(Unit.s); + numerator.AddRange(new[] { Unit.k, Unit.g, Unit.m }); + denominator.AddRange(new[] { Unit.s, Unit.s }); break; case Unit.t: - factor *= 1000; - numerator.Add(Unit.k); - numerator.Add(Unit.g); - break; + numerator.AddRange(new[] { Unit.k, Unit.g }); + return 1000; case Unit.J: - numerator.Add(Unit.k); - numerator.Add(Unit.g); - numerator.Add(Unit.m); - numerator.Add(Unit.m); - denominator.Add(Unit.s); - denominator.Add(Unit.s); + numerator.AddRange(new[] { Unit.k, Unit.g, Unit.m, Unit.m }); + denominator.AddRange(new[] { Unit.s, Unit.s }); break; case Unit.min: - factor *= 60; numerator.Add(Unit.s); - break; + return 60; default: numerator.Add(unit); break; } + return 1; } /// <summary> @@ -1330,38 +1324,6 @@ namespace TUGraz.VectoCommon.Utils return Math.Sign(Val); } - /// <summary> - /// Returns the Square root of value and units of the SI. - /// </summary> - public SI Sqrt() - { - var si = ToBasicUnits(); - if (si.Numerator.Length % 2 != 0 || si.Denominator.Length % 2 != 0) { - throw new VectoException("The squareroot cannot be calculated because the Unit-Exponents are not even: [{0}]", - si.GetUnitString()); - } - - var numerator = new List<Unit>(); - var currentNumerator = si.Numerator.ToList(); - while (currentNumerator.Count != 0) { - var unit = currentNumerator.First(); - currentNumerator.Remove(unit); - currentNumerator.Remove(unit); - numerator.Add(unit); - } - - var denominator = new List<Unit>(); - var currentDenominator = si.Denominator.ToList(); - while (currentDenominator.Count != 0) { - var unit = currentDenominator.First(); - currentDenominator.Remove(unit); - currentDenominator.Remove(unit); - denominator.Add(unit); - } - - return new SI(Math.Sqrt(si.Val), numerator, denominator); - } - #region Unit Definitions /// <summary> @@ -1611,11 +1573,16 @@ namespace TUGraz.VectoCommon.Utils /// <returns> /// The result of the operator. /// </returns> - [DebuggerHidden] public static SI operator *(SI si1, SI si2) { - var numerator = si1.Numerator.Concat(si2.Numerator); - var denominator = si1.Denominator.Concat(si2.Denominator); + var numerator = new Unit[si1.Numerator.Length + si2.Numerator.Length]; + Array.Copy(si1.Numerator, numerator, si1.Numerator.Length); + Array.Copy(si2.Numerator, 0, numerator, si1.Numerator.Length, si2.Numerator.Length); + + var denominator = new Unit[si1.Denominator.Length + si2.Denominator.Length]; + Array.Copy(si1.Denominator, denominator, si1.Denominator.Length); + Array.Copy(si2.Denominator, 0, denominator, si1.Denominator.Length, si2.Denominator.Length); + return new SI(si1.Val * si2.Val, numerator, denominator); } @@ -1655,7 +1622,6 @@ namespace TUGraz.VectoCommon.Utils /// <returns> /// The result of the operator. /// </returns> - [DebuggerHidden] public static SI operator /(SI si1, SI si2) { double result; @@ -1671,8 +1637,14 @@ namespace TUGraz.VectoCommon.Utils string.Format("Can not compute division by zero ([{0}] / 0[{1}])", si1.GetUnitString(), si2.GetUnitString()), ex); } - var numerator = si1.Numerator.Concat(si2.Denominator); - var denominator = si1.Denominator.Concat(si2.Numerator); + var numerator = new Unit[si1.Numerator.Length + si2.Denominator.Length]; + Array.Copy(si1.Numerator, numerator, si1.Numerator.Length); + Array.Copy(si2.Denominator, 0, numerator, si1.Numerator.Length, si2.Denominator.Length); + + var denominator = new Unit[si1.Denominator.Length + si2.Numerator.Length]; + Array.Copy(si1.Denominator, denominator, si1.Denominator.Length); + Array.Copy(si2.Numerator, 0, denominator, si1.Denominator.Length, si2.Numerator.Length); + return new SI(result, numerator, denominator); } @@ -1724,6 +1696,7 @@ namespace TUGraz.VectoCommon.Utils /// </returns> /// <exception cref="VectoException"></exception> [DebuggerHidden] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool operator <(SI si1, SI si2) { if (!si1.HasEqualUnit(si2)) { @@ -1756,6 +1729,7 @@ namespace TUGraz.VectoCommon.Utils /// </returns> /// <exception cref="VectoException"></exception> [DebuggerHidden] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool operator >(SI si1, SI si2) { if (!si1.HasEqualUnit(si2)) { @@ -1979,6 +1953,7 @@ namespace TUGraz.VectoCommon.Utils /// <param name="si">The si.</param> /// <returns></returns> [DebuggerHidden] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool HasEqualUnit(SI si) { if (Numerator.SequenceEqualFast(si.Numerator) && Denominator.SequenceEqualFast(si.Denominator)) { diff --git a/VectoCommon/VectoCommon/Utils/VectoMath.cs b/VectoCommon/VectoCommon/Utils/VectoMath.cs index 58c55265c95570a7720cb0c61625005cc4b7ac2b..31194a5998e32ac61626c0240733a2d753a516b5 100644 --- a/VectoCommon/VectoCommon/Utils/VectoMath.cs +++ b/VectoCommon/VectoCommon/Utils/VectoMath.cs @@ -33,6 +33,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using System.Runtime.CompilerServices; using TUGraz.VectoCommon.Exceptions; using TUGraz.VectoCommon.Models; @@ -130,11 +131,6 @@ namespace TUGraz.VectoCommon.Utils return value; } - public static T Sqrt<T>(SI si) where T : SIBase<T> - { - return si.Sqrt().Cast<T>(); - } - /// <summary> /// converts the given inclination in percent (0-1+) into Radians /// </summary> @@ -436,12 +432,18 @@ namespace TUGraz.VectoCommon.Utils /// <param name="y"></param> /// <param name="exact"></param> /// <returns></returns> + [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool IsInside(double x, double y, bool exact) { - if ((P1.Y.IsSmaller(y) && P2.Y.IsSmaller(y) && P3.Y.IsSmaller(y)) - || (P1.X.IsSmaller(x) && P2.X.IsSmaller(x) && P3.X.IsSmaller(x)) - || (P1.X.IsGreater(x) && P2.X.IsGreater(x) && P3.X.IsGreater(x)) - || (P1.Y.IsGreater(y) && P2.Y.IsGreater(y) && P3.Y.IsGreater(y))) + var smallerY = y - DoubleExtensionMethods.Tolerance; + var biggerY = y + DoubleExtensionMethods.Tolerance; + var smallerX = x - DoubleExtensionMethods.Tolerance; + var biggerX = x + DoubleExtensionMethods.Tolerance; + + if ((P1.Y < smallerY && P2.Y < smallerY && P3.Y < smallerY) + || (P1.X < smallerX && P2.X < smallerX && P3.X < smallerX) + || (P1.X > biggerX && P2.X > biggerX && P3.X > biggerX) + || (P1.Y > biggerY && P2.Y > biggerY && P3.Y > biggerY)) return false; var v0X = P3.X - P1.X; diff --git a/VectoCore/VectoCore/Utils/DelaunayMap.cs b/VectoCore/VectoCore/Utils/DelaunayMap.cs index fb9e42a5761548835c9cd482b4437093f31c8b09..661a91b450ea2f2b8e6e00f033f7103b66277c28 100644 --- a/VectoCore/VectoCore/Utils/DelaunayMap.cs +++ b/VectoCore/VectoCore/Utils/DelaunayMap.cs @@ -47,7 +47,7 @@ namespace TUGraz.VectoCore.Utils public sealed class DelaunayMap : LoggingObject { internal ICollection<Point> Points = new HashSet<Point>(); - private List<Triangle> _triangles; + private Triangle[] _triangles; private Edge[] _convexHull; private readonly string _mapName; @@ -137,7 +137,7 @@ namespace TUGraz.VectoCore.Utils SelectMany(t => t.GetEdges()). Where(e => !(superTriangle.Contains(e.P1) || superTriangle.Contains(e.P2))).ToArray(); - _triangles = triangles.FindAll(t => !t.SharesVertexWith(superTriangle)); + _triangles = triangles.FindAll(t => !t.SharesVertexWith(superTriangle)).ToArray(); } private void SanitycheckInputPoints() @@ -226,7 +226,7 @@ namespace TUGraz.VectoCore.Utils /// <param name="y"></param> /// <returns>a value if interpolation is successfull, /// null if interpolation has failed.</returns> - [MethodImpl(MethodImplOptions.Synchronized)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public double? Interpolate(double x, double y) { if (_triangles == null) @@ -236,15 +236,15 @@ namespace TUGraz.VectoCore.Utils y = (y - _minY) / (_maxY - _minY); var i = 0; - while (i < _triangles.Count && !_triangles[i].IsInside(x, y, true)) + while (i < _triangles.Length && !_triangles[i].IsInside(x, y, true)) i++; - if (i == _triangles.Count) { + if (i == _triangles.Length) { i = 0; - while (i < _triangles.Count && !_triangles[i].IsInside(x, y, false)) + while (i < _triangles.Length && !_triangles[i].IsInside(x, y, false)) i++; } - if (i == _triangles.Count) + if (i == _triangles.Length) return null; var tr = _triangles[i]; diff --git a/VectoCore/VectoCoreTest/Utils/SITest.cs b/VectoCore/VectoCoreTest/Utils/SITest.cs index e03ef731dec9613c6288685e60fb4758d91bf5c9..0a44af7b0f25412a8f2103a9ea59377811351008 100644 --- a/VectoCore/VectoCoreTest/Utils/SITest.cs +++ b/VectoCore/VectoCoreTest/Utils/SITest.cs @@ -387,13 +387,6 @@ namespace TUGraz.VectoCore.Tests.Utils { AssertHelper.AreRelativeEqual(-3, -3.SI().Value()); AssertHelper.AreRelativeEqual(3.SI(), (-3).SI().Abs()); - - AssertHelper.AreRelativeEqual(6.SI(), 36.SI().Sqrt()); - AssertHelper.AreRelativeEqual(6.SI<NewtonMeter>(), (6.SI<NewtonMeter>() * 6.SI<NewtonMeter>()).Sqrt()); - AssertHelper.AreRelativeEqual(6.SI().Second, 36.SI().Square.Second.Sqrt()); - - AssertHelper.Exception<VectoException>(() => 36.SI().Second.Sqrt(), - "The squareroot cannot be calculated because the Unit-Exponents are not even: [s]"); } [TestMethod]