Skip to content

Feat/mul div - #54

Open
aritkulova wants to merge 12 commits into
devfrom
feat/mul-div
Open

Feat/mul div#54
aritkulova wants to merge 12 commits into
devfrom
feat/mul-div

Conversation

@aritkulova

@aritkulova aritkulova commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator
  • This PR suggests a bug fix and I've added the necessary tests.
  • This PR introduces a new feature and I've discussed the update in an Issue or with the team.
  • This PR is just a minor change like a typo fix.

@aritkulova aritkulova self-assigned this Sep 4, 2026
@aritkulova
aritkulova requested a review from Hrom131 September 4, 2026 07:53
Comment thread simf/lib/u128/math.simf Outdated
Comment thread simf/lib/u128/math.simf
Comment thread simf/lib/u128/mul_div.simf
/// Panics if the result overflows a u256
pub fn mul_div_256(a: u256, b: u256, denominator: u256) -> u256 {
match is_zero_256(denominator) {
true => 0,

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.

Shouldn't we panic if we divide by 0?

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.

I agree that panicking on division by zero would be less error-prone, but the jet's division functions don't panic on division by zero, so here it feels more like the default behavior

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.

We had a discussion on a call with @roconnor-blockstream about this behavior, which other people found unusual or surprising. I think it has to do with some functional programming conventions related to wanting functions to be total when possible. I don't know that he necessarily felt that all library functions written using the jet needed to replicate the behavior, but I don't remember his exact position about this.

I think @apoelstra is also familiar with this discussion and might be able to weigh in.

moved arithmetic section for u128 and u256 to be consistent with other sections

@LesterEvSe LesterEvSe left a comment

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.

Also let's add more tests to cover new u512 division functionality.

  1. Force entry into algorithm_d_512_256:
a = generate_u256(2^128, U256::MAX)
b = generate_u256(2^128, U256::MAX)

result_high = high 256 bits of a.full_mul(b)
c = generate_u256(max(2^128, result_high + 1), U256::MAX)

Guarantees result_high != 0 and denom_high != 0.

  1. Add two normalize_to_threshold_512_127 tests.
    2.1. norm == 1. Forces the divisor's top bit to already be set:
a = generate_u256(2^128, U256::MAX)
b = generate_u256(2^128, U256::MAX)

result_high = high 256 bits of a.full_mul(b)
c = generate_u256(max(2^255, result_high + 1), U256::MAX)

2.2. norm > 1. Forces the divisor's top bit to be clear:

a = generate_u256(2^128, U256::MAX)
b = generate_u256(2^128, 2^192)

result_high = high 256 bits of a.full_mul(b)   // < 2^192, well under the 2^255 ceiling
c = generate_u256(max(2^128, result_high + 1), 2^255 - 1)
  1. Same a, b as (1), but c = result_high + 1.

  2. Exact division with remainder == 0. Set a = c for some c in range [2^128, U256::MAX], pick b as a*b >= 2^256.

  3. Minimal denom_high:

a = generate_u256(2^128, 2^129)
b = generate_u256(2^128, 2^129)

result_high = high 256 bits of a.full_mul(b)   // in {1, 2, 3}
c = generate_u256(max(2^128, result_high + 1), 2^129 - 1)

Comment thread tests/u32_mul_div_test.rs Outdated
Comment thread tests/u64_mul_div_test.rs Outdated
Comment thread tests/u128_mul_div_test.rs Outdated
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.

4 participants