divide method
- FloatingPointValue a,
- FloatingPointValue b, {
- FloatingPointRoundingMode roundingMode = FloatingPointRoundingMode.roundNearestEven,
Divides a by b exactly (to sufficient precision) and rounds once
into this format.
b must be nonzero: callers are expected to handle infinity and
zero-divisor special cases before calling this (as
FloatingPointValue.operator / does). NaN operands are propagated
correctly.
Implementation
FpvType divide(FloatingPointValue a, FloatingPointValue b,
{FloatingPointRoundingMode roundingMode =
FloatingPointRoundingMode.roundNearestEven}) {
if (a.isNaN | b.isNaN) {
return _propagateNaN(a, b);
}
final negative = a.sign.toBool() != b.sign.toBool();
final aExact = _decodeFinite(a);
final bExact = _decodeFinite(b);
if (aExact.significand == BigInt.zero) {
return _zero(negative);
}
// Compute the quotient's significand to at least `guardBits` bits more
// precision than the target format needs, by left-shifting the
// dividend before doing exact BigInt integer division. Shifting left
// (never right) means no dividend precision is ever silently
// discarded. Any nonzero remainder from the integer division is folded
// into the quotient's LSB as a sticky bit -- a standard technique so
// that information about further (unrepresented) nonzero low-order
// bits isn't lost for tie-breaking during later rounding.
final fractionWidth = mantissaWidth - (explicitJBit ? 1 : 0);
final guardBits = fractionWidth + 4;
final shiftAmount = max(
0,
bExact.significand.bitLength +
guardBits -
aExact.significand.bitLength);
final shiftedDividend = aExact.significand << shiftAmount;
var quotient = shiftedDividend ~/ bExact.significand;
final remainder = shiftedDividend.remainder(bExact.significand);
if (remainder != BigInt.zero) {
quotient |= BigInt.one;
}
return _quantize((
significand: quotient,
exponent: aExact.exponent - bExact.exponent - shiftAmount,
), negative: negative, roundingMode: roundingMode);
}