/// <summary> /// Returns the modulus (remainder after dividing) two Fractions /// </summary> /// <param name="left">A Fraction</param> /// <param name="right">Another Fraction</param> /// <returns>Modulus of the Fractions. Returns NaN if either Fraction is a NaN.</returns> /// <exception cref="FractionException">Will throw if an overflow occurs. Does a cross-reduce to /// insure only the unavoidable overflows occur.</exception> private static Fraction Modulus(Fraction left, Fraction right) { if (left.IsNaN() || right.IsNaN()) return NaN; try { checked { // this will discard any fractional places... Int64 quotient = (Int64)(left / right); Fraction whole = new Fraction(quotient * right.m_Numerator, right.m_Denominator); return left - whole; } } catch (Exception e) { throw new FractionException("Modulus error", e); } }
/// <summary> /// Adds two Fractions /// </summary> /// <param name="left">A Fraction</param> /// <param name="right">Another Fraction</param> /// <returns>Sum of the Fractions. Returns NaN if either Fraction is a NaN.</returns> /// <exception cref="FractionException">Will throw if an overflow occurs when computing the /// GCD-normalized values.</exception> private static Fraction Add(Fraction left, Fraction right) { if (left.IsNaN() || right.IsNaN()) return NaN; long gcd = GCD(left.m_Denominator, right.m_Denominator); // cannot return less than 1 long leftDenominator = left.m_Denominator / gcd; long rightDenominator = right.m_Denominator / gcd; try { checked { long numerator = left.m_Numerator * rightDenominator + right.m_Numerator * leftDenominator; long denominator = leftDenominator * rightDenominator * gcd; return new Fraction(numerator, denominator); } } catch (Exception e) { throw new FractionException("Add error", e); } }
/// <summary> /// Multiplies two Fractions /// </summary> /// <param name="left">A Fraction</param> /// <param name="right">Another Fraction</param> /// <returns>Product of the Fractions. Returns NaN if either Fraction is a NaN.</returns> /// <exception cref="FractionException">Will throw if an overflow occurs. Does a cross-reduce to /// insure only the unavoidable overflows occur.</exception> private static Fraction Multiply(Fraction left, Fraction right) { if (left.IsNaN() || right.IsNaN()) return NaN; // this would be unsafe if we were not a ValueType, because we would be changing the // caller's values. If we change back to a class, must use temporaries CrossReducePair(ref left, ref right); try { checked { long numerator = left.m_Numerator * right.m_Numerator; long denominator = left.m_Denominator * right.m_Denominator; return new Fraction(numerator, denominator); } } catch (Exception e) { throw new FractionException("Multiply error", e); } }
/// <summary> /// Determines how this Fraction, of an indeterminate type, compares to another Fraction /// </summary> /// <param name="leftType">What kind of indeterminate</param> /// <param name="right">The other Fraction to compare against</param> /// <returns>-1 if this is less than <paramref name="right"></paramref>, /// 0 if they are equal, /// 1 if this is greater than <paramref name="right"></paramref></returns> /// <remarks>NaN is less than anything except NaN and Negative Infinity. Negative Infinity is less /// than anything except Negative Infinity. Positive Infinity is greater than anything except /// Positive Infinity.</remarks> private static int IndeterminantCompare(Indeterminates leftType, Fraction right) { switch (leftType) { case Indeterminates.NaN: // A NaN is... if (right.IsNaN()) return 0; // equal to a NaN else if (right.IsNegativeInfinity()) return 1; // great than Negative Infinity else return -1; // less than anything else case Indeterminates.NegativeInfinity: // Negative Infinity is... if (right.IsNegativeInfinity()) return 0; // equal to Negative Infinity else return -1; // less than anything else case Indeterminates.PositiveInfinity: if (right.IsPositiveInfinity()) return 0; // equal to Positive Infinity else return 1; // greater than anything else default: // this CAN'T happen, something VERY wrong is going on... return 0; } }