public CBORObject ValidateObject(CBORObject obj) { if (obj.Type != CBORType.Array) { throw new CBORException("Rational number must be an array"); } if (obj.Count != 2) { throw new CBORException("Rational number requires exactly 2 items"); } CBORObject first = obj[0]; CBORObject second = obj[1]; if (!first.IsIntegral) { throw new CBORException("Rational number requires integer numerator"); } if (!second.IsIntegral) { throw new CBORException("Rational number requires integer denominator"); } if (second.Sign <= 0) { throw new CBORException("Rational number requires denominator greater than 0"); } EInteger denom = second.AsEInteger(); // NOTE: Discards tags. See comment in CBORTag2. return(denom.Equals(EInteger.One) ? CBORObject.FromObject(first.AsEInteger()) : CBORObject.FromObject( ERational.Create( first.AsEInteger(), denom))); }
/// <include file='../docs.xml' /// path='docs/doc[@name="M:PeterO.ExtendedRational.Create(System.Int32,System.Int32)"]/*'/> public static ExtendedRational Create( int numeratorSmall, int denominatorSmall) { return(new ExtendedRational( ERational.Create( numeratorSmall, denominatorSmall))); }
public void TestCompareTo() { var r = new RandomGenerator(); for (var i = 0; i < 500; ++i) { ERational bigintA = RandomObjects.RandomERational(r); ERational bigintB = RandomObjects.RandomERational(r); ERational bigintC = RandomObjects.RandomERational(r); TestCommon.CompareTestRelations(bigintA, bigintB, bigintC); } TestCommon.CompareTestLess(ERational.Zero, ERational.NaN); ERational rat, rat2; for (var i = 0; i < 100; ++i) { EInteger num = RandomObjects.RandomEInteger(r); if (num.IsZero) { // Skip if number is 0; 0/1 and 0/2 are // equal in that case continue; } num = num.Abs(); rat = ERational.Create(num, EInteger.One); rat2 = ERational.Create(num, (EInteger)2); TestCommon.CompareTestLess(rat2, rat); TestCommon.CompareTestGreater(rat, rat2); } TestCommon.CompareTestLess( ERational.Create(EInteger.One, (EInteger)2), ERational.Create((EInteger)4, EInteger.One)); for (var i = 0; i < 100; ++i) { EInteger num = RandomObjects.RandomEInteger(r); EInteger den = RandomObjects.RandomEInteger(r); if (den.IsZero) { den = EInteger.One; } rat = ERational.Create(num, den); for (int j = 0; j < 10; ++j) { EInteger num2 = num; EInteger den2 = den; EInteger mult = RandomObjects.RandomEInteger(r); if (mult.IsZero || mult.Equals(EInteger.One)) { mult = (EInteger)2; } num2 *= (EInteger)mult; den2 *= (EInteger)mult; rat2 = ERational.Create(num2, den2); TestCommon.CompareTestEqual(rat, rat2); } } }
public static ERational RandomERational(IRandomGenExtended rand) { EInteger bigintA = RandomEInteger(rand); EInteger bigintB = RandomEInteger(rand); if (bigintB.IsZero) { bigintB = EInteger.One; } return(ERational.Create(bigintA, bigintB)); }
/// <include file='../docs.xml' /// path='docs/doc[@name="M:PeterO.ExtendedRational.Create(PeterO.BigInteger,PeterO.BigInteger)"]/*'/> public static ExtendedRational Create( BigInteger numerator, BigInteger denominator) { if (numerator == null) { throw new ArgumentNullException(nameof(numerator)); } if (denominator == null) { throw new ArgumentNullException(nameof(denominator)); } return(new ExtendedRational( ERational.Create( numerator.Ei, denominator.Ei))); }
public void TestRemainder() { var fr = new RandomGenerator(); for (var i = 0; i < 100; ++i) { ERational er; ERational er2; er = ERational.Create( RandomObjects.RandomEInteger(fr), EInteger.One); er2 = ERational.Create( RandomObjects.RandomEInteger(fr), EInteger.One); if (er2.IsZero || !er2.IsFinite) { continue; } if (er.IsZero || !er.IsFinite) { // Code below will divide by "er", // so skip if "er" is zero continue; } ERational ermult = er.Multiply(er2); ERational erdiv = ermult.Divide(er); erdiv = ermult.Remainder(er); if (!erdiv.IsZero) { Assert.Fail(ermult + "; " + er); } erdiv = ermult.Remainder(er2); if (!erdiv.IsZero) { Assert.Fail(er + "; " + er2); } } }
public static CBORObject Divide(CBORObject a, CBORObject b) { if (a == null) { throw new ArgumentNullException("a"); } if (b == null) { throw new ArgumentNullException("b"); } if (a.Type != CBORType.Number) { throw new ArgumentException("a.Type (" + a.Type + ") is not equal to " + CBORType.Number); } if (b.Type != CBORType.Number) { throw new ArgumentException("b.Type (" + b.Type + ") is not equal to " + CBORType.Number); } object objA = a.ThisItem; object objB = b.ThisItem; int typeA = a.ItemType; int typeB = b.ItemType; if (typeA == CBORObject.CBORObjectTypeInteger && typeB == CBORObject.CBORObjectTypeInteger) { var valueA = (long)objA; var valueB = (long)objB; if (valueB == 0) { return((valueA == 0) ? CBORObject.NaN : ((valueA < 0) ? CBORObject.NegativeInfinity : CBORObject.PositiveInfinity)); } if (valueA == Int64.MinValue && valueB == -1) { return(CBORObject.FromObject(valueA).Negate()); } long quo = valueA / valueB; long rem = valueA - (quo * valueB); return((rem == 0) ? CBORObject.FromObject(quo) : CBORObject.FromObject( ERational.Create( (EInteger)valueA, (EInteger)valueB))); } if (typeA == CBORObject.CBORObjectTypeExtendedRational || typeB == CBORObject.CBORObjectTypeExtendedRational) { ERational e1 = CBORObject.GetNumberInterface(typeA).AsExtendedRational(objA); ERational e2 = CBORObject.GetNumberInterface(typeB).AsExtendedRational(objB); return(CBORObject.FromObject(e1.Divide(e2))); } if (typeA == CBORObject.CBORObjectTypeExtendedDecimal || typeB == CBORObject.CBORObjectTypeExtendedDecimal) { EDecimal e1 = CBORObject.GetNumberInterface(typeA).AsExtendedDecimal(objA); EDecimal e2 = CBORObject.GetNumberInterface(typeB).AsExtendedDecimal(objB); if (e1.IsZero && e2.IsZero) { return(CBORObject.NaN); } EDecimal eret = e1.Divide(e2, null); // If either operand is infinity or NaN, the result // is already exact. Likewise if the result is a finite number. if (!e1.IsFinite || !e2.IsFinite || eret.IsFinite) { return(CBORObject.FromObject(eret)); } ERational er1 = CBORObject.GetNumberInterface(typeA).AsExtendedRational(objA); ERational er2 = CBORObject.GetNumberInterface(typeB).AsExtendedRational(objB); return(CBORObject.FromObject(er1.Divide(er2))); } if (typeA == CBORObject.CBORObjectTypeExtendedFloat || typeB == CBORObject.CBORObjectTypeExtendedFloat || typeA == CBORObject.CBORObjectTypeDouble || typeB == CBORObject.CBORObjectTypeDouble || typeA == CBORObject.CBORObjectTypeSingle || typeB == CBORObject.CBORObjectTypeSingle) { EFloat e1 = CBORObject.GetNumberInterface(typeA).AsExtendedFloat(objA); EFloat e2 = CBORObject.GetNumberInterface(typeB).AsExtendedFloat(objB); if (e1.IsZero && e2.IsZero) { return(CBORObject.NaN); } EFloat eret = e1.Divide(e2, null); // If either operand is infinity or NaN, the result // is already exact. Likewise if the result is a finite number. if (!e1.IsFinite || !e2.IsFinite || eret.IsFinite) { return(CBORObject.FromObject(eret)); } ERational er1 = CBORObject.GetNumberInterface(typeA).AsExtendedRational(objA); ERational er2 = CBORObject.GetNumberInterface(typeB).AsExtendedRational(objB); return(CBORObject.FromObject(er1.Divide(er2))); } else { EInteger b1 = CBORObject.GetNumberInterface(typeA).AsEInteger(objA); EInteger b2 = CBORObject.GetNumberInterface(typeB).AsEInteger(objB); if (b2.IsZero) { return(b1.IsZero ? CBORObject.NaN : ((b1.Sign < 0) ? CBORObject.NegativeInfinity : CBORObject.PositiveInfinity)); } EInteger bigrem; EInteger bigquo; { EInteger[] divrem = b1.DivRem(b2); bigquo = divrem[0]; bigrem = divrem[1]; } return(bigrem.IsZero ? CBORObject.FromObject(bigquo) : CBORObject.FromObject(ERational.Create(b1, b2))); } }
[Fact] public void FromERational() => Test(ERational.Create(EInteger.FromString("32324"), EInteger.FromString("243244")), ((Entity)"32324/243244").InnerSimplified);
private static CBORNumber RationalToNumber( CBORObject o, int tagName) { if (o.Type != CBORType.Array) { return(null); // "Big fraction must be an array"; } if (tagName == 270) { if (o.Count != 3) { return(null); // "Extended big fraction requires exactly 3 items"; } if (!IsUntaggedInteger(o[2])) { return(null); // "Third item must be an integer"; } } else { if (o.Count != 2) { return(null); // "Big fraction requires exactly 2 items"; } } if (!IsUntaggedIntegerOrBignum(o[0])) { return(null); // "Numerator is not an integer or bignum"; } if (!IsUntaggedIntegerOrBignum(o[1])) { return(null); // "Denominator is not an integer or bignum"); } EInteger numerator = IntegerOrBignum(o[0]); EInteger denominator = IntegerOrBignum(o[1]); if (denominator.Sign <= 0) { return(null); // "Denominator may not be negative or zero"); } ERational erat = ERational.Create(numerator, denominator); if (tagName == 270) { if (numerator.Sign < 0) { return(null); // "Numerator may not be negative"); } if (!o[2].CanValueFitInInt32()) { return(null); // "Invalid options"; } int options = o[2].AsInt32Value(); switch (options) { case 0: break; case 1: erat = erat.Negate(); break; case 2: if (!numerator.IsZero || denominator.CompareTo(1) != 0) { return(null); // "invalid values"); } erat = ERational.PositiveInfinity; break; case 3: if (!numerator.IsZero || denominator.CompareTo(1) != 0) { return(null); // "invalid values"); } erat = ERational.NegativeInfinity; break; case 4: case 5: case 6: case 7: if (denominator.CompareTo(1) != 0) { return(null); // "invalid values"); } erat = ERational.CreateNaN( numerator, options >= 6, options == 5 || options == 7); break; default: return(null); // "Invalid options"); } } return(CBORNumber.FromObject(erat)); }
/// <summary>Returns the quotient of this number and another /// number.</summary> /// <param name='b'>The right-hand side (divisor) to the division /// operation.</param> /// <returns>The quotient of this number and another one.</returns> /// <exception cref='ArgumentNullException'>The parameter <paramref /// name='b'/> is null.</exception> public CBORNumber Divide(CBORNumber b) { if (b == null) { throw new ArgumentNullException(nameof(b)); } CBORNumber a = this; object objA = a.value; object objB = b.value; Kind typeA = a.kind; Kind typeB = b.kind; if (typeA == Kind.Integer && typeB == Kind.Integer) { var valueA = (long)objA; var valueB = (long)objB; if (valueB == 0) { return((valueA == 0) ? CBORNumber.FromObject(EDecimal.NaN) : ((valueA < 0) ? CBORNumber.FromObject(EDecimal.NegativeInfinity) : CBORNumber.FromObject(EDecimal.PositiveInfinity))); } if (valueA == Int64.MinValue && valueB == -1) { return(new CBORNumber(Kind.Integer, valueA).Negate()); } long quo = valueA / valueB; long rem = valueA - (quo * valueB); return((rem == 0) ? new CBORNumber(Kind.Integer, quo) : new CBORNumber(Kind.ERational, ERational.Create( (EInteger)valueA, (EInteger)valueB))); } if (typeA == Kind.ERational || typeB == Kind.ERational) { ERational e1 = GetNumberInterface(typeA).AsExtendedRational(objA); ERational e2 = GetNumberInterface(typeB).AsExtendedRational(objB); return(new CBORNumber(Kind.ERational, e1.Divide(e2))); } if (typeA == Kind.EDecimal || typeB == Kind.EDecimal) { EDecimal e1 = GetNumberInterface(typeA).AsExtendedDecimal(objA); EDecimal e2 = GetNumberInterface(typeB).AsExtendedDecimal(objB); if (e1.IsZero && e2.IsZero) { return(new CBORNumber(Kind.EDecimal, EDecimal.NaN)); } EDecimal eret = e1.Divide(e2, null); // If either operand is infinity or NaN, the result // is already exact. Likewise if the result is a finite number. if (!e1.IsFinite || !e2.IsFinite || eret.IsFinite) { return(new CBORNumber(Kind.EDecimal, eret)); } ERational er1 = GetNumberInterface(typeA).AsExtendedRational(objA); ERational er2 = GetNumberInterface(typeB).AsExtendedRational(objB); return(new CBORNumber(Kind.ERational, er1.Divide(er2))); } 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); if (e1.IsZero && e2.IsZero) { return(CBORNumber.FromObject(EDecimal.NaN)); } EFloat eret = e1.Divide(e2, null); // If either operand is infinity or NaN, the result // is already exact. Likewise if the result is a finite number. if (!e1.IsFinite || !e2.IsFinite || eret.IsFinite) { return(CBORNumber.FromObject(eret)); } ERational er1 = GetNumberInterface(typeA).AsExtendedRational(objA); ERational er2 = GetNumberInterface(typeB).AsExtendedRational(objB); return(new CBORNumber(Kind.ERational, er1.Divide(er2))); } else { EInteger b1 = GetNumberInterface(typeA).AsEInteger(objA); EInteger b2 = GetNumberInterface(typeB).AsEInteger(objB); if (b2.IsZero) { return(b1.IsZero ? CBORNumber.FromObject(EDecimal.NaN) : ((b1.Sign < 0) ? CBORNumber.FromObject(EDecimal.NegativeInfinity) : CBORNumber.FromObject(EDecimal.PositiveInfinity))); } EInteger bigrem; EInteger bigquo; { EInteger[] divrem = b1.DivRem(b2); bigquo = divrem[0]; bigrem = divrem[1]; } return(bigrem.IsZero ? CBORNumber.FromObject(bigquo) : new CBORNumber(Kind.ERational, ERational.Create(b1, b2))); } }