diff --git a/VectoCore/Utils/SI.cs b/VectoCore/Utils/SI.cs index d4a895ac313bd4b6a0cfbead80d22b1581dab1dd..49adfc1d02e1b4ed0850f5ad3ed207fd1207e92d 100644 --- a/VectoCore/Utils/SI.cs +++ b/VectoCore/Utils/SI.cs @@ -1,5 +1,4 @@ using System; -using System.CodeDom; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; @@ -8,12 +7,14 @@ using System.Globalization; using System.Linq; using System.Runtime.CompilerServices; using System.Runtime.Serialization; -using System.Text; using Newtonsoft.Json; using TUGraz.VectoCore.Exceptions; namespace TUGraz.VectoCore.Utils { + /// <summary> + /// Special SI Class for Scalar Values. Converts implicitely to double. + /// </summary> public class Scalar : SIBase<Scalar> { static Scalar() @@ -28,9 +29,34 @@ namespace TUGraz.VectoCore.Utils return self.Val; } - public static implicit operator Scalar(double val) + public static Scalar operator +(Scalar si1, Scalar si2) + { + return new Scalar(si1.Val + si2.Val); + } + + public static Scalar operator +(Scalar si1, double si2) + { + return new Scalar(si1.Val + si2); + } + + public static Scalar operator +(double si1, Scalar si2) + { + return new Scalar(si1 + si2.Val); + } + + public static Scalar operator -(Scalar si1, Scalar si2) { - return new Scalar(val); + return new Scalar(si1.Val - si2.Val); + } + + public static Scalar operator -(Scalar si1, double si2) + { + return new Scalar(si1.Val - si2); + } + + public static Scalar operator -(double si1, Scalar si2) + { + return new Scalar(si1 - si2.Val); } } @@ -94,27 +120,26 @@ namespace TUGraz.VectoCore.Utils protected Meter(double val) : base(new SI(val).Meter) {} } - public class Ton : SIBase<Ton> + public class Kilogram : SIBase<Kilogram> { - static Ton() + static Kilogram() { - Constructors.Add(typeof(Ton), val => new Ton(val)); + Constructors.Add(typeof(Kilogram), val => new Kilogram(val)); } [JsonConstructor] - protected Ton(double val) : base(new SI(val).Ton) {} + protected Kilogram(double val) : base(new SI(val).Kilo.Gramm) {} } - - public class Kilogram : SIBase<Kilogram> + public class Ton : SIBase<Ton> { - static Kilogram() + static Ton() { - Constructors.Add(typeof(Kilogram), val => new Kilogram(val)); + Constructors.Add(typeof(Ton), val => new Ton(val)); } [JsonConstructor] - protected Kilogram(double val) : base(new SI(val).Kilo.Gramm) {} + protected Ton(double val) : base(new SI(val).Ton) {} } public class SquareMeter : SIBase<SquareMeter> @@ -265,11 +290,6 @@ namespace TUGraz.VectoCore.Utils return Constructors[typeof(T)](val); } - protected SIBase(Type type, Func<double, T> constructor) - { - Constructors[type] = constructor; - } - protected SIBase(SI si) : base(si) {} #region Operators @@ -286,33 +306,22 @@ namespace TUGraz.VectoCore.Utils public static T operator +(SI si1, SIBase<T> si2) { - return si2 + si1; - } - - public static T operator +(SIBase<T> si1, double d) - { - return ((si1 as SI) + d).Cast<T>(); - } - - public static T operator +(double d, SIBase<T> si) - { - return si + d; + return (si1 + (si2 as SI)).Cast<T>(); } - public static T operator -(SIBase<T> si1) { - return 0 - si1; + return (-(si1 as SI)).Cast<T>(); } public static T operator -(SIBase<T> si1, SIBase<T> si2) { - return (si1 as SI) - si2; + return ((si1 as SI) - (si2 as SI)).Cast<T>(); } public static T operator -(SIBase<T> si1, SI si2) { - return (-1 * si2) + si1; + return ((si1 as SI) - si2).Cast<T>(); } public static T operator -(SI si1, SIBase<T> si2) @@ -320,19 +329,9 @@ namespace TUGraz.VectoCore.Utils return (si1 - (si2 as SI)).Cast<T>(); } - public static T operator -(SIBase<T> si, double d) - { - return ((si as SI) - d).Cast<T>(); - } - - public static T operator -(double d, SIBase<T> si) - { - return (d - (si as SI)).Cast<T>(); - } - public static T operator *(double d, SIBase<T> si) { - return si * d; + return (d * (si as SI)).Cast<T>(); } public static T operator *(SIBase<T> si, double d) @@ -340,11 +339,6 @@ namespace TUGraz.VectoCore.Utils return ((si as SI) * d).Cast<T>(); } - public static T operator /(double d, SIBase<T> si) - { - return si / d; - } - public static T operator /(SIBase<T> si, double d) { return ((si as SI) / d).Cast<T>(); @@ -519,14 +513,16 @@ namespace TUGraz.VectoCore.Utils { var numerator = new List<Unit>(); var denominator = new List<Unit>(); - Numerator.ToList().ForEach(unit => ConvertToBasicUnits(unit, numerator, denominator)); - Denominator.ToList().ForEach(unit => ConvertToBasicUnits(unit, denominator, numerator)); - return new SI(Val, numerator, denominator); + var numeratorFactor = 1.0; + Numerator.ToList().ForEach(unit => ConvertToBasicUnits(unit, numerator, denominator, ref numeratorFactor)); + var denominatorFactor = 1.0; + Denominator.ToList().ForEach(unit => ConvertToBasicUnits(unit, denominator, numerator, ref denominatorFactor)); + return new SI(Val * numeratorFactor / denominatorFactor, numerator, denominator); } private static void ConvertToBasicUnits(Unit unit, ICollection<Unit> numerator, - ICollection<Unit> denominator) + ICollection<Unit> denominator, ref double factor) { switch (unit) { case Unit.W: @@ -546,7 +542,7 @@ namespace TUGraz.VectoCore.Utils denominator.Add(Unit.s); break; case Unit.t: - numerator.Add(Unit.k); + factor *= 1000; numerator.Add(Unit.k); numerator.Add(Unit.g); break; @@ -583,11 +579,31 @@ namespace TUGraz.VectoCore.Utils public SI Sqrt() { var si = ToBasicUnits(); - var numerator = si.Numerator.Where((u, i) => i % 2 == 0); - var denominator = si.Denominator.Where((u, i) => i % 2 == 0); - var root = new SI(Math.Sqrt(si.Val), numerator, denominator); - Contract.Requires(root * root == this); - return root; + if (si.Numerator.Length % 2 != 0 || si.Denominator.Length % 2 != 0) { + throw new VectoException( + string.Format("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 @@ -765,57 +781,25 @@ namespace TUGraz.VectoCore.Utils Contract.Requires(si2 != null); if (!si1.HasEqualUnit(si2)) { throw new VectoException( - string.Format("Operator '-' can only operate on SI Objects with the same unit. Got: {0} + {1}", si1, si2)); + string.Format("Operator '-' can only operate on SI Objects with the same unit. Got: {0} - {1}", si1, si2)); } return new SI(si1.Val - si2.Val, si1.Numerator, si1.Denominator); } - public static SI operator *(SI si1, SI si2) - { - Contract.Requires(si1 != null); - Contract.Requires(si2 != null); - var numerator = si1.Numerator.Concat(si2.Numerator); - var denominator = si1.Denominator.Concat(si2.Denominator); - return new SI(si1.Val * si2.Val, numerator, denominator); - } - - public static SI operator /(SI si1, SI si2) - { - Contract.Requires(si1 != null); - Contract.Requires(si2 != null); - var numerator = si1.Numerator.Concat(si2.Denominator); - var denominator = si1.Denominator.Concat(si2.Numerator); - return new SI(si1.Val / si2.Val, numerator, denominator); - } - - public static SI operator +(SI si1, double d) - { - Contract.Requires(si1 != null); - return new SI(si1.Val + d, si1); - } - - public static SI operator +(double d, SI si1) + public static SI operator -(SI si1) { Contract.Requires(si1 != null); - return si1 + d; + return new SI(-si1.Val, si1); } - public static SI operator -(SI si1, double d) - { - Contract.Requires(si1 != null); - return new SI(si1.Val - d, si1); - } - public static SI operator -(double d, SI si1) - { - Contract.Requires(si1 != null); - return new SI(d - si1.Val, si1); - } - - public static SI operator -(SI si1) + public static SI operator *(SI si1, SI si2) { Contract.Requires(si1 != null); - return 0 - si1; + Contract.Requires(si2 != null); + var numerator = si1.Numerator.Concat(si2.Numerator); + var denominator = si1.Denominator.Concat(si2.Denominator); + return new SI(si1.Val * si2.Val, numerator, denominator); } public static SI operator *(SI si1, double d) @@ -830,6 +814,15 @@ namespace TUGraz.VectoCore.Utils return new SI(d * si1.Val, si1); } + public static SI operator /(SI si1, SI si2) + { + Contract.Requires(si1 != null); + Contract.Requires(si2 != null); + var numerator = si1.Numerator.Concat(si2.Denominator); + var denominator = si1.Denominator.Concat(si2.Numerator); + return new SI(si1.Val / si2.Val, numerator, denominator); + } + public static SI operator /(SI si1, double d) { Contract.Requires(si1 != null); @@ -839,7 +832,7 @@ namespace TUGraz.VectoCore.Utils public static SI operator /(double d, SI si1) { Contract.Requires(si1 != null); - return new SI(d / si1.Val, si1); + return new SI(d / si1.Val, si1.Denominator, si1.Numerator); } public static bool operator <(SI si1, SI si2) @@ -848,54 +841,55 @@ namespace TUGraz.VectoCore.Utils Contract.Requires(si2 != null); if (!si1.HasEqualUnit(si2)) { throw new VectoException( - string.Format("Operator '<' can only operate on SI Objects with the same unit. Got: {0} + {1}", si1, si2)); + string.Format("Operator '<' can only operate on SI Objects with the same unit. Got: {0} < {1}", si1, si2)); } return si1.Val < si2.Val; } + public static bool operator <(SI si1, double d) + { + Contract.Requires(si1 != null); + return si1 != null && si1.Val < d; + } + public static bool operator >(SI si1, SI si2) { Contract.Requires(si1 != null); Contract.Requires(si2 != null); if (!si1.HasEqualUnit(si2)) { throw new VectoException( - string.Format("Operator '>' can only operate on SI Objects with the same unit. Got: {0} + {1}", si1, si2)); + string.Format("Operator '>' can only operate on SI Objects with the same unit. Got: {0} > {1}", si1, si2)); } return si1.Val > si2.Val; } - public static bool operator <=(SI si1, SI si2) + public static bool operator >(SI si1, double d) { Contract.Requires(si1 != null); - Contract.Requires(si2 != null); - if (!si1.HasEqualUnit(si2)) { - throw new VectoException( - string.Format("Operator '<=' can only operate on SI Objects with the same unit. Got: {0} + {1}", si1, si2)); - } - return si1.Val <= si2.Val; + return si1 != null && si1.Val > d; } - public static bool operator >=(SI si1, SI si2) + public static bool operator >(double d, SI si1) { Contract.Requires(si1 != null); - Contract.Requires(si2 != null); - if (!si1.HasEqualUnit(si2)) { - throw new VectoException( - string.Format("Operator '>=' can only operate on SI Objects with the same unit. Got: {0} + {1}", si1, si2)); - } - return si1.Val >= si2.Val; + return si1 != null && d > si1.Val; } - public static bool operator <(SI si1, double d) + public static bool operator <(double d, SI si1) { Contract.Requires(si1 != null); - return si1 != null && si1.Val < d; + return si1 != null && d < si1.Val; } - public static bool operator >(SI si1, double d) + public static bool operator <=(SI si1, SI si2) { Contract.Requires(si1 != null); - return si1 != null && si1.Val > d; + Contract.Requires(si2 != null); + if (!si1.HasEqualUnit(si2)) { + throw new VectoException( + string.Format("Operator '<=' can only operate on SI Objects with the same unit. Got: {0} <= {1}", si1, si2)); + } + return si1.Val <= si2.Val; } public static bool operator <=(SI si1, double d) @@ -904,34 +898,21 @@ namespace TUGraz.VectoCore.Utils return si1 != null && si1.Val <= d; } - public static bool operator >=(SI si1, double d) + public static bool operator >=(SI si1, SI si2) { Contract.Requires(si1 != null); - return si1 != null && si1.Val >= d; - } - - #endregion - - #region Double Conversion - - /// <summary> - /// Casts an SI Unit to an double. - /// </summary> - /// <param name="si"></param> - /// <returns></returns> - public static explicit operator double(SI si) - { - return si.Val; + Contract.Requires(si2 != null); + if (!si1.HasEqualUnit(si2)) { + throw new VectoException( + string.Format("Operator '>=' can only operate on SI Objects with the same unit. Got: {0} >= {1}", si1, si2)); + } + return si1.Val >= si2.Val; } - /// <summary> - /// Casts a double to an SI Unit. - /// </summary> - /// <param name="d"></param> - /// <returns></returns> - public static explicit operator SI(double d) + public static bool operator >=(SI si1, double d) { - return new SI(d); + Contract.Requires(si1 != null); + return si1 != null && si1.Val >= d; } #endregion @@ -1057,16 +1038,6 @@ namespace TUGraz.VectoCore.Utils #endregion - public Scalar Scalar() - { - var si = ToBasicUnits(); - if (si.Numerator.Length == 0 && si.Denominator.Length == 0) { - return Val.SI<Scalar>(); - } - throw new InvalidCastException("The SI Unit is not a scalar."); - } - - public virtual string ToOutputFormat(uint? decimals = null, double? outputFactor = null, bool? showUnit = null) { decimals = decimals ?? 4; diff --git a/VectoCoreTest/Utils/AssertHelper.cs b/VectoCoreTest/Utils/AssertHelper.cs index 079d3ef0cc9ea08b604cd988c6f1d8971a395f6f..7897625df34802348c7717ab294795c1da4ca83f 100644 --- a/VectoCoreTest/Utils/AssertHelper.cs +++ b/VectoCoreTest/Utils/AssertHelper.cs @@ -17,12 +17,12 @@ namespace TUGraz.VectoCore.Tests.Utils Assert.Fail("Expected Exception {0}, but no exception occured.", typeof(T)); } catch (T ex) { if (!string.IsNullOrEmpty(message)) { - Assert.AreEqual(message, ex.Message, - string.Format("Expected Exception message: {0}, but got message: {1}", message, ex.Message)); + Assert.AreEqual(message, ex.Message); } } } + [DebuggerHidden] public static void AreRelativeEqual(SI expected, SI actual) { Assert.IsTrue(actual.HasEqualUnit(expected), @@ -48,13 +48,13 @@ namespace TUGraz.VectoCore.Tests.Utils if (expected.IsEqual(0.0)) { Assert.AreEqual(expected, actual, DoubleExtensionMethods.Tolerance, - string.Format("Actual value is different. Difference: {3} Expected: {0}, Actual: {1}, Tolerance: {2}{4}", + string.Format("Actual value is different. Expected: {0}, Actual: {1}, Difference: {3}, ToleranceFactor: {2}{4}", expected, actual, toleranceFactor, expected - actual, message)); return; } Assert.IsTrue(Math.Abs(actual / expected - 1) < toleranceFactor, - string.Format("Actual value is different. Difference: {3} Expected: {0}, Actual: {1}, Tolerance: {2}{4}", + string.Format("Actual value is different. Expected: {0}, Actual: {1}, Difference: {3}, ToleranceFactor: {2}{4}", expected, actual, toleranceFactor, expected - actual, message)); } } diff --git a/VectoCoreTest/Utils/SITest.cs b/VectoCoreTest/Utils/SITest.cs index a98b038e5dd93421815689b553bd311e1251daf1..cfd1224efaaf88708d15f5f5f1b6de3d3ba47592 100644 --- a/VectoCoreTest/Utils/SITest.cs +++ b/VectoCoreTest/Utils/SITest.cs @@ -1,5 +1,4 @@ using System; -using System.Diagnostics.CodeAnalysis; using Microsoft.VisualStudio.TestTools.UnitTesting; using TUGraz.VectoCore.Exceptions; using TUGraz.VectoCore.Utils; @@ -9,24 +8,6 @@ namespace TUGraz.VectoCore.Tests.Utils [TestClass] public class SITest { - /// <summary> - /// Assert an expected Exception. - /// </summary> - /// <typeparam name="T"></typeparam> - /// <param name="func"></param> - /// <param name="message"></param> - public static void AssertException<T>(Action func, string message = null) where T : Exception - { - try { - func(); - Assert.Fail("Expected Exception {0}, but no exception occured.", typeof(T)); - } catch (T ex) { - if (message != null) { - Assert.AreEqual(message, ex.Message); - } - } - } - [TestMethod] public void SI_TypicalUsageTest() { @@ -62,7 +43,7 @@ namespace TUGraz.VectoCore.Tests.Utils var angVeloSum = angularVelocity + angularVelocity2; Assert.IsInstanceOfType(angVeloSum, typeof(PerSecond)); Assert.AreEqual((400.0 + 600) / 60 * 2 * Math.PI, angVeloSum.Value(), 0.0000001); - AssertException<VectoException>(() => { var x = 500.SI().Watt + 300.SI().Newton; }); + AssertHelper.Exception<VectoException>(() => { var x = 500.SI().Watt + 300.SI().Newton; }); //subtract var angVeloDiff = angularVelocity - angularVelocity2; @@ -92,11 +73,11 @@ namespace TUGraz.VectoCore.Tests.Utils // ConvertTo only allows conversion if the units are correct. - AssertException<VectoException>(() => { var x = 40.SI<Newton>().ConvertTo().Watt; }); + AssertHelper.Exception<VectoException>(() => { var x = 40.SI<Newton>().ConvertTo().Watt; }); var res1 = 40.SI<Newton>().ConvertTo().Newton; // Cast only allows the cast if the units are correct. - AssertException<VectoException>(() => { var x = 40.SI().Newton.Cast<Watt>(); }); + AssertHelper.Exception<VectoException>(() => { var x = 40.SI().Newton.Cast<Watt>(); }); var res2 = 40.SI().Newton.Cast<Newton>(); } @@ -156,21 +137,55 @@ namespace TUGraz.VectoCore.Tests.Utils } [TestMethod] - public void SI_Test_Addition_Subtraction() + public void SI_Comparison_Operators() { var v1 = 600.SI<NewtonMeter>(); var v2 = 455.SI<NewtonMeter>(); + var v3 = 600.SI<NewtonMeter>(); + var v4 = 100.SI<Watt>(); + var d = 700; Assert.IsTrue(v1 > v2); - Assert.IsTrue(v2 < v1); - Assert.IsTrue(v1 >= v2); - Assert.IsTrue(v2 <= v1); - Assert.IsFalse(v1 < v2); + AssertHelper.Exception<VectoException>(() => { var x = v1 < v4; }, + "Operator '<' can only operate on SI Objects with the same unit. Got: 600.0000 [Nm] < 100.0000 [W]"); + AssertHelper.Exception<VectoException>(() => { var x = v1 > v4; }, + "Operator '>' can only operate on SI Objects with the same unit. Got: 600.0000 [Nm] > 100.0000 [W]"); + AssertHelper.Exception<VectoException>(() => { var x = v1 <= v4; }, + "Operator '<=' can only operate on SI Objects with the same unit. Got: 600.0000 [Nm] <= 100.0000 [W]"); + AssertHelper.Exception<VectoException>(() => { var x = v1 >= v4; }, + "Operator '>=' can only operate on SI Objects with the same unit. Got: 600.0000 [Nm] >= 100.0000 [W]"); + + SI si = null; + Assert.IsFalse(si > 3); + Assert.IsFalse(si < 3); + Assert.IsFalse(si >= 3); + Assert.IsFalse(si <= 3); + + Assert.IsFalse(3 > si); + Assert.IsFalse(3 < si); + Assert.IsFalse(si >= 3); + Assert.IsFalse(si <= 3); + + + Assert.IsTrue(v2 < v1); Assert.IsFalse(v2 > v1); + + Assert.IsTrue(v1 >= v2); Assert.IsFalse(v1 <= v2); + + Assert.IsTrue(v2 <= v1); Assert.IsFalse(v2 >= v1); + Assert.IsTrue(v1 <= v3); + Assert.IsTrue(v1 >= v3); + + Assert.IsTrue(v1 < d); + Assert.IsFalse(v1 > d); + Assert.IsFalse(v1 >= d); + Assert.IsTrue(v1 <= d); + + Assert.AreEqual(1, new SI().CompareTo(null)); Assert.AreEqual(1, new SI().CompareTo("not an SI")); Assert.AreEqual(-1, new SI().Meter.CompareTo(new SI().Kilo.Meter.Per.Hour)); @@ -179,43 +194,184 @@ namespace TUGraz.VectoCore.Tests.Utils Assert.AreEqual(0, 1.SI().CompareTo(1.SI())); Assert.AreEqual(-1, 1.SI().CompareTo(2.SI())); Assert.AreEqual(1, 2.SI().CompareTo(1.SI())); + } + + + [TestMethod] + public void SI_Test_Addition_Subtraction() + { + AssertHelper.AreRelativeEqual(3.SI(), 1.SI() + 2.SI()); + AssertHelper.AreRelativeEqual(-1.SI(), 1.SI() - 2.SI()); + + AssertHelper.AreRelativeEqual(3.SI<Scalar>(), 1.SI<Scalar>() + 2.SI<Scalar>()); + AssertHelper.AreRelativeEqual(3.SI<Scalar>(), 1 + 2.SI<Scalar>()); + AssertHelper.AreRelativeEqual(3.SI<Scalar>(), 1.SI<Scalar>() + 2); + AssertHelper.AreRelativeEqual(-1.SI<Scalar>(), 1.SI<Scalar>() - 2.SI<Scalar>()); + AssertHelper.AreRelativeEqual(-1.SI<Scalar>(), 1 - 2.SI<Scalar>()); + AssertHelper.AreRelativeEqual(-1.SI<Scalar>(), 1.SI<Scalar>() - 2); + + AssertHelper.AreRelativeEqual(3.SI<NewtonMeter>(), 1.SI<NewtonMeter>() + 2.SI<NewtonMeter>()); + AssertHelper.AreRelativeEqual(-1.SI<NewtonMeter>(), 1.SI<NewtonMeter>() - 2.SI<NewtonMeter>()); + + AssertHelper.AreRelativeEqual(3.SI<NewtonMeter>(), 1.SI().Newton.Meter + 2.SI<NewtonMeter>()); + AssertHelper.AreRelativeEqual(-1.SI<NewtonMeter>(), 1.SI().Newton.Meter - 2.SI<NewtonMeter>()); + + AssertHelper.AreRelativeEqual(3.SI<NewtonMeter>(), 1.SI<NewtonMeter>() + 2.SI().Newton.Meter); + AssertHelper.AreRelativeEqual(-1.SI<NewtonMeter>(), 1.SI<NewtonMeter>() - 2.SI().Newton.Meter); + + AssertHelper.Exception<VectoException>(() => { var x = 1.SI().Second - 1.SI<Meter>(); }, + "Operator '-' can only operate on SI Objects with the same unit. Got: 1.0000 [s] - 1.0000 [m]"); + } + + [TestMethod] + public void SI_SpecialUnits() + { + Scalar scalar = 3.SI<Scalar>(); + AssertHelper.AreRelativeEqual(3.SI(), scalar); + double scalarDouble = scalar; + AssertHelper.AreRelativeEqual(3, scalarDouble); + + MeterPerSecond meterPerSecond = 2.SI<MeterPerSecond>(); + AssertHelper.AreRelativeEqual(2.SI().Meter.Per.Second, meterPerSecond); + + Second second = 1.SI<Second>(); + AssertHelper.AreRelativeEqual(1.SI().Second, second); + + Watt watt = 2.SI<Watt>(); + AssertHelper.AreRelativeEqual(2.SI().Watt, watt); + PerSecond perSecond = 1.SI<PerSecond>(); + AssertHelper.AreRelativeEqual(1.SI().Per.Second, perSecond); - NewtonMeter v3 = v1 + v2; + RoundsPerMinute rpm = 20.SI<RoundsPerMinute>(); + AssertHelper.AreRelativeEqual(20.SI().Rounds.Per.Minute, rpm); + AssertHelper.AreRelativeEqual(20.RPMtoRad(), rpm); + AssertHelper.AreRelativeEqual(2.0943951023931953, rpm.Value()); - NewtonMeter v4 = v1 - v2; + Radian radian = 30.SI<Radian>(); + AssertHelper.AreRelativeEqual(30.SI().Radian, radian); + AssertHelper.AreRelativeEqual(30, radian.Value()); - var v5 = v1 * v2; - Assert.IsTrue(v5.HasEqualUnit(0.SI().Square.Newton.Meter)); - Assert.AreEqual(v1.Value() * v2.Value(), v5.Value()); + Newton newton = 3.SI<Newton>(); + AssertHelper.AreRelativeEqual(3.SI().Newton, newton); - var v6 = v1 / v2; - Assert.IsTrue(v6.HasEqualUnit(0.SI())); - Assert.AreEqual(v1.Value() / v2.Value(), v6.Value()); + NewtonMeter newtonMeter = 5.SI<NewtonMeter>(); + AssertHelper.AreRelativeEqual(5.SI().Newton.Meter, newtonMeter); + AssertHelper.AreRelativeEqual(5.SI().Meter.Newton, newtonMeter); - var t = 10.SI<NewtonMeter>(); - var angVelo = 5.SI<PerSecond>(); + MeterPerSquareSecond meterPerSquareSecond = 3.SI<MeterPerSquareSecond>(); + AssertHelper.AreRelativeEqual(3.SI().Meter.Per.Square.Second, meterPerSquareSecond); - Watt w = t * angVelo; - Watt w1 = angVelo * t; + Kilogram kilogram = 3.SI<Kilogram>(); + AssertHelper.AreRelativeEqual(3.SI().Kilo.Gramm, kilogram); + AssertHelper.AreRelativeEqual(3, kilogram.Value()); - NewtonMeter t1 = w / angVelo; + Ton ton = 5.SI<Ton>(); + AssertHelper.AreRelativeEqual(5.SI().Ton, ton); + AssertHelper.AreRelativeEqual(5000.SI<Kilogram>(), ton); - PerSecond angVelo1 = w / t; - Second sec = t / w; + SquareMeter squareMeter = 3.SI<SquareMeter>(); + AssertHelper.AreRelativeEqual(3.SI().Square.Meter, squareMeter); + + CubicMeter cubicMeter = 3.SI<CubicMeter>(); + AssertHelper.AreRelativeEqual(3.SI().Cubic.Meter, cubicMeter); + + KilogramSquareMeter kilogramSquareMeter = 3.SI<KilogramSquareMeter>(); + AssertHelper.AreRelativeEqual(3.SI().Kilo.Gramm.Square.Meter, kilogramSquareMeter); + + KilogramPerWattSecond kilogramPerWattSecond = 3.SI<KilogramPerWattSecond>(); + AssertHelper.AreRelativeEqual(3.SI().Kilo.Gramm.Per.Watt.Second, kilogramPerWattSecond); } + /// <summary> + /// VECTO-111 + /// </summary> [TestMethod] - public void SI_SpecialUnits() + public void SI_ReziprokDivision() + { + var test = 2.0.SI<Second>(); + + var actual = 1.0 / test; + var expected = 0.5.SI<PerSecond>(); + + AssertHelper.AreRelativeEqual(expected, actual); + } + + [TestMethod] + public void SI_Multiplication_Division() { - 2.SI<MeterPerSecond>(); - 1.SI<Second>(); - 2.SI<Watt>(); - 1.SI<PerSecond>(); - 2.SI<RoundsPerMinute>(); - 3.SI<Newton>(); - 4.SI<Radian>(); - 5.SI<NewtonMeter>(); + AssertHelper.AreRelativeEqual(12.SI(), 3.SI() * 4.SI()); + AssertHelper.AreRelativeEqual(12.SI(), 3 * 4.SI()); + AssertHelper.AreRelativeEqual(12.SI(), 3.SI() * 4); + + AssertHelper.AreRelativeEqual(12.SI<NewtonMeter>(), 3.SI<Newton>() * 4.SI<Meter>()); + AssertHelper.AreRelativeEqual(12.SI<NewtonMeter>(), 3 * 4.SI<NewtonMeter>()); + AssertHelper.AreRelativeEqual(12.SI<NewtonMeter>(), 3.SI<NewtonMeter>() * 4); + AssertHelper.AreRelativeEqual(12.SI().Square.Newton.Meter, 3.SI<NewtonMeter>() * 4.SI<NewtonMeter>()); + + AssertHelper.AreRelativeEqual(3.SI(), 12.SI() / 4); + AssertHelper.AreRelativeEqual(3.SI(), 12.SI() / 4.SI()); + AssertHelper.AreRelativeEqual(3.SI(), 12.SI<NewtonMeter>() / 4.SI<NewtonMeter>()); + AssertHelper.AreRelativeEqual(3.SI<Scalar>(), 12.SI<NewtonMeter>() / 4.SI<NewtonMeter>()); + + AssertHelper.AreRelativeEqual(3.SI<NewtonMeter>(), 12.SI<NewtonMeter>() / 4); + AssertHelper.AreRelativeEqual(3.SI().Per.Newton.Meter, 12 / 4.SI<NewtonMeter>()); + + + var newtonMeter = 10.SI<NewtonMeter>(); + var perSecond = 5.SI<PerSecond>(); + var watt = (10 * 5).SI<Watt>(); + var second = (1.0 / 5.0).SI<Second>(); + + AssertHelper.AreRelativeEqual(watt, newtonMeter * perSecond); + AssertHelper.AreRelativeEqual(watt, perSecond * newtonMeter); + + AssertHelper.AreRelativeEqual(newtonMeter, watt / perSecond); + AssertHelper.AreRelativeEqual(perSecond, watt / newtonMeter); + + AssertHelper.AreRelativeEqual(second, newtonMeter / watt); + } + + [TestMethod] + public void SI_MeterPerSecond_Div_Meter() + { + PerSecond actual = 6.SI<MeterPerSecond>() / 2.SI<Meter>(); + AssertHelper.AreRelativeEqual(3.SI().Per.Second, actual); + } + + [TestMethod] + public void SI_SimplifyUnits() + { + AssertHelper.AreRelativeEqual(3.SI(), 18.SI().Kilo.Gramm / 6.SI().Kilo.Gramm); + AssertHelper.AreRelativeEqual(3.SI(), 18.SI<NewtonMeter>() / 6.SI<NewtonMeter>()); + + AssertHelper.AreRelativeEqual(18.SI(), 3.SI().Kilo.Gramm * 6.SI().Per.Kilo.Gramm); + AssertHelper.AreRelativeEqual(18.SI<Meter>(), 3.SI().Kilo.Gramm.Meter * 6.SI().Per.Kilo.Gramm); + + + AssertHelper.AreRelativeEqual(3.SI().Kilo.Gramm.Square.Meter.Per.Cubic.Second, 3.SI<Watt>()); + AssertHelper.AreRelativeEqual(3.SI().Kilo.Gramm.Meter.Per.Square.Second, 3.SI<Newton>()); + AssertHelper.AreRelativeEqual(3000.SI().Kilo.Gramm, 3.SI<Ton>()); + AssertHelper.AreRelativeEqual(3.SI().Kilo.Kilo.Gramm.ConvertTo().Ton, 3.SI<Ton>().ConvertTo().Ton); + + AssertHelper.AreRelativeEqual(3.SI<Meter>(), 3000.SI().Milli.Meter); + + AssertHelper.AreRelativeEqual(36.SI().Square.Newton.Meter, 6.SI<NewtonMeter>() * 6.SI<NewtonMeter>()); + AssertHelper.AreRelativeEqual(36.SI().Newton.Newton.Meter.Meter, 6.SI<NewtonMeter>() * 6.SI<NewtonMeter>()); + } + + [TestMethod] + public void SI_Math() + { + 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]"); } } } \ No newline at end of file