ofDouble method
- double inDouble, {
- FloatingPointRoundingMode roundingMode = FloatingPointRoundingMode.roundNearestEven,
Convert from double using its native binary representation
Implementation
FpvType ofDouble(double inDouble,
{FloatingPointRoundingMode roundingMode =
FloatingPointRoundingMode.roundNearestEven}) {
if (explicitJBit) {
return ofFloatingPointValue(FloatingPointValue.populator(
exponentWidth: exponentWidth, mantissaWidth: mantissaWidth - 1)
.ofDouble(inDouble, roundingMode: roundingMode)) as FpvType;
}
if (inDouble.isNaN) {
return nan;
}
if (inDouble.isInfinite) {
return ofConstant(
inDouble < 0.0
? FloatingPointConstants.negativeInfinity
: FloatingPointConstants.positiveInfinity,
);
}
if (roundingMode != FloatingPointRoundingMode.roundNearestEven &&
roundingMode != FloatingPointRoundingMode.truncate) {
throw UnimplementedError(
'Only roundNearestEven or truncate is supported for this width');
}
final fp64 = FloatingPoint64Value.populator().ofDouble(inDouble);
final fp64Mw = fp64.mantissa.width;
final exponent64 = fp64.exponent;
var expVal = (exponent64.toInt() - fp64.bias) + bias;
final mantissa64n = ((expVal <= 0)
? [LogicValue.one, fp64.mantissa].swizzle() >>>
(-expVal +
(!explicitJBit & (fp64.exponent.toInt() > 0)
? 1
: explicitJBit
? 1
: 0))
: [LogicValue.one, fp64.mantissa].swizzle());
var mantissa = mantissa64n.slice(fp64Mw - (explicitJBit ? 0 : 1),
fp64Mw - mantissaWidth + (explicitJBit ? 1 : 0));
// TODO(desmonddak): this should be in a separate function to use
// with a FloatingPointValue converter we need.
if (roundingMode == FloatingPointRoundingMode.roundNearestEven) {
final stickyPos = fp64Mw - (mantissaWidth + 3);
final sticky =
(stickyPos >= 0) ? mantissa64n.slice(stickyPos, 0).or() : 0;
final roundPos = stickyPos + 1;
final round = ((roundPos >= 0) & (roundPos > stickyPos))
? mantissa64n[roundPos]
: 0;
final guardPos = roundPos + 1;
final guard = (guardPos >= 1) ? mantissa64n[roundPos + 1] : 0;
// RNE Rounding
if (guard == LogicValue.one) {
if ((round == LogicValue.one) |
(sticky == LogicValue.one) |
(mantissa[0] == LogicValue.one)) {
mantissa += 1;
if (mantissa == LogicValue.zero.zeroExtend(mantissa.width)) {
expVal += 1;
if (explicitJBit) {
mantissa = [
LogicValue.one,
LogicValue.zero.zeroExtend(mantissa.width - 1)
].swizzle();
}
}
}
}
}
if (_unpopulated.supportsInfinities && expVal > maxExponent + bias) {
return ofConstant(
fp64.sign.toBool()
? FloatingPointConstants.negativeInfinity
: FloatingPointConstants.positiveInfinity,
);
}
final exponent =
LogicValue.ofBigInt(BigInt.from(max(expVal, 0)), exponentWidth);
if (subNormalAsZero && expVal <= 0) {
// If we are subnormal, we return zero
mantissa = LogicValue.zero.zeroExtend(mantissaWidth);
}
final sign = fp64.sign;
return populate(
sign: sign,
exponent: exponent,
mantissa: mantissa,
);
}