using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Globalization; using UnitTestSharp; namespace Azimuth.UnitTests { public class ScalarTests : TestFixture { public void CSharpTest_EqualsBetweenDifferentNumericTypes() { int value1 = 10; double value2 = 10; CheckFalse(value1.Equals(value2)); Check(value2.Equals(value1)); } public class EqualsTests : TestFixture { public void EqualsMethod_EqualScalar() { Scalar value1 = 10; Scalar value2 = 10; Check(value1.Equals(value2)); Check(value2.Equals(value1)); } public void EqualsMethod_EqualScalarPrimitive() { Scalar value1 = 10; double value2 = 10; Check(value1.Equals(value2)); Check(value2.Equals(value1)); } public void EqualsMethod_NotEqualScalar() { Scalar value1 = 10; Scalar value2 = 11; CheckFalse(value1.Equals(value2)); CheckFalse(value2.Equals(value1)); } public void EqualsMethod_NotEqualScalarPrimitive() { Scalar value1 = 10; double value2 = 11; CheckFalse(value1.Equals(value2)); CheckFalse(value2.Equals(value1)); } /////////////////////////////////////////////////////// /////////////////////////////////////////////////////// /////////////////////////////////////////////////////// public void EqualsOperator_EqualScalar() { Scalar value1 = 10; Scalar value2 = 10; Check(value1 == value2); Check(value2 == value1); } public void EqualsOperator_EqualScalarPrimitive() { Scalar value1 = 10; double value2 = 10; Check(value1 == value2); Check(value2 == value1); } public void EqualsOperator_NotEqualScalar() { Scalar value1 = 10; Scalar value2 = 11; CheckFalse(value1 == value2); CheckFalse(value2 == value1); } public void EqualsOperator_NotEqualScalarPrimitive() { Scalar value1 = 10; double value2 = 11; CheckFalse(value1 == value2); CheckFalse(value2 == value1); } /////////////////////////////////////////////////////// /////////////////////////////////////////////////////// /////////////////////////////////////////////////////// public void NotEqualsOperator_EqualScalar() { Scalar value1 = 10; Scalar value2 = 10; CheckFalse(value1 != value2); CheckFalse(value2 != value1); } public void NotEqualsOperator_EqualScalarPrimitive() { Scalar value1 = 10; double value2 = 10; CheckFalse(value1 != value2); CheckFalse(value2 != value1); } public void NotEqualsOperator_NotEqualScalar() { Scalar value1 = 10; Scalar value2 = 11; Check(value1 != value2); Check(value2 != value1); } public void NotEqualsOperator_NotEqualScalarPrimitive() { Scalar value1 = 10; double value2 = 11; Check(value1 != value2); Check(value2 != value1); } /////////////////////////////////////////////////////// /////////////////////////////////////////////////////// /////////////////////////////////////////////////////// public void EqualsObjectMethod_Null() { Scalar value = 10; CheckFalse(value.Equals(null)); } public void EqualsObjectMethod_Scalar() { Scalar value1 = 10; object value2 = (Scalar)10; Check(value1.Equals(value2)); Check(value2.Equals(value1)); } public void EqualsObjectMethod_double() { Scalar value1 = 10; object value2 = (double)10; Check(value1.Equals(value2)); //Check(value2.Equals(value1)); } public void EqualsObjectMethod_bool() { Scalar value1 = 1000; object value2 = true; CheckFalse(value1.Equals(value2)); CheckFalse(value2.Equals(value1)); } /////////////////////////////////////////////////////// /////////////////////////////////////////////////////// /////////////////////////////////////////////////////// public void CanHandleUnitTestSharpCheckEqual_Scalar() { Scalar value1 = 10; Scalar value2 = 10; CheckEqual(value1, value2); CheckEqual(value2, value1); } public void CanHandleUnitTestSharpCheckEqual_ScalarPrimitive() { Scalar value1 = 10; double value2 = 10; CheckEqual(value1, value2); CheckEqual(value2, value1); } public void CanHandleUnitTestSharpCheckEqual_Object() { Scalar value1 = 10; object value2 = (double)10; CheckEqual(value1, value2); CheckEqual(value2, value1); } /////////////////////////////////////////////////////// /////////////////////////////////////////////////////// /////////////////////////////////////////////////////// public void FuzzyEqualityTest() { Scalar a = 1.0; Scalar b = 1.0 + 1e-11; CheckEqual(a, b); CheckEqual(b, a); } public void FuzzyEquality_OperatorTest() { Scalar a = 1.0; Scalar b = 1.0 + 1e-11; Check(a == b); Check(b == a); } public void FuzzyEquality_ObjEqualsTest() { Scalar a = 1.0; Scalar b = 1.0 + 1e-11; Check(a.Equals((object)b)); Check(b.Equals((object)a)); } public void FuzzyEquality_ScalarEqualsTest() { Scalar a = 1.0; Scalar b = 1.0 + 1e-11; Check(a.Equals(b)); Check(b.Equals(a)); } public void FuzzyEquality_StaticMethod() { Scalar a = 1.0; Scalar b = 1.0 + 1e-11; Check(Scalar.FuzzyEquality(a, b)); Check(Scalar.FuzzyEquality(b, a)); Check(b.Equals(a)); } /////////////////////////////////////////////////////// /////////////////////////////////////////////////////// /////////////////////////////////////////////////////// public void Gotcha_00() { Scalar v1 = 0; Scalar v2 = 0; CheckEqual(v1, v2); CheckEqual(v2, v1); } public void Gotcha_InfInf() { Scalar v1 = Scalar.PositiveInfinity; Scalar v2 = Scalar.PositiveInfinity; CheckEqual(v1, v2); CheckEqual(v2, v1); } public void Gotcha_NegInfNegInf() { Scalar v1 = Scalar.NegativeInfinity; Scalar v2 = Scalar.NegativeInfinity; CheckEqual(v1, v2); CheckEqual(v2, v1); } public void Gotcha_ZeroInf() { Scalar v1 = 0; Scalar v2 = Scalar.PositiveInfinity; CheckNotEqual(v1, v2); CheckNotEqual(v2, v1); } public void Gotcha_NaNNan() { Scalar v1 = Scalar.NaN; Scalar v2 = Scalar.NaN; CheckNotEqual(v1, v2); CheckNotEqual(v2, v1); } } public class CtorTests : TestFixture { public void ScalarConstructorTest_Double() { double value = (9.0/8.0); Scalar target = new Scalar(value); CheckEqual(value, target); } public void ScalarConstructorTest_Float() { float value = (9.0f / 8.0f); Scalar target = new Scalar(value); CheckEqual(value, target); } } public class IVectorSpaceTests : TestFixture { public void AssignmentAdd() { IVectorSpace a = (Scalar)10; Scalar b = 5; a.AddAssignment(b); CheckEqual(15, a); CheckEqual(5, b); } public void AssignmentSubtract() { IVectorSpace a = (Scalar)10; Scalar b = 5; a.SubtractAssignment(b); CheckEqual(5, a); CheckEqual(5, b); } public void AssignmentScale() { IVectorSpace a = (Scalar)10; Scalar b = 5; a.ScaleAssignment(b); CheckEqual(50, a); CheckEqual(5, b); } public void AssignmentScaleThenAdd() { IVectorSpace a = (Scalar)10; Scalar b = 5; Scalar scale = 10; a.ScaleThenAddAssignment(scale, b); CheckEqual(60, a); CheckEqual(5, b); } public void InnerProduct() { Scalar a = 10; Scalar b = 20; CheckEqual(200, a.InnerProduct(b)); CheckEqual(10, a); CheckEqual(20, b); } public void Dimension() { IVectorSpace v1 = new Scalar(4); CheckEqual(1, v1.Dimension); } public void GetDimension() { IVectorSpace a = new Scalar(21); CheckEqual(21, a[0]); } public void GetDimension_OutOfBounds() { IVectorSpace a = new Scalar(21); CheckThrow(typeof(System.Exception)); Scalar dummy = a[1]; CheckFalse(dummy == 0); //dummy } public void MinMax() { Scalar a = 13; Scalar b = 1; Scalar c, d; a.MinMax(b, out c, out d); CheckEqual(1, c); CheckEqual(13, d); } public void InplaceMinMax() { Scalar a = 13; Scalar b = 1; a.MinMax(ref b); CheckEqual(1, a); CheckEqual(13, b); } public void Clone() { Scalar a = 10; Scalar b = ((IVectorSpace)a).Clone(); a++; CheckEqual(10, b); CheckEqual(11, a); } } public class ConversionsTests : TestFixture { public void ExplicitFloat() { float valueF1 = (9.0f / 8.0f); Scalar valueS = valueF1; float valueF2 = (float)valueS; CheckEqual(valueF1, valueF2); } public void ExplicitDouble() { double valueF1 = (9.0 / 8.0); Scalar valueS = valueF1; double valueF2 = (double)valueS; CheckEqual(valueF1, valueF2); } public void ImplicitScalarPrimitive() { Scalar valueS = 10; //NOTE: This won't compile if you switch to using floats by defining AZIMUTH_USE_FLOAT double valueD = valueS; CheckEqual(valueD, valueS); } } public class OperatorTests : TestFixture { public void LessThan_True() { Scalar v1 = 1; Scalar v2 = 2; Check(v1 < v2); } public void LessThan_False_Equal() { Scalar v1 = 1; Scalar v2 = 1; CheckFalse(v1 < v2); } public void LessThan_False_Greater() { Scalar v1 = 2; Scalar v2 = 1; CheckFalse(v1 < v2); } /////////////////////////////////////////////////////// /////////////////////////////////////////////////////// /////////////////////////////////////////////////////// public void GreaterThan_True() { Scalar v1 = 2; Scalar v2 = 1; Check(v1 > v2); } public void GreaterThan_False_Equal() { Scalar v1 = 1; Scalar v2 = 1; CheckFalse(v1 > v2); } public void GreaterThan_False_Less() { Scalar v1 = 1; Scalar v2 = 2; CheckFalse(v1 > v2); } /////////////////////////////////////////////////////// /////////////////////////////////////////////////////// /////////////////////////////////////////////////////// public void GreaterThanEqual_True_GreaterThan() { Scalar v1 = 2; Scalar v2 = 1; Check(v1 >= v2); } public void GreaterThanEqual_True_Equal() { Scalar v1 = 1; Scalar v2 = 1; Check(v1 >= v2); } public void GreaterThanEqual_True_FuzzyEqual() { Scalar v1 = 1; Scalar v2 = 1 + 1e-11; Check(v1 >= v2); } public void GreaterThanEqual_False_Less() { Scalar v1 = 1; Scalar v2 = 2; CheckFalse(v1 >= v2); } /////////////////////////////////////////////////////// /////////////////////////////////////////////////////// /////////////////////////////////////////////////////// public void LessThanEqual_True_LessThan() { Scalar v1 = 1; Scalar v2 = 2; Check(v1 <= v2); } public void LessThanEqual_True_Equal() { Scalar v1 = 1; Scalar v2 = 1; Check(v1 <= v2); } public void LessThanEqual_True_FuzzyEqual() { Scalar v1 = 1; Scalar v2 = 1 - 1e-11; Check(v1 <= v2); } public void LessThanEqual_False_Greater() { Scalar v1 = 2; Scalar v2 = 1; CheckFalse(v1 <= v2); } /////////////////////////////////////////////////////// /////////////////////////////////////////////////////// /////////////////////////////////////////////////////// public void Addition() { Scalar v1 = 17; Scalar v2 = 23; CheckEqual(40, v1 + v2); CheckEqual(40, v2 + v1); } /////////////////////////////////////////////////////// /////////////////////////////////////////////////////// /////////////////////////////////////////////////////// public void Subtraction() { Scalar v1 = 17; Scalar v2 = 23; CheckEqual(6, v2 - v1); CheckEqual(-6, v1 - v2); } /////////////////////////////////////////////////////// /////////////////////////////////////////////////////// /////////////////////////////////////////////////////// public void Negation() { Scalar v1 = 17; CheckEqual(-17, -v1); CheckEqual(17, -(-v1)); } /////////////////////////////////////////////////////// /////////////////////////////////////////////////////// /////////////////////////////////////////////////////// public void Multiplication() { Scalar v1 = 17; Scalar v2 = 23; CheckEqual(391, v1 * v2); CheckEqual(391, v2 * v1); } /*public void Multiplication_Inf0() { Scalar v1 = Scalar.PositiveInfinity; Scalar v2 = 0; CheckEqual(0, v1 * v2); CheckEqual(0, v2 * v1); } public void Multiplication_NegInf0() { Scalar v1 = Scalar.NegativeInfinity; Scalar v2 = 0; CheckEqual(0, v1 * v2); CheckEqual(0, v2 * v1); }*/ /////////////////////////////////////////////////////// /////////////////////////////////////////////////////// /////////////////////////////////////////////////////// public void Division() { Scalar v1 = 9.0 / 8.0; Scalar v2 = 18.0 / 8.0; CheckEqual(0.5, v1 / v2); CheckEqual(2, v2 / v1); } /////////////////////////////////////////////////////// /////////////////////////////////////////////////////// /////////////////////////////////////////////////////// } public class ToStringTests : TestFixture { // Note: we have to force the culture for these tests so that the unit tests run the same for // other developers. public class American : TestFixture { CultureInfo culture; public override void FixtureSetup() { culture = CultureInfo.CreateSpecificCulture("en-US"); } public void Basic() { CheckEqual("1.125", ((Scalar)9.0 / 8.0).ToString(culture)); } public void Thousands() { CheckEqual("1001.125", (1000 + (Scalar)9.0 / 8.0).ToString(culture)); } public void TooManyDigits() { CheckEqual("0.3333333333", ((Scalar)(1.0 / 3.0)).ToString(culture)); } public void GenericFormat() { CheckEqual("0.3333333333", ((Scalar)(1.0 / 3.0)).ToString("G", culture)); } public void Rounding() { CheckEqual("0.6666666667", ((Scalar)(2.0 / 3.0)).ToString(culture)); } public void HugeNumber() { Scalar value = 1.0 / Scalar.FuzzyEqualityEpsilon + 0.1; CheckEqual("10000000000", value.ToString(culture)); } public void DropsTrailingZeros() { Scalar value = 1.0; CheckEqual("1", value.ToString(culture)); } public void CustomFormater() { CheckEqual("MOM: 0.3", ((Scalar)(1.0 / 3.0)).ToString("MOM: 0.#", culture)); } public void Infinity() { Scalar value = Scalar.PositiveInfinity; CheckEqual(culture.NumberFormat.PositiveInfinitySymbol, value.ToString(culture)); } public void NegativeInfinity() { Scalar value = Scalar.NegativeInfinity; CheckEqual(culture.NumberFormat.NegativeInfinitySymbol, value.ToString(culture)); } public void NaN() { Scalar value = Scalar.NaN; CheckEqual(culture.NumberFormat.NaNSymbol, value.ToString(culture)); } } public class European : TestFixture { CultureInfo culture; public override void FixtureSetup() { culture = CultureInfo.CreateSpecificCulture("de-DE"); } public void Basic() { CheckEqual("1,125", ((Scalar)9.0 / 8.0).ToString(culture)); } public void Thousands() { CheckEqual("1001,125", (1000 + (Scalar)9.0 / 8.0).ToString(culture)); } public void TooManyDigits() { CheckEqual("0,3333333333", ((Scalar)(1.0 / 3.0)).ToString(culture)); } public void GenericFormat() { CheckEqual("0,3333333333", ((Scalar)(1.0 / 3.0)).ToString("G", culture)); } public void Rounding() { CheckEqual("0,6666666667", ((Scalar)(2.0 / 3.0)).ToString(culture)); } public void HugeNumber() { Scalar value = 1.0 / Scalar.FuzzyEqualityEpsilon + 0.1; CheckEqual("10000000000", value.ToString(culture)); } public void DropsTrailingZeros() { Scalar value = 1.0; CheckEqual("1", value.ToString(culture)); } public void CustomFormater() { CheckEqual("MOM: 0,3", ((Scalar)(1.0 / 3.0)).ToString("MOM: 0.#", culture)); } public void Infinity() { Scalar value = Scalar.PositiveInfinity; CheckEqual(culture.NumberFormat.PositiveInfinitySymbol, value.ToString(culture)); } public void NegativeInfinity() { Scalar value = Scalar.NegativeInfinity; CheckEqual(culture.NumberFormat.NegativeInfinitySymbol, value.ToString(culture)); } public void NaN() { Scalar value = Scalar.NaN; CheckEqual(culture.NumberFormat.NaNSymbol, value.ToString(culture)); } } } public class SignTests : TestFixture { public void Zero() { Scalar a = 0; CheckEqual(1.0, a.Sign); } public void Positive() { Scalar a = 1; CheckEqual(1.0, a.Sign); } public void Negative() { Scalar a = -1; CheckEqual(-1.0, a.Sign); } public void PositiveInfinity() { Scalar a = Scalar.PositiveInfinity; CheckEqual(1.0, a.Sign); } public void NegativeInfinity() { Scalar a = Scalar.NegativeInfinity; CheckEqual(-1.0, a.Sign); } public void NaN() { Scalar a = Scalar.NaN; CheckEqual(1.0, a.Sign); } } public class ToFromHexCodes : TestFixture { public void RoundTrips() { Scalar val = 1.0 / 3.0; var bits = Scalar.BitsToHexCode(val); var returnTrip = Scalar.HexCodeToBits(bits); CheckEqual(val.Value, returnTrip.Value); } public void TryRoundTrips() { Scalar val = 1.0 / 3.0; var bits = Scalar.BitsToHexCode(val); Scalar returnTrip; bool success = Scalar.TryHexCodeToBits(bits, out returnTrip); Check(success); CheckEqual(val.Value, returnTrip.Value); } public void NaNs() { Scalar val = Scalar.NaN; var bits = Scalar.BitsToHexCode(val); var returnTrip = Scalar.HexCodeToBits(bits); Check(Scalar.IsNaN(returnTrip)); } public void TryNaNs() { Scalar val = Scalar.NaN; var bits = Scalar.BitsToHexCode(val); Scalar returnTrip; bool success = Scalar.TryHexCodeToBits(bits, out returnTrip); Check(success); Check(Scalar.IsNaN(returnTrip)); } public void _0() { Scalar val = 0.0; var bits = Scalar.BitsToHexCode(val); var returnTrip = Scalar.HexCodeToBits(bits); CheckEqual(val.Value, returnTrip.Value); } public void Try0() { Scalar val = 0.0; var bits = Scalar.BitsToHexCode(val); Scalar returnTrip; bool success = Scalar.TryHexCodeToBits(bits, out returnTrip); Check(success); CheckEqual(val.Value, returnTrip.Value); } public void Inf() { Scalar val = Scalar.PositiveInfinity; var bits = Scalar.BitsToHexCode(val); var returnTrip = Scalar.HexCodeToBits(bits); Check(Scalar.IsPositiveInfinity(returnTrip)); } public void TryInf() { Scalar val = Scalar.PositiveInfinity; var bits = Scalar.BitsToHexCode(val); Scalar returnTrip; bool success = Scalar.TryHexCodeToBits(bits, out returnTrip); Check(success); Check(Scalar.IsPositiveInfinity(returnTrip)); } public void StartsWith0x() { Scalar val = 1.0 / 3.0; var bits = Scalar.BitsToHexCode(val); Check(bits.StartsWith("0x")); } public void FailsWhenNotStartingWith0x() { var text = "4000000000000000"; CheckThrow(typeof(Exception)); Scalar.HexCodeToBits(text); } public void TryFailsWhenNotStartingWith0x() { var text = "4000000000000000"; Scalar value; bool success = Scalar.TryHexCodeToBits(text, out value); Check(Scalar.IsNaN(value)); CheckFalse(success); } } public class FromUnknownFormat : TestFixture { public void TryRoundtripHex() { Scalar val = 1.0 / 3.0; var bits = Scalar.BitsToHexCode(val); Scalar valOut; bool success = Scalar.TryParseFromUnknownFormat(bits, out valOut); Check(success); CheckEqual(val.Value, valOut.Value); } public void RoundtripHex() { Scalar val = 1.0 / 3.0; var bits = Scalar.BitsToHexCode(val); Scalar valOut = Scalar.ParseFromUnknownFormat(bits); CheckEqual(val.Value, valOut.Value); } public void TryRoundtripNumbers() { Scalar val = 1.0 / 3.0; string str = val.ToString(); Scalar valOut; bool success = Scalar.TryParseFromUnknownFormat(str, out valOut); Check(success); CheckEqual(val, valOut); } public void RoundtripNumbers() { Scalar val = 1.0 / 3.0; string str = val.ToString(); Scalar valOut = Scalar.ParseFromUnknownFormat(str); CheckEqual(val, valOut); } public void TryRoundTripWord() { string str = "poop"; Scalar valOut; bool success = Scalar.TryParseFromUnknownFormat(str, out valOut); CheckFalse(success); Check(Scalar.IsNaN(valOut)); } public void RoundTripWord() { string str = "poop"; Scalar valOut; CheckThrow(typeof(Exception)); valOut = Scalar.ParseFromUnknownFormat(str); } } public class LERP : TestFixture { public void ZeroReturnsFirstArgument() { CheckEqual(3, Scalar.LERP(3, 4, 0)); } public void OneReturnsSecondArgument() { CheckEqual(4, Scalar.LERP(3, 4, 1)); } public void HalfReturnsMidpoint() { CheckEqual(4, Scalar.LERP(3, 5, 0.5)); } public void NegativeInterpolatesBelowFirstArgument() { CheckEqual(1, Scalar.LERP(3, 5, -1)); } public void AboveUnityInterpolatesAboveSecondArgument() { CheckEqual(7, Scalar.LERP(3, 5, 2)); } } public class FLOPCounting : TestFixture { #if AZIMUTH_COUNT_FLOPS public override void TestSetup() { Scalar.ResetFlopCount(); } public void CheckIfAzimuthAndTestsAreConsistent() { CheckTrue(Scalar.IsCountingFlops); } public void CheckZeroCount() { CheckEqual(0, Scalar.FLOPs); } public void Add() { Scalar a = 0; CheckEqual(0, Scalar.FLOPs); a += 20; CheckEqual(1, Scalar.FLOPs); } public void Sub() { Scalar a = 0; CheckEqual(0, Scalar.FLOPs); a -= 20; CheckEqual(1, Scalar.FLOPs); } public void Mul() { Scalar a = 10; CheckEqual(0, Scalar.FLOPs); a *= 20; CheckEqual(1, Scalar.FLOPs); } public void Div() { Scalar a = 10; CheckEqual(0, Scalar.FLOPs); a /= 2; CheckEqual(1, Scalar.FLOPs); } public void Equality() { Scalar a = 0; CheckEqual(0, Scalar.FLOPs); bool value = (a == 20); CheckEqual(1, Scalar.FLOPs); } public void Inequality() { Scalar a = 0; CheckEqual(0, Scalar.FLOPs); bool value = (a != 20); CheckEqual(1, Scalar.FLOPs); } public void LessThan() { Scalar a = 0; CheckEqual(0, Scalar.FLOPs); bool value = a < 20; CheckEqual(1, Scalar.FLOPs); } public void GreatherThan() { Scalar a = 0; CheckEqual(0, Scalar.FLOPs); bool value = a > 20; CheckEqual(1, Scalar.FLOPs); } #else public void CheckIfAzimuthAndTestsAreConsistent() { // You need to make sure that the Unit Tests are compiled // with AZIMUTH_COUNT_FLOPS if Azimuth proper is. CheckFalse(Scalar.IsCountingFlops); } public void CountIsZero() { CheckEqual(0, Scalar.FLOPs); } public void CountDoesNotIncrment() { Scalar a = 0; CheckEqual(0, Scalar.FLOPs); a += 20; CheckEqual(0, Scalar.FLOPs); } #endif } } }