Example #1
0
		/// <summary>
		/// Creates an inverted NuGenFraction
		/// </summary>
		/// <returns>The inverted NuGenFraction (with Denominator over Numerator)</returns>
		/// <remarks>Does NOT throw for zero Numerators as later use of the fraction will catch the error.</remarks>
		public static NuGenFraction Inverted(double value)
		{
			NuGenFraction frac = new NuGenFraction(value);
			return frac.Inverse();
		}
Example #2
0
		/// <summary>
		/// Compares this NuGenFraction to another NuGenFraction
		/// </summary>
		/// <param name="right">The NuGenFraction 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>
		public int CompareTo(NuGenFraction right)
		{
						
			// if left is an indeterminate, punt to the helper...
			if (this.m_Denominator == 0)
			{
				return IndeterminantCompare(NormalizeIndeterminate(this.m_Numerator), right);
			}

			// if right is an indeterminate, punt to the helper...
			if (right.m_Denominator == 0)
			{
				// note sign-flip...
				return - IndeterminantCompare(NormalizeIndeterminate(right.m_Numerator), this);
			}

			// they're both normal Fractions
			CrossReducePair(ref this, ref right);

			try
			{
				checked
				{
					long leftScale = this.m_Numerator * right.m_Denominator;
					long rightScale = this.m_Denominator * right.m_Numerator;

					if (leftScale < rightScale)
						return -1;

					else if (leftScale > rightScale)
						return 1;

					else
						return 0;
				}
			}

			catch (Exception e)
			{
				throw new NuGenFractionException(string.Format("CompareTo({0}, {1}) error", this, right), e);
			}
		}
Example #3
0
		/// <summary>
		/// Returns the modulus (remainder after dividing) two Fractions
		/// </summary>
		/// <param name="left">A NuGenFraction</param>
		/// <param name="right">Another NuGenFraction</param>
		/// <returns>Modulus of the Fractions. Returns NaN if either NuGenFraction is a NaN.</returns>
		/// <exception cref="NuGenFractionException">Will throw if an overflow occurs. Does a cross-reduce to 
		/// insure only the unavoidable overflows occur.</exception>
		private static NuGenFraction Modulus(NuGenFraction left, NuGenFraction right)
		{
						
			if (left.IsNaN() || right.IsNaN())
				return NaN;

			try
			{
				checked
				{
					// this will discard any fractional places...
					Int64 quotient = (Int64)(left / right);
					NuGenFraction whole = new NuGenFraction(quotient * right.m_Numerator, right.m_Denominator);
					return left - whole;
				}
			}

			catch (Exception e)
			{
				throw new NuGenFractionException("Modulus error", e);
			}
		}
Example #4
0
		/// <summary>
		/// Inverts a NuGenFraction
		/// </summary>
		/// <returns>The inverted NuGenFraction (with Denominator over Numerator)</returns>
		/// <remarks>Does NOT throw for zero Numerators as later use of the fraction will catch the error.</remarks>
		public NuGenFraction Inverse()
		{
			// don't use the obvious constructor because we do not want it normalized at this time
			NuGenFraction frac = new NuGenFraction();

			frac.m_Numerator = this.m_Denominator;
			frac.m_Denominator = this.m_Numerator;
			return frac;
		}
Example #5
0
		/// <summary>
		/// Adds two Fractions
		/// </summary>
		/// <param name="left">A NuGenFraction</param>
		/// <param name="right">Another NuGenFraction</param>
		/// <returns>Sum of the Fractions. Returns NaN if either NuGenFraction is a NaN.</returns>
		/// <exception cref="NuGenFractionException">Will throw if an overflow occurs when computing the
		/// GCD-normalized values.</exception>
		private static NuGenFraction Add(NuGenFraction left, NuGenFraction 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 NuGenFraction(numerator, denominator);
				}
			}

			catch (Exception e)
			{
				throw new NuGenFractionException("Add error", e);
			}
		}
Example #6
0
		/// <summary>
		/// Multiplies two Fractions
		/// </summary>
		/// <param name="left">A NuGenFraction</param>
		/// <param name="right">Another NuGenFraction</param>
		/// <returns>Product of the Fractions. Returns NaN if either NuGenFraction is a NaN.</returns>
		/// <exception cref="NuGenFractionException">Will throw if an overflow occurs. Does a cross-reduce to 
		/// insure only the unavoidable overflows occur.</exception>
		private static NuGenFraction Multiply(NuGenFraction left, NuGenFraction 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 NuGenFraction(numerator, denominator);
				}
			}

			catch (Exception e)
			{
				throw new NuGenFractionException("Multiply error", e);
			}
		}
Example #7
0
		/// <summary>
		/// Negates the NuGenFraction
		/// </summary>
		/// <param name="frac">Value to negate</param>
		/// <returns>A new NuGenFraction that is sign-flipped from the input</returns>
		private static NuGenFraction Negate(NuGenFraction frac)
		{
			// for a NaN, it's still a NaN
			return new NuGenFraction( - frac.m_Numerator, frac.m_Denominator);
		}
Example #8
0
		/// <summary>
		/// Determines how this NuGenFraction, of an indeterminate type, compares to another NuGenFraction
		/// </summary>
		/// <param name="leftType">What kind of indeterminate</param>
		/// <param name="right">The other NuGenFraction 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, NuGenFraction 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;
			}
		}
Example #9
0
		/// <summary>
		/// Compares for equality the current NuGenFraction to the value passed.
		/// </summary>
		/// <param name="right">A NuGenFraction to compare against</param>
		/// <param name="notEqualCheck">If true, we're looking for not-equal</param>
		/// <returns>True if the <paramref name="right"></paramref> equals the current 
		/// fraction, false otherwise. If comparing two NaNs, they are always equal AND
		/// not-equal.</returns>
		private bool CompareEquality(NuGenFraction right, bool notEqualCheck)
		{
			// insure we're normalized first
			ReduceFraction(ref this);

			// now normalize the comperand
			ReduceFraction(ref right);

			if (this.m_Numerator == right.m_Numerator && this.m_Denominator == right.m_Denominator)
			{

				// special-case rule, two NaNs are always both equal
				if (notEqualCheck && this.IsNaN())
					return true;

				else
					return ! notEqualCheck;
			}

			else
			{
				return notEqualCheck;
			}
		}
Example #10
0
		/// <summary>
		/// Cross-reduces a pair of Fractions so that we have the best GCD-reduced values for multiplication
		/// </summary>
		/// <param name="frac1">The first NuGenFraction [WILL BE MODIFIED IN PLACE]</param>
		/// <param name="frac2">The second NuGenFraction [WILL BE MODIFIED IN PLACE]</param>
		/// <remarks>Modifies the input arguments in-place!</remarks>
		/// <example>(3/4, 5/9) = (1/4, 5/3)</example>
		public static void CrossReducePair(ref NuGenFraction frac1, ref NuGenFraction frac2)
		{
						
			// leave the indeterminates alone!
			if (frac1.m_Denominator == 0 || frac2.m_Denominator == 0)
				return;

			long gcdTop = GCD(frac1.m_Numerator, frac2.m_Denominator);
			frac1.m_Numerator = frac1.m_Numerator / gcdTop;
			frac2.m_Denominator = frac2.m_Denominator / gcdTop;

			long gcdBottom = GCD(frac1.m_Denominator, frac2.m_Numerator);
			frac2.m_Numerator = frac2.m_Numerator / gcdBottom;
			frac1.m_Denominator = frac1.m_Denominator / gcdBottom;
		}
Example #11
0
		/// <summary>
		/// Reduces (simplifies) a NuGenFraction by dividing down to lowest possible denominator (via GCD)
		/// </summary>
		/// <param name="frac">The NuGenFraction to be reduced [WILL BE MODIFIED IN PLACE]</param>
		/// <remarks>Modifies the input arguments in-place! Will normalize the NaN and infinites
		/// representation. Will set Denominator to 1 for any zero numerator. Moves sign to the
		/// Numerator.</remarks>
		/// <example>2/4 will be reduced to 1/2</example>
		public static void ReduceFraction(ref NuGenFraction frac)
		{
						
			// clean up the NaNs and infinites
			if (frac.m_Denominator == 0)
			{
				frac.m_Numerator = (long)NormalizeIndeterminate(frac.m_Numerator);
				return;
			}

			// all forms of zero are alike.
			if (frac.m_Numerator == 0)
			{
				frac.m_Denominator = 1;
				return;
			}
	            
			long iGCD = GCD(frac.m_Numerator, frac.m_Denominator);
			frac.m_Numerator /= iGCD;
			frac.m_Denominator /= iGCD;
	        
			// if negative sign in denominator
			if ( frac.m_Denominator < 0 )
			{
				//move negative sign to numerator
				frac.m_Numerator = - frac.m_Numerator;
				frac.m_Denominator = - frac.m_Denominator;  
			}
		}