Skip to content

Implement INumber, IFloatingPoint, and the modulus operator for the IEEE 754 decimal types#130890

Merged
tannergooding merged 14 commits into
dotnet:mainfrom
tannergooding:tannergooding-decimal-ieee754-ifloatingpoint
Jul 17, 2026
Merged

Implement INumber, IFloatingPoint, and the modulus operator for the IEEE 754 decimal types#130890
tannergooding merged 14 commits into
dotnet:mainfrom
tannergooding:tannergooding-decimal-ieee754-ifloatingpoint

Conversation

@tannergooding

Copy link
Copy Markdown
Member

Continues the incremental buildout of the IEEE 754 decimal types (part of #81376). #130807 added the conversion surface and INumberBase<TSelf>; this one adds the next set of interfaces and the modulus operator.

Adds to Decimal32, Decimal64, and Decimal128:

  • IFloatingPointConstants<TSelf> -- E, Pi, and Tau, correctly rounded to each format's precision.
  • ISignedNumber<TSelf> -- NegativeOne.
  • INumber<TSelf> -- Max/Min/MaxNumber/MinNumber/Clamp/Sign/CopySign and friends, mirroring System.Half's semantics (IEEE 2019 minimum/maximum cohort/signed-zero/NaN handling).
  • IFloatingPoint<TSelf> -- Round (all overloads), the GetExponentByteCount/GetSignificandByteCount/TryWrite* bit APIs, and the remaining classification members.
  • The modulus operator (%, IModulusOperators<TSelf, TSelf, TSelf>).

The % operator follows the same truncated-remainder (fmod) semantics as float/double/Half -- x - Truncate(x / y) * y -- which is distinct from IEEE754Remainder (round-to-nearest quotient); the latter arrives with IFloatingPointIeee754.


Non-trivial members are ported from the Intel BID reference and validated bit-exact against its reference vectors (modulus and round), plus the existing Python-oracle-generated coverage. The multi-argument Round(value, digits, mode) overloads are the one bespoke piece -- Intel has no direct baseline for them, so they are built on the faithful single-argument rounding primitive.

IFloatingPointIeee754<TSelf>/IDecimalFloatingPointIeee754<TSelf> (and the transcendental sub-interfaces) are deferred to a follow-up that stacks on this.

Note

This PR description was drafted by GitHub Copilot.

tannergooding and others added 7 commits July 16, 2026 10:16
E, Pi, and Tau already exist as public constants; this just declares the
interface on Decimal32/64/128.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
NegativeOne already exists as a public constant; this just declares the
interface on Decimal32/64/128.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Implements the truncated remainder (x - Truncate(x / y) * y) matching the C#
floating-point % operator on double/float/Half, not the round-to-nearest
IEEE 754 remainder. The result carries the dividend's sign and is computed
exactly at the preferred exponent min(exp(x), exp(y)) by reducing the dividend
coefficient modulo the divisor coefficient with word-level integer arithmetic.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
All INumber members (Clamp/Max/Min/Sign/CopySign and friends) already exist as
public static members; the modulus operator and relational comparison operators
satisfy the remaining IModulusOperators/IComparisonOperators requirements, so
this declares the interface on Decimal32/64/128.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Collapses the IFloatingPointConstants/INumber/INumberBase/ISignedNumber
declarations into IFloatingPoint<TSelf> on Decimal32/64/128 and adds the
member set: Ceiling/Floor/Truncate/Round, ConvertToInteger(Native), and
the IFloatingPoint exponent/significand writers.

Exponent is exposed as int (its UnbiasedExponent type) so NaN/Inf exponent
fields don't overflow a narrower type; the significand is the full unpacked
coefficient. Round shares Number.RoundDecimalIeee754.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Covers Round (all midpoint modes, curated NaN/Inf/signed-zero/tie edge cases
plus oracle-derived random vectors), operator %, the Ceiling/Floor/Truncate/
Round convenience overloads, and the exponent/significand writers + ConvertToInteger.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…tel reference vectors

Wires bidNN_fmod and bidNN_round_integral_* from the Intel readtest.in vectors into
the existing DecimalIeee754IntelTestData harness. The round vectors surfaced two
canonicalization gaps in RoundDecimalIeee754 (non-canonical finite and infinity
operands were returned verbatim), now fixed in the implementation.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 16, 2026 17:21
@tannergooding tannergooding self-assigned this Jul 16, 2026
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
12 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/area-system-numerics
See info in area-owners.md if you want to be subscribed.

@tannergooding
tannergooding marked this pull request as ready for review July 16, 2026 17:25
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
12 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR expands the IEEE 754 decimal floating-point types (System.Numerics.Decimal32, Decimal64, Decimal128) with additional generic-math surface (notably IFloatingPoint-related members) and implements the % (truncating remainder / fmod) operator, with accompanying runtime and reference-vector-based tests.

Changes:

  • Add % operator support by introducing Number.RemainderDecimalIeee754 and wiring it into Decimal32/64/128.
  • Implement IFloatingPoint<TSelf> members (rounding helpers, ConvertToInteger*, and exponent/significand byte-writing APIs) for Decimal32/64/128 using new Number.RoundDecimalIeee754.
  • Extend tests and Intel reference-vector enumerators to cover modulus and integral rounding behavior, plus the new exponent/significand bit APIs.
Show a summary per file
File Description
src/libraries/System.Private.CoreLib/src/System/Number.DecimalIeee754.cs Adds shared helpers for truncated remainder (%) and rounding to fractional digits used by decimal IEEE types.
src/libraries/System.Private.CoreLib/src/System/Numerics/Decimal32.cs Adds % operator and IFloatingPoint<Decimal32> implementations (Round/Ceiling/Floor/Truncate + exponent/significand write APIs).
src/libraries/System.Private.CoreLib/src/System/Numerics/Decimal64.cs Adds % operator and IFloatingPoint<Decimal64> implementations (Round/Ceiling/Floor/Truncate + exponent/significand write APIs).
src/libraries/System.Private.CoreLib/src/System/Numerics/Decimal128.cs Adds % operator and IFloatingPoint<Decimal128> implementations (Round/Ceiling/Floor/Truncate + exponent/significand write APIs).
src/libraries/System.Runtime/ref/System.Runtime.cs Updates public ref surface for Decimal32/64/128 to include the new interfaces and members (including % and rounding APIs).
src/libraries/System.Runtime/tests/System.Runtime.Tests/System/DecimalIeee754IntelTestData.cs Adds Intel readtest.in operation families for fmod and integral-rounding vectors.
src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Decimal32Tests.cs Adds modulus, round-to-digits, convenience overload, and exponent/significand write API tests (plus Intel vector theories).
src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Decimal64Tests.cs Adds modulus, round-to-digits, convenience overload, and exponent/significand write API tests (plus Intel vector theories).
src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Decimal128Tests.cs Adds modulus, round-to-digits, convenience overload, and exponent/significand write API tests (plus Intel vector theories).

Copilot's findings

  • Files reviewed: 9/9 changed files
  • Comments generated: 2

Comment thread src/libraries/System.Private.CoreLib/src/System/Number.DecimalIeee754.cs Outdated
Comment thread src/libraries/System.Runtime/ref/System.Runtime.cs
The reduction loop scaled the running remainder one decimal digit at a time, so a large exponent gap spun far more iterations than necessary and kept going after the remainder reached zero. Fold as many trailing zeros per step as the running product can hold without overflowing the integer width (up to the largest cached power of ten) and stop once the remainder is zero. A small divisor now reaches the full cached power; output is bit-exact-unchanged against the Intel reference vectors.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 16, 2026 18:09

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

Comments suppressed due to low confidence (1)

src/libraries/System.Runtime/ref/System.Runtime.cs:11436

  • This PR adds new public API surface (e.g., Decimal32/64/128 now implement additional generic-math interfaces and expose new members like %/Round/Ceiling/Floor/Truncate/bit APIs). Issue #81376 is labeled api-approved, but I couldn’t locate the “approved API shape” comment (code-fenced C# snippet) required by the API-approval procedure. Please link the specific approval comment (or add it) so reviewers can verify the ref changes match the approved shape.
  • Files reviewed: 9/9 changed files
  • Comments generated: 4

Comment thread src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Decimal32Tests.cs Outdated
Comment thread src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Decimal64Tests.cs Outdated
Comment thread src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Decimal128Tests.cs Outdated
Comment thread src/libraries/System.Private.CoreLib/src/System/Number.DecimalIeee754.cs Outdated
…est files

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Comment thread src/libraries/System.Private.CoreLib/src/System/Number.DecimalIeee754.cs Outdated
tannergooding and others added 3 commits July 16, 2026 11:52
…4 decimal types

Covers GetExponentShortestBitLength (both exponent-sign branches),
GetSignificandBitLength, and the big-endian significand and exponent writers.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Ceiling/Floor/Round/Truncate propagated a NaN operand's bits unchanged,
so a signaling or out-of-range-payload NaN escaped as a non-canonical
result. Route it through PropagateNaN, matching the binary operators.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Comment thread src/libraries/System.Private.CoreLib/src/System/Number.DecimalIeee754.cs Outdated
@PranavSenthilnathan

Copy link
Copy Markdown
Member

LGTM after null propagation is fixed

Replace the manual divide and multiply-subtract with TValue.DivRem,
matching the remainder computation used elsewhere in the file.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…amily

IEEE 754-2019 5.1 requires general-computational operations to produce
canonical results, so a returned NaN operand must be re-canonicalized.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 16, 2026 20:38

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 9/9 changed files
  • Comments generated: 1

Comment thread src/libraries/System.Runtime/ref/System.Runtime.cs
@tannergooding
tannergooding enabled auto-merge (squash) July 16, 2026 20:55
@tannergooding

Copy link
Copy Markdown
Member Author

@PranavSenthilnathan should all be handled. Still needs explicit sign-off

@tannergooding

Copy link
Copy Markdown
Member Author

/ba-g the known net481 build break and an unrelated timeout

@tannergooding
tannergooding merged commit 874b9e9 into dotnet:main Jul 17, 2026
141 of 145 checks passed
@tannergooding
tannergooding deleted the tannergooding-decimal-ieee754-ifloatingpoint branch July 17, 2026 03:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants