convertDecimalToBinary static method
BsonBinary
convertDecimalToBinary(
- Decimal? decimal
)
Implementation
static BsonBinary convertDecimalToBinary(Decimal? decimal) {
if (decimal == null) {
// Decimal does not manage NaN
return BsonBinary.fromHexString('0000000000000000000000000000007c');
} else if (decimal == infinityValue) {
// Decimal does not manage infinity, this is a conventional value
return BsonBinary.fromHexString('00000000000000000000000000000078');
} else if (decimal == -infinityValue) {
// Decimal does not manage -infinity, this is a conventional value
return BsonBinary.fromHexString('000000000000000000000000000000f8');
} else if (decimal == Decimal.zero) {
return BsonBinary.fromHexString('00000000000000000000000000004030');
} else if (
// if bigger than one (i.e at least one integer digit)
// we could have a lot of unnecessary trailing zeros calculated
// in the precision.
decimal < Decimal.one && decimal.significandLength > 34) {
// Return zero
return BsonBinary.fromHexString('00000000000000000000000000004030');
}
String res = decimal.toStringAsFixed(decimal.scaleFast);
var exponent = extractExponent(res);
var significand = extractSignificand(res);
// Significand greater or equal to 10^34 - 1 must be considered as 0
if (significand > maxSignificand) {
significand = Decimal.zero;
}
// The exponent calculated implies that the significand is of the form
// i.ddddddd, but our significand must be an integer.
// plus 6176 (exp 0, lower is negative)
var biasedExponent = exponent + 6176;
// encoding as case 1 number (first bit of the combination field not '11')
// because the minimum value of the case 2 (2^114) is higher than
// the max allowed value (10^34-1)
var highSignificand = Decimal.fromBigInt(significand ~/ maxUInt64);
var lowSignificand = significand - (highSignificand * maxUInt64);
// Needed because we are using Int instead of UInt
if (lowSignificand >= maxInt64) {
lowSignificand -= maxUInt64;
}
var lowInt = Int64.parseRadix(lowSignificand.toString(), 10);
var highInt = Int64.parseRadix(highSignificand.toString(), 10);
highInt += (Int64(biasedExponent) << 49);
if (decimal.isNegative) {
highInt |= signMask;
}
return BsonBinary(16)
..writeFixInt64(lowInt)
..writeFixInt64(highInt);
}