Act nowcan affect a running systemThe raw payload contains no superseded_by markers. The embedded consecutive diffs nevertheless show one explicit GetNumericVariantFromJson regression fix and several cumulative conversion fixes. Commit aa165fe9 and its merge do not increment mormot.commit-num.inc beyond 16851, so the full landing SHA matters.
Decimal parsing reaches exact IEEE rounding after a zero regression
This edition continues the numeric conversion stabilization with production-visible correctness fixes in both directions. DoubleToAscii now handles scientific notation and 64-bit sticky-bit rounding correctly, while GetExtended accepts boundary exponents and rounds common decimal fractions to the nearest IEEE double. GetNumericVariantFromJson also restores numeric handling for 0.0, so backends that exchange JSON numbers or persist floating-point text should take the completed series.
TL;DR
- Land on commit c9eff241 at build 2.4.16851; it includes the final decimal-rounding merge after the version number was last incremented.
- GetNumericVariantFromJson again parses 0.0 and all-zero fractional forms as numeric zero instead of failing the numeric conversion.
- GetExtended and GetNumericVariantFromJson now return the nearest IEEE double for common fractions such as 1.2 instead of a one-ULP-high value.
- DoubleToAscii fixes scientific-notation punctuation and applies sticky-bit rounding on CPU64, improving exact floating-point text round trips.
- The non-WIN32DELPHI GetExtended path now handles minimum subnormal and maximum finite double boundaries without premature failure.
Upgrade advice
Take the final c9eff241 revision identified as build 2.4.16851, not merely an earlier commit carrying that build number. Avoid builds 2.4.16844 through 2.4.16850 because GetNumericVariantFromJson can reject 0.0 there, and the output/parser boundary work is still incomplete. After upgrading, rerun JSON numeric, scientific-notation and exact double round-trip tests on every Delphi and FPC target you ship.
8 of 8 entries · 9 commits upstream
1
High
Common decimal fractions now round to the nearest IEEE double
GetExtended in mormot.core.text and GetNumericVariantFromJson in mormot.core.variants use Clinger’s fast path when the fractional exponent is -1 through -22 and the accumulated integer is within MAX_SAFE_JS_INTEGER. They divide by an exactly represented positive power of ten instead of multiplying by an inexact negative power; exact-bit tests cover values including 1.2, 0.1, 2.675 and small JSON doubles.
Fixes
mormot.core.text+1
aa165fe9+87-10
core: correctly rounded GetExtended() and GetNumericVariantFromJson() decimals
Impact
Parsed doubles for common decimal text can change by one ULP to the correctly rounded value; for example, 1.2 no longer becomes 1.2000000000000002 on the affected Pascal path. FPC and non-Win32 Delphi GetExtended callers benefit directly, while GetNumericVariantFromJson is corrected across Delphi and FPC backends.
Upgrade recommended
Take the merged c9eff241 head and rerun exact numeric comparisons, hashes or persisted-value tests that depend on parsed double bits.
Public API
GetExtendedbehaviour-changed — Common decimal fractions on the Pascal path now produce the nearest IEEE double.GetNumericVariantFromJsonbehaviour-changed — Eligible JSON fractions now produce the nearest IEEE double rather than a one-ULP rounding error.
2
High
CPU64 formatting now keeps the sticky digit needed for correct rounding
DoubleToAscii in mormot.core.text now appends a synthetic nonzero sticky digit on CPU64 as well as CPU32 when discarded bits remain beyond the requested precision. d2a_k_comp also replaces floating-point logarithm arithmetic with an inline fixed-point integer estimate, and exponential output writes a decimal point whenever retained fractional digits exist.
Fixes
mormot.core.text
f4433cf3+13-24
core: fixed DoubleToAscii()
Impact
Delphi 64-bit and FPC 64-bit builds can produce different final digits for tie-adjacent values, now following round-to-nearest-even with the discarded tail represented. Serialized floating-point strings become more reliable for exact parse-back; signatures do not change.
Upgrade recommended
Upgrade through the final c9eff241 revision and rerun exact floating-point serialization round trips on CPU64.
Public API
DoubleToAsciibehaviour-changed — CPU64 rounding now accounts for discarded nonzero bits through a sticky digit.
Units
3
High
Extreme decimal exponents reach valid double boundaries
The non-WIN32DELPHI GetExtended implementation in mormot.core.text no longer rejects every frac value at or below -324. For the reachable -342 through -324 range it pre-scales d64 before applying the remaining negative power, and it permits frac 308 to pass through the existing overflow-safe scaling path.
Fixes
mormot.core.text
56bb70cd+14-4
core: fixed GetExtended() on huge/tiny exponents
Impact
FPC and non-Win32 Delphi backends can now parse valid minimum-subnormal and maximum-finite decimal values instead of reporting an error or losing them prematurely. The Delphi Win32 x87 assembly implementation is not changed by this commit.
Worth a look
Retest accepted and rejected exponent boundaries if input validation depends on GetExtended returning err.
Public API
GetExtendedbehaviour-changed — The Pascal path accepts valid extreme double exponents that were previously rejected prematurely.
Units
4
High
JSON fractional zero is numeric again
GetNumericVariantFromJson in mormot.core.variants no longer exits when it reaches a delimiter after one or more fractional zeros. It distinguishes a missing first digit after the decimal point from a completed all-zero fractional part, and new tests require 0.0 and 0.000000000 to return varInteger zero.
Fixes
mormot.core.variants
58178149+8-3
core: fixed regression in GetNumericVariantFromJson()
Impact
JSON numeric zero with a decimal point no longer fails this fast numeric parser or falls through to a nonnumeric representation in higher-level conversion paths. Delphi and FPC services receiving 0.0 regain the same normalized integer-zero result as other zero spellings.
Upgrade recommended
Move past builds 2.4.16844–2.4.16850 and test JSON fields that may contain 0.0 or zero with trailing fractional digits.
Public API
GetNumericVariantFromJsonbehaviour-changed — All-zero fractional JSON forms again parse successfully and normalize to varInteger zero.
Units
5
Medium
Zero exponents take a safe fast path before scaling
The Pascal GetExtended path in mormot.core.text returns signed zero through the common sign epilogue before any exponent scaling when v64 is zero. The tiny-exponent calculation is also regrouped so d64, the 1E-160 factor and the remaining inverse power are multiplied in one expression.
Fixes
mormot.core.text
8b5a85a4+19-7
core: refine some GetExtended() specific cases
Impact
FPC and non-Win32 Delphi backends accept 0E400 and 0E-400 without a range error and preserve negative zero. Existing source code needs no change; Delphi Win32 continues to use its separate assembly parser.
Public API
GetExtendedbehaviour-changed — Zero remains valid regardless of a very large exponent, with its sign preserved.
Units
6
Medium
Scientific formatting no longer emits a misplaced decimal point
In mormot.core.text, d2a_return_exponential now decides whether to write the decimal point after limiting n_digits_have to n_digits_req. The separator is emitted with the fractional significant digits rather than before their final count is known.
Fixes
mormot.core.text
37212dc4+8-8
core: fixed DoubleToAscii() correctness of scientific notation
Impact
Existing Delphi and FPC code keeps the same DoubleToAscii signature, but edge-case scientific strings can change to valid punctuation. Consumers comparing serialized floating-point text byte for byte should update expected values after taking the full series.
Worth a look
Rerun golden-output tests that compare DoubleToAscii scientific notation exactly.
Public API
DoubleToAsciibehaviour-changed — Scientific output places the decimal separator only when fractional significant digits are emitted.
Units
7
Low
Round-trip coverage expands across signs, scales and exact bit patterns
test.core.base adds positive and negative DoubleToShort cases from 1.5E-19 through 2E19, exact QWord-to-double vectors and GetExtended checks for zero with very large positive or negative exponents. It also verifies a TimeSpan input with trailing whitespace.
Tests
a155bf80+34-3
tests: enhanced double / text conversion coverage
Impact
No application code or public API changes. The expanded suite locks in formatter/parser round trips across Delphi and FPC and documents that the exact-bit GetExtended boundary checks are not applied to WIN32DELPHI.
8
Low
Conversion tests gain exact boundary vectors
test.core.base adds exact-bit assertions for minimum subnormal, maximum finite and other boundary doubles, plus positive and negative scientific-notation round trips. Its local output helper now compares ShortString values directly.
Tests
511fe932+25-8
tests: enhanced floating point conversion vectors
Impact
No application code or public API changes. The tests make later parser and formatter boundary corrections observable on Delphi and FPC, while exact GetExtended bit checks remain excluded for WIN32DELPHI.