/// <summary> /// Computes the quotient of two double double numbers. /// </summary> /// <param name="a">The dividend.</param> /// <param name="b">The divisor.</param> /// <returns>The value of <paramref name="a"/> / <paramref name="b"/>.</returns> public static DoubleDouble operator /(DoubleDouble a, DoubleDouble b) { double q1 = a.hi / b.hi; DoubleDouble r = a - q1 * b; double q2 = r.hi / b.hi; r = r - q2 * b; double q3 = r.hi / b.hi; double qHi, qLo; double t1, t2, t3; ExtendedMath.TwoSum(q1, q2, out t1, out t2); ExtendedMath.TwoSum(q3, t1, out qHi, out t3); ExtendedMath.TwoSum(t2, t3, out qLo, out t1); return(new DoubleDouble(qHi, qLo)); /* * // Compute an initial approximation by dividing hi parts. * double qHi = a.hi / b.hi; * * // Compute the product of qHi and bHi to full precision. * // Ideally this would be exactly aHi but it won't be. * double uHi, uLo; * ExtendedMath.TwoProduct(qHi, b.hi, out uHi, out uLo); * * // Now compute the correction and but it in qLo. * double qLo = ((((a.hi - uHi) - uLo) + a.lo) - qHi * b.lo) / b.hi; * * return new DoubleDouble(qHi, qLo); */ }
public static void ThreeSum(double a, double b, double c, out double sum, out double err) { double t1, t2, t3; ExtendedMath.TwoSum(a, b, out t1, out t2); ExtendedMath.TwoSum(c, t1, out sum, out t3); ExtendedMath.TwoSum(t2, t3, out err, out t1); }
/// <summary> /// Computes the sum of two double double numbers. /// </summary> /// <param name="x">The first number.</param> /// <param name="y">The second number.</param> /// <returns>The value of <paramref name="x"/> + <paramref name="y"/>.</returns> public static DoubleDouble operator +(DoubleDouble x, DoubleDouble y) { // Add high components ExtendedMath.TwoSum(x.hi, y.hi, out double sHi, out double sLo); if (ExtendedMath.IsNotFinite(sHi)) { return((DoubleDouble)sHi); } // Add low components ExtendedMath.TwoSum(x.lo, y.lo, out double tHi, out double tLo); ExtendedMath.TwoSum(sHi, sLo + tHi, out double vHi, out double vLo); ExtendedMath.FastTwoSum(vHi, tLo + vLo, out double zHi, out double zLo); return(new DoubleDouble(zHi, zLo)); }
/// <summary> /// Computes the quotient of two double double numbers. /// </summary> /// <param name="x">The dividend.</param> /// <param name="y">The divisor.</param> /// <returns>The value of <paramref name="x"/> / <paramref name="y"/>.</returns> public static DoubleDouble operator /(DoubleDouble x, DoubleDouble y) { double q1 = x.hi / y.hi; // If leading order result is NaN or infinity or zero, we are done. // To continue would introduce NaNs even if result is infinite, so this early return is necessary. if (q1 == 0.0 || ExtendedMath.IsNotFinite(q1)) { return((DoubleDouble)q1); } DoubleDouble r = x - q1 * y; double q2 = r.hi / y.hi; r = r - q2 * y; double q3 = r.hi / y.hi; double qHi, qLo; double t1, t2, t3; ExtendedMath.TwoSum(q1, q2, out t1, out t2); ExtendedMath.TwoSum(q3, t1, out qHi, out t3); ExtendedMath.TwoSum(t2, t3, out qLo, out t1); return(new DoubleDouble(qHi, qLo)); /* * // Compute an initial approximation by dividing hi parts. * double qHi = a.hi / b.hi; * * // Compute the product of qHi and bHi to full precision. * // Ideally this would be exactly aHi but it won't be. * double uHi, uLo; * ExtendedMath.TwoProduct(qHi, b.hi, out uHi, out uLo); * * // Now compute the correction and but it in qLo. * double qLo = ((((a.hi - uHi) - uLo) + a.lo) - qHi * b.lo) / b.hi; * * return new DoubleDouble(qHi, qLo); */ }
/// <summary> /// Computes the sum of two double double numbers. /// </summary> /// <param name="a">The first number.</param> /// <param name="b">The second number.</param> /// <returns>The value of <paramref name="a"/> + <paramref name="b"/>.</returns> public static DoubleDouble operator +(DoubleDouble a, DoubleDouble b) { // Add high components double sHi, sLo; ExtendedMath.TwoSum(a.hi, b.hi, out sHi, out sLo); // Add low components double tHi, tLo; ExtendedMath.TwoSum(a.lo, b.lo, out tHi, out tLo); double vHi, vLo; ExtendedMath.TwoSum(sHi, sLo + tHi, out vHi, out vLo); double zHi, zLo; ExtendedMath.FastTwoSum(vHi, tLo + vLo, out zHi, out zLo); return(new DoubleDouble(zHi, zLo)); }