public static Fraction /*!*/ Multiply(Fraction /*!*/ x, Fraction /*!*/ y, out int offset) { int xPrecision = x.Precision; int yPrecision = y.Precision; int zPrecision = xPrecision + yPrecision; uint[] xData = x._words; uint[] yData = y._words; uint[] zData = new uint[zPrecision]; Fraction z = new Fraction(zData); for (int xIndex = xPrecision - 1; xIndex >= 0; xIndex--) { uint xValue = xData[xIndex]; int zIndex = zPrecision - (xPrecision - xIndex); ulong carry = 0; for (int yIndex = yPrecision - 1; yIndex >= 0; yIndex--) { carry = carry + ((ulong)xValue) * yData[yIndex] + zData[zIndex]; zData[zIndex--] = (uint)(carry % BASE); carry /= BASE; } while (carry != 0) { carry += zData[zIndex]; zData[zIndex--] = (uint)carry; carry /= BASE; } } z = Fraction.Normalize(z, out offset); return(z); }
public static Fraction /*!*/ Subtract(Fraction /*!*/ x, Fraction /*!*/ y, int exponentDiff, out int exponentOffset, out int sign) { Fraction upper = x; Fraction lower = y; sign = Compare(x, y, exponentDiff); if (sign == 0) { exponentOffset = 0; return(new Fraction(1)); } else if (sign < 0) { exponentDiff = -exponentDiff; upper = y; lower = x; } // Calculate the word and digit offsets between upper and lower int wordOffset = exponentDiff / BASE_FIG; int digitOffset = exponentDiff % BASE_FIG; // If necessary we need to scroll one of the arrays if (digitOffset != 0) { lower = ScrollRight(lower, digitOffset); } int lowerStart = wordOffset; // We should now have something like: // UUU UUU UU0 000 000 000 (upperStart=0, upperLength=8) // 000 0LL LLL LLL LLL LL0 (lowerStart=4, lowerLength=13) // assuming that exponentDiff is 4 (or -4) and BASE_FIG is 3 // where each character above is a decimal digit and a space indicates a word boundary // Also, upper should be larger than lower int zPrecision = System.Math.Max(upper.Precision, lower.Precision + lowerStart); Fraction z = new Fraction(zPrecision); uint[] upperWords = upper._words; uint[] lowerWords = lower._words; uint[] zWords = z._words; // Copy words of upper straight into z Array.Copy(upperWords, 0, zWords, 0, upper.Precision); //// Subtract words of lower from z, borrowing as necessary SubtractInPlace(zWords, lowerWords, lower.Precision, lowerStart); z = Fraction.Normalize(z, out exponentOffset); return(z); }
private static Fraction /*!*/ Parse(string /*!*/ digits, out int digitOffset) { // Trim off any trailing zeros digits = digits.TrimEnd('0'); if (digits == "") { digitOffset = 0; return(Zero); } // Create the new fraction int precision = digits.Length / BASE_FIG; int finalDigits = digits.Length % BASE_FIG; if (finalDigits > 0) { ++precision; } Fraction /*!*/ fraction = new Fraction(precision); // Iterate through groups of BASE_FIG digits int digitIndex; int wordIndex = 0; for (digitIndex = 0; digitIndex + BASE_FIG <= digits.Length; digitIndex += BASE_FIG) { fraction._words[wordIndex] = uint.Parse(digits.Substring(digitIndex, BASE_FIG), CultureInfo.InvariantCulture); wordIndex++; } // Add on the last few digits, adding extra zeros as necessary if (finalDigits > 0) { uint lastWord = uint.Parse(digits.Substring(digitIndex), CultureInfo.InvariantCulture); while (finalDigits < BASE_FIG) { lastWord *= 10; ++finalDigits; } fraction._words[wordIndex] = lastWord; } fraction = Fraction.Normalize(fraction, out digitOffset); return(fraction); }
public static Fraction /*!*/ Add(Fraction /*!*/ x, Fraction /*!*/ y, int exponentDiff, out int exponentOffset) { Fraction upper = x; Fraction lower = y; // Switch x and y around if the exponentDiff is negative bool swap = exponentDiff < 0; if (swap) { exponentDiff = -exponentDiff; upper = y; lower = x; } // Calculate the word and digit offsets between upper and lower int wordOffset = exponentDiff / BASE_FIG; int digitOffset = exponentDiff % BASE_FIG; // If necessary we need to scroll one of the arrays if (digitOffset != 0) { lower = ScrollRight(lower, digitOffset); } int upperStart = 0; int lowerStart = wordOffset; // We should now have something like: // UUU UUU UU0 000 000 000 (upperStart=0, upperLength=8) // 000 0LL LLL LLL LLL LL0 (lowerStart=4, lowerLength=13) // assuming that exponentDiff is 4 (or -4) and BASE_FIG is 3 // where each character above is a decimal digit and a space indicates a word boundary int zPrecision = System.Math.Max(upper.Precision, lower.Precision + wordOffset) + 1; Fraction z = new Fraction(zPrecision); uint[] upperWords = upper._words; uint[] lowerWords = lower._words; uint[] zWords = z._words; // Copy words of lower straight into z Array.Copy(lowerWords, 0, zWords, lowerStart + 1, lower.Precision); // Add words of upper into z, carrying as necessary ulong carry = 0; for (int i = upper.Precision - 1; i >= upperStart; i--) { carry += upperWords[i] + zWords[i + 1]; zWords[i + 1] = (uint)(carry % BASE); carry /= BASE; } Debug.Assert(carry / BASE == 0); zWords[0] = (uint)(carry % BASE); // We expect there to be BASE_FIG offset when normalizing unless // the carry overflowed into the top word. z = Fraction.Normalize(z, out exponentOffset); exponentOffset += BASE_FIG; return(z); }