Skip to content

Commit aaad4df

Browse files
committed
Optimize rpow(x,n,base) for the case x != 0 && n == 0 (291 gas vs 383 gas)
1 parent 2318555 commit aaad4df

File tree

2 files changed

+40
-34
lines changed

2 files changed

+40
-34
lines changed

src/jug.sol

+22-19
Original file line numberDiff line numberDiff line change
@@ -38,27 +38,30 @@ contract Jug is DSNote {
3838

3939
// --- Math ---
4040
function rpow(uint x, uint n, uint b) internal pure returns (uint z) {
41-
assembly {
42-
switch x case 0 {switch n case 0 {z := b} default {z := 0}}
43-
default {
44-
switch mod(n, 2) case 0 { z := b } default { z := x }
45-
let half := div(b, 2) // for rounding.
46-
for { n := div(n, 2) } n { n := div(n,2) } {
47-
let xx := mul(x, x)
48-
if iszero(eq(div(xx, x), x)) { revert(0,0) }
49-
let xxRound := add(xx, half)
50-
if lt(xxRound, xx) { revert(0,0) }
51-
x := div(xxRound, b)
52-
if mod(n,2) {
53-
let zx := mul(z, x)
54-
if and(iszero(iszero(x)), iszero(eq(div(zx, x), z))) { revert(0,0) }
55-
let zxRound := add(zx, half)
56-
if lt(zxRound, zx) { revert(0,0) }
57-
z := div(zxRound, b)
41+
assembly {
42+
switch n case 0 { z := b }
43+
default {
44+
switch x case 0 { z := 0 }
45+
default {
46+
switch mod(n, 2) case 0 { z := b } default { z := x }
47+
let half := div(b, 2) // for rounding.
48+
for { n := div(n, 2) } n { n := div(n,2) } {
49+
let xx := mul(x, x)
50+
if iszero(eq(div(xx, x), x)) { revert(0,0) }
51+
let xxRound := add(xx, half)
52+
if lt(xxRound, xx) { revert(0,0) }
53+
x := div(xxRound, b)
54+
if mod(n,2) {
55+
let zx := mul(z, x)
56+
if and(iszero(iszero(x)), iszero(eq(div(zx, x), z))) { revert(0,0) }
57+
let zxRound := add(zx, half)
58+
if lt(zxRound, zx) { revert(0,0) }
59+
z := div(zxRound, b)
60+
}
61+
}
62+
}
5863
}
59-
}
6064
}
61-
}
6265
}
6366
uint256 constant ONE = 10 ** 27;
6467
function add(uint x, uint y) internal pure returns (uint z) {

src/pot.sol

+18-15
Original file line numberDiff line numberDiff line change
@@ -77,22 +77,25 @@ contract Pot is DSNote {
7777
uint256 constant ONE = 10 ** 27;
7878
function rpow(uint x, uint n, uint base) internal pure returns (uint z) {
7979
assembly {
80-
switch x case 0 {switch n case 0 {z := base} default {z := 0}}
80+
switch n case 0 { z := base }
8181
default {
82-
switch mod(n, 2) case 0 { z := base } default { z := x }
83-
let half := div(base, 2) // for rounding.
84-
for { n := div(n, 2) } n { n := div(n,2) } {
85-
let xx := mul(x, x)
86-
if iszero(eq(div(xx, x), x)) { revert(0,0) }
87-
let xxRound := add(xx, half)
88-
if lt(xxRound, xx) { revert(0,0) }
89-
x := div(xxRound, base)
90-
if mod(n,2) {
91-
let zx := mul(z, x)
92-
if and(iszero(iszero(x)), iszero(eq(div(zx, x), z))) { revert(0,0) }
93-
let zxRound := add(zx, half)
94-
if lt(zxRound, zx) { revert(0,0) }
95-
z := div(zxRound, base)
82+
switch x case 0 { z := 0 }
83+
default {
84+
switch mod(n, 2) case 0 { z := base } default { z := x }
85+
let half := div(base, 2) // for rounding.
86+
for { n := div(n, 2) } n { n := div(n,2) } {
87+
let xx := mul(x, x)
88+
if iszero(eq(div(xx, x), x)) { revert(0,0) }
89+
let xxRound := add(xx, half)
90+
if lt(xxRound, xx) { revert(0,0) }
91+
x := div(xxRound, base)
92+
if mod(n,2) {
93+
let zx := mul(z, x)
94+
if and(iszero(iszero(x)), iszero(eq(div(zx, x), z))) { revert(0,0) }
95+
let zxRound := add(zx, half)
96+
if lt(zxRound, zx) { revert(0,0) }
97+
z := div(zxRound, base)
98+
}
9699
}
97100
}
98101
}

0 commit comments

Comments
 (0)