roundBigIntByPowerOfTwo function
- BigInt value,
- int discardedWidth, {
- required FloatingPointRoundingMode roundingMode,
Divides value by 2^[discardedWidth] using roundingMode.
This operates entirely on BigInt so value-side arithmetic can round without passing through a host floating-point type.
Implementation
BigInt roundBigIntByPowerOfTwo(BigInt value, int discardedWidth,
{required FloatingPointRoundingMode roundingMode}) {
if (discardedWidth < 0) {
throw ArgumentError.value(
discardedWidth, 'discardedWidth', 'Must be non-negative.');
}
if (discardedWidth == 0 || value == BigInt.zero) {
return value;
}
final negative = value.isNegative;
final magnitude = value.abs();
final quotient = magnitude >> discardedWidth;
final remainder = magnitude & ((BigInt.one << discardedWidth) - BigInt.one);
if (remainder == BigInt.zero) {
return negative ? -quotient : quotient;
}
final increment = switch (roundingMode) {
FloatingPointRoundingMode.truncate ||
FloatingPointRoundingMode.roundTowardsZero =>
false,
FloatingPointRoundingMode.roundTowardsInfinity => !negative,
FloatingPointRoundingMode.roundTowardsNegativeInfinity => negative,
FloatingPointRoundingMode.roundNearestTiesAway =>
remainder >= (BigInt.one << (discardedWidth - 1)),
FloatingPointRoundingMode.roundNearestEven =>
remainder > (BigInt.one << (discardedWidth - 1)) ||
(remainder == (BigInt.one << (discardedWidth - 1)) && quotient.isOdd),
};
final rounded = increment ? quotient + BigInt.one : quotient;
return negative ? -rounded : rounded;
}