Conversation
Codecov Report
@@ Coverage Diff @@
## master #110 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 4 4
Lines 1388 1396 +8
=========================================
+ Hits 1388 1396 +8 |
|
I pushed a fuzzer to this PR, looks good so far. Also, I noticed that the fuzzer was broken, which is also fixed. |
|
I've optimized a bit by zero-check on the p[4:] directly instead copy to new Int. Before After |
|
cc @chfast would you mind taking a look? |
|
@holiman Is everything okay? How long will it take? |
|
@Planxnx just came back from a vacation, we'll get this merged soon |
uint256.go
Outdated
| p := umul(x, y) | ||
|
|
||
| // If the multiplication is within 256 bits use Div(). | ||
| if (p[4] | p[5] | p[6] | p[7]) == 0 { |
There was a problem hiding this comment.
You don't have to do it. The udivrem() will skip leading zero words itself and Div() is using udivrem() internally. So this optimization does not improve it algorithmically. My preference is too leave such optimization to at least another PR where it can be shown it improves any particular use case.
There was a problem hiding this comment.
This requires a fix to udivrem() to handle case when uLen < dLen (quick return).
Benchmarks (current PR vs simplified version):
name old time/op new time/op delta
MulDivOverflow/small/uint256-8 2.23ns ± 0% 2.24ns ± 1% +0.66% (p=0.000 n=9+10)
MulDivOverflow/div64/uint256-8 2.25ns ± 0% 2.25ns ± 0% -0.05% (p=0.008 n=8+8)
MulDivOverflow/div128/uint256-8 2.37ns ± 0% 2.36ns ± 0% -0.51% (p=0.000 n=9+9)
MulDivOverflow/div192/uint256-8 2.41ns ± 0% 2.39ns ± 0% -0.64% (p=0.000 n=8+9)
MulDivOverflow/div256/uint256-8 2.56ns ± 0% 2.54ns ± 0% -0.66% (p=0.000 n=8+9)
MulDivOverflow/small/big-8 18.4ns ± 0% 19.0ns ± 0% +3.16% (p=0.000 n=9+10)
MulDivOverflow/div64/big-8 18.4ns ± 0% 19.0ns ± 1% +3.22% (p=0.000 n=9+10)
MulDivOverflow/div128/big-8 22.2ns ± 1% 22.9ns ± 1% +3.10% (p=0.000 n=10+10)
MulDivOverflow/div192/big-8 23.2ns ± 1% 23.8ns ± 1% +2.78% (p=0.000 n=9+9)
MulDivOverflow/div256/big-8 26.7ns ± 1% 27.4ns ± 1% +2.69% (p=0.000 n=10+10)
There was a problem hiding this comment.
I've removed Div() and added a handle case where the denominator is greater than the numerator instead.
There was a problem hiding this comment.
My idea is to handle this case inside udivrem(). My attempt is in #111 but we need to figure out why one of the tests fails (help welcome).
There was a problem hiding this comment.
The #111 looks to be ready. Can you try to rebase on top of it and completely remove this block?
|
@chfast I've updated the code. Can you do another review? |
|
The last change made the code coverage from the tests drop a bit - see https://app.codecov.io/gh/holiman/uint256/compare/110/diff . Not sure if I think the |
chfast
left a comment
There was a problem hiding this comment.
Looks good to me with some questions around testing.
| } | ||
| return -1 | ||
| switch { | ||
| case len(data) < 64: |
There was a problem hiding this comment.
I figured it would be better to use the input we have, rather than be too picky about the input size...?
There was a problem hiding this comment.
I'm not sure this is good idea because you have unused bytes in the end of the input. They will give you exactly the same coverage path and also for all inputs giving the same coverage fuzzers prefer the shortest one and should reduce corpus entries finally. So the end result should be the same but this may be just longer route to get there.
I will experiment with two versions to see which one is faster.
| return b1.Div(b1, b4) | ||
| } | ||
|
|
||
| func intMulDiv(f1, f2, f3, f4 *Int) *Int { |
There was a problem hiding this comment.
This may be upgraded to public function in future so maybe change it to func (z *Int) mulDiv(x, y, d *Int) *Int?
There was a problem hiding this comment.
Let's do that later in that case
fuzz.go
Outdated
| return fuzzTernaryOp(data) // needs 96 byte | ||
| } | ||
| // Too large input | ||
| return 0 |
There was a problem hiding this comment.
This should still return -1 I believe.

(x * y) / denominatoris the most common case that cannot be calculated with full precision by normal methodsz.Mul(x, y).Div(z, denominator)ex.
(max_uint256 * 2)/10an overflow occurs when you try to calculated by normal methods, but the result is smaller than
max_uint256.MulDivOverflow()is 512-bit multiplication and 512-bit by 256-bit division.returns The 256-bit result and overflow occurred.
inspired and realworld use-case from UniswapV3
https://github.com/Uniswap/v3-core/blob/main/contracts/libraries/FullMath.sol