public void TestCompareToDecimal() { var fr = new RandomGenerator(); for (var i = 0; i < 100; ++i) { ERational er = RandomObjects.RandomERational(fr); int exp = -100000 + fr.UniformInt(200000); EDecimal ed = EDecimal.Create( RandomObjects.RandomEInteger(fr), (EInteger)exp); ERational er2 = ERational.FromEDecimal(ed); int c2r = er.CompareTo(er2); int c2d = er.CompareToDecimal(ed); Assert.AreEqual(c2r, c2d); } }
/// <summary>Compares two CBOR numbers. In this implementation, the two /// numbers' mathematical values are compared. Here, NaN (not-a-number) /// is considered greater than any number.</summary> /// <param name='other'>A value to compare with. Can be null.</param> /// <returns>A negative number, if this value is less than the other /// object; or 0, if both values are equal; or a positive number, if /// this value is less than the other object or if the other object is /// null. /// <para>This implementation returns a positive number if <paramref /// name='other'/> is null, to conform to the.NET definition of /// CompareTo. This is the case even in the Java version of this /// library, for consistency's sake, even though implementations of /// <c>Comparable.compareTo()</c> in Java ought to throw an exception /// if they receive a null argument rather than treating null as less /// or greater than any object.</para>.</returns> public int CompareTo(CBORNumber other) { if (other == null) { return(1); } if (this == other) { return(0); } var cmp = 0; Kind typeA = this.kind; Kind typeB = other.kind; object objA = this.value; object objB = other.value; if (typeA == typeB) { switch (typeA) { case Kind.Integer: { var a = (long)objA; var b = (long)objB; cmp = (a == b) ? 0 : ((a < b) ? -1 : 1); break; } case Kind.EInteger: { var bigintA = (EInteger)objA; var bigintB = (EInteger)objB; cmp = bigintA.CompareTo(bigintB); break; } case Kind.Double: { var a = (double)objA; var b = (double)objB; // Treat NaN as greater than all other numbers cmp = Double.IsNaN(a) ? (Double.IsNaN(b) ? 0 : 1) : (Double.IsNaN(b) ? (-1) : ((a == b) ? 0 : ((a < b) ? -1 : 1))); break; } case Kind.EDecimal: { cmp = ((EDecimal)objA).CompareTo((EDecimal)objB); break; } case Kind.EFloat: { cmp = ((EFloat)objA).CompareTo( (EFloat)objB); break; } case Kind.ERational: { cmp = ((ERational)objA).CompareTo( (ERational)objB); break; } default: throw new InvalidOperationException("Unexpected data type"); } } else { int s1 = GetNumberInterface(typeA).Sign(objA); int s2 = GetNumberInterface(typeB).Sign(objB); if (s1 != s2 && s1 != 2 && s2 != 2) { // if both types are numbers // and their signs are different return((s1 < s2) ? -1 : 1); } if (s1 == 2 && s2 == 2) { // both are NaN cmp = 0; } else if (s1 == 2) { // first object is NaN return(1); } else if (s2 == 2) { // second object is NaN return(-1); } else { // DebugUtility.Log("a=" + this + " b=" + other); if (typeA == Kind.ERational) { ERational e1 = GetNumberInterface(typeA).AsExtendedRational(objA); if (typeB == Kind.EDecimal) { EDecimal e2 = GetNumberInterface(typeB).AsExtendedDecimal(objB); cmp = e1.CompareToDecimal(e2); } else { EFloat e2 = GetNumberInterface(typeB).AsExtendedFloat(objB); cmp = e1.CompareToBinary(e2); } } else if (typeB == Kind.ERational) { ERational e2 = GetNumberInterface(typeB).AsExtendedRational(objB); if (typeA == Kind.EDecimal) { EDecimal e1 = GetNumberInterface(typeA).AsExtendedDecimal(objA); cmp = e2.CompareToDecimal(e1); cmp = -cmp; } else { EFloat e1 = GetNumberInterface(typeA).AsExtendedFloat(objA); cmp = e2.CompareToBinary(e1); cmp = -cmp; } } else if (typeA == Kind.EDecimal || typeB == Kind.EDecimal) { EDecimal e1 = null; EDecimal e2 = null; if (typeA == Kind.EFloat) { var ef1 = (EFloat)objA; e2 = (EDecimal)objB; cmp = e2.CompareToBinary(ef1); cmp = -cmp; } else if (typeB == Kind.EFloat) { var ef1 = (EFloat)objB; e2 = (EDecimal)objA; cmp = e2.CompareToBinary(ef1); } else { e1 = GetNumberInterface(typeA).AsExtendedDecimal(objA); e2 = GetNumberInterface(typeB).AsExtendedDecimal(objB); cmp = e1.CompareTo(e2); } } else if (typeA == Kind.EFloat || typeB == Kind.EFloat || typeA == Kind.Double || typeB == Kind.Double) { EFloat e1 = GetNumberInterface(typeA).AsExtendedFloat(objA); EFloat e2 = GetNumberInterface(typeB).AsExtendedFloat(objB); cmp = e1.CompareTo(e2); } else { EInteger b1 = GetNumberInterface(typeA).AsEInteger(objA); EInteger b2 = GetNumberInterface(typeB).AsEInteger(objB); cmp = b1.CompareTo(b2); } } } return(cmp); }