Skip to content

feat!: Use num-bigint for large numbers - #500

Merged
anakrish merged 1 commit into
microsoft:mainfrom
anakrish:number-semantics
Dec 1, 2025
Merged

feat!: Use num-bigint for large numbers#500
anakrish merged 1 commit into
microsoft:mainfrom
anakrish:number-semantics

Conversation

@anakrish

@anakrish anakrish commented Nov 10, 2025

Copy link
Copy Markdown
Collaborator

feat!: Use num-bigint for large numbers

  • Supply chain: Use the popular num-bigint crate for handling large integers
  • Optimization: Handle f64, i64, u64 directly. These will be the most common instances of a number.

OPA number semantics isn't clear.
open-policy-agent/opa#6281

As part of this change, we update the following failing tests:

  • A local test that relies on what 15.3/3 evaluates to.
    With our current change, we round in a different direction than what OPA does, but consistent
    with Rust. We produce 5.1000000000000005 where as the OPA test expects 5.1.
    There is no clear definition in Rego of what the right answer is. Moreover, policies should not
    rely on exact floating point value comparison. Therefore this deviations is justified.
    The test is patched to pass.
  • Another local vm test that exercised 1.1 + 2.2
  • Another local vm test that exercises 5.5 - 2.2
  • An OPA test that expects that a large integer number say 10e308 is printed in exponent notation.
    num-bigint does not print using scientific notation and instead prints all the digits.
    The benefit of preserving this compatibility is not clear. We skip this test.
  • Doc tests that exercised handling floating point numbers with more than 15 (what f64 supports)
    digits of precision. There is no usecase for this scenario. The tests are updated to reflect
    the behavior.

closes #165
Signed-off-by: Anand Krishnamoorthi anakrish@microsoft.com

Comment thread src/builtins/units.rs Fixed
Comment thread src/number.rs Fixed
Comment thread src/number.rs Fixed
@anakrish
anakrish force-pushed the number-semantics branch 7 times, most recently from 46674fb to 3f9ff7a Compare November 24, 2025 22:38
- Supply chain: Use the popular num-bigint crate for handling large integers
- Optimization: Handle f64, i64, u64 directly. These will be the most common instances of a number.

OPA number semantics isn't clear.
open-policy-agent/opa#6281

As part of this change, we update the following failing tests:
- A local test that relies on what 15.3/3 evaluates to.
 With our current change, we round in a different direction than what OPA does, but consistent
 with Rust. We produce 5.1000000000000005 where as the OPA test expects 5.1.
 There is no clear definition in Rego of what the right answer is. Moreover, policies should not
 rely on exact floating point value comparison. Therefore this deviations is justified.
 The test is patched to pass.
- Another local vm test that exercised 1.1 + 2.2
- Another local vm test that exercises 5.5 - 2.2
- An OPA test that expects that a large integer number say 10e308 is printed in exponent notation.
 num-bigint does not print using scientific notation and instead prints all the digits.
 The benefit of preserving this compatibility is not clear. We skip this test.
- Doc tests that exercised handling floating point numbers with more than 15 (what f64 supports)
  digits of precision. There is no usecase for this scenario. The tests are updated to reflect
  the behavior.

Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
@anakrish anakrish changed the title feat!: Optimized number implementation feat!: Use num-bigint for large numbers Nov 24, 2025
@anakrish
anakrish marked this pull request as ready for review November 24, 2025 22:56
Comment thread src/number.rs
return Number::UInt(u);
} else if let Some(i) = value.to_i64() {
return Number::Int(i);
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

nit: not sure if it matters, but should we try converting to i64 first and then u64? otherwise won't the i64 clause never be hit?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Good observation. Let me reorder.

Comment thread src/number.rs
return Ok(Number::Float(self.to_f64_lossy() / rhs.to_f64_lossy()));
}

match (&self, rhs) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

match (&self, rhs)

seeing a lot of new code here - are there nuances to all of these combinations that we should add tests for? or is it all mostly boilerplate and a result of the different combinations of number types we're supporting?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

There are some nuances as well as boilerplate. Let me add the tests in the next PR.

@anakrish

anakrish commented Dec 1, 2025

Copy link
Copy Markdown
Collaborator Author

@dekomissMSFT Thanks for the approval. I will address both your comments in a follow up PR, just to keep the momemtum going.

@anakrish
anakrish merged commit a8a3a98 into microsoft:main Dec 1, 2025
41 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Optimize Number representation

3 participants