(value: number)
| 240 | } |
| 241 | |
| 242 | function floatToParts(value: number): DecimalParts { |
| 243 | if (!Number.isFinite(value)) { |
| 244 | throw new Error(`Non-finite scalar value ${value}.`); |
| 245 | } |
| 246 | if (Object.is(value, -0)) { |
| 247 | return { unscaled: 0n, scale: 0, negativeZero: true }; |
| 248 | } |
| 249 | if (value === 0) { |
| 250 | return { unscaled: 0n, scale: 0, negativeZero: false }; |
| 251 | } |
| 252 | float64DataView.setFloat64(0, value, false); |
| 253 | const bits = float64DataView.getBigUint64(0, false); |
| 254 | const negative = bits >> 63n !== 0n; |
| 255 | const exponentBits = Number((bits >> 52n) & 0x7ffn); |
| 256 | const fraction = bits & ((1n << 52n) - 1n); |
| 257 | let mantissa: bigint; |
| 258 | let exponent: number; |
| 259 | if (exponentBits === 0) { |
| 260 | mantissa = fraction; |
| 261 | exponent = 1 - 1023 - 52; |
| 262 | } else { |
| 263 | mantissa = (1n << 52n) | fraction; |
| 264 | exponent = exponentBits - 1023 - 52; |
| 265 | } |
| 266 | if (negative) { |
| 267 | mantissa = -mantissa; |
| 268 | } |
| 269 | if (exponent >= 0) { |
| 270 | return normalizeParts({ |
| 271 | unscaled: mantissa << BigInt(exponent), |
| 272 | scale: 0, |
| 273 | negativeZero: false, |
| 274 | }); |
| 275 | } |
| 276 | const scale = -exponent; |
| 277 | if (scale > MAX_COMPATIBLE_DECIMAL_DIGITS) { |
| 278 | throw new Error("Scalar float decimal expansion exceeds compatible limit."); |
| 279 | } |
| 280 | return normalizeParts({ |
| 281 | unscaled: mantissa * pow5(scale), |
| 282 | scale, |
| 283 | negativeZero: false, |
| 284 | }); |
| 285 | } |
| 286 | |
| 287 | function parseDecimalString(value: string): DecimalParts { |
| 288 | if (value.length === 0 || value.length > MAX_COMPATIBLE_NUMERIC_TEXT_LENGTH) { |
no test coverage detected