我有这个Yul功能,为了学习的目的,我正试图逆转到稳固。我对实体函数的结果与原来的函数不同,我不知道我缺少了什么。
最初的Yul函数:
function fpow(
uint256 x,
uint256 n,
uint256 baseUnit
) internal pure returns (uint256 z) {
assembly {
switch x
case 0 {
switch n
case 0 {
// 0 ** 0 = 1
z := baseUnit
}
default {
// 0 ** n = 0
z := 0
}
}
default {
switch mod(n, 2)
case 0 {
// If n is even, store baseUnit in z for now.
z := baseUnit
}
default {
// If n is odd, store x in z for now.
z := x
}
// Shifting right by 1 is like dividing by 2.
let half := shr(1, baseUnit)
for {
// Shift n right by 1 before looping to halve it.
n := shr(1, n)
} n {
// Shift n right by 1 each iteration to halve it.
n := shr(1, n)
} {
// Revert immediately if x ** 2 would overflow.
// Equivalent to iszero(eq(div(xx, x), x)) here.
if shr(128, x) {
revert(0, 0)
}
// Store x squared.
let xx := mul(x, x)
// Round to the nearest number.
let xxRound := add(xx, half)
// Revert if xx + half overflowed.
if lt(xxRound, xx) {
revert(0, 0)
}
// Set x to scaled xxRound.
x := div(xxRound, baseUnit)
// If n is even:
if mod(n, 2) {
// Compute z * x.
let zx := mul(z, x)
// If z * x overflowed:
if iszero(eq(div(zx, x), z)) {
// Revert if x is non-zero.
if iszero(iszero(x)) {
revert(0, 0)
}
}
// Round to the nearest number.
let zxRound := add(zx, half)
// Revert if zx + half overflowed.
if lt(zxRound, zx) {
revert(0, 0)
}
// Return properly scaled zxRound.
z := div(zxRound, baseUnit)
}
}
}
}
}我的稳固功能:
function fpowSol(
uint256 x,
uint256 n,
uint256 baseUnit
) public pure returns (uint256 z) {
if(x == 0) {
if(n == 0) {
return (baseUnit);
} else {
return (0);
}
}
if(n % 2 == 0) {
z = baseUnit;
} else {
z = x;
}
uint256 half = baseUnit >> 1;
for(n >>= 1; n > 0; n >>= 1) {
uint256 xx = x * x;
if(xx / x != x) { require(false, "xx overvlowed"); }
uint256 xxRound = xx + half;
if(xxRound < xx) { require(false, "xxRound overflowed"); }
x = xxRound / baseUnit;
if(n % 2 == 0) {
uint256 zx = z * x;
require(zx / x == z, "zx overflowed");
uint256 zxRound = zx + half;
if(zxRound < zx) { require(false, "zxRound overflowed"); }
z = zxRound / baseUnit;
}
}
return (z);
}你将如何在稳固中重写这个Yul函数?
或
我从玉到实的翻译有什么不对?
发布于 2022-10-21 19:10:06
我之所以不能得到同样的结果,是因为上一次if声明对我有误导作用
// If n is even:
if mod(n, 2) { ... }实际上,这不是if(n%0 != 0),实际上是“如果n不是偶数”。
我对yul是新手,所以如果我错了,请纠正我,但是我已经能够得到一致的结果到主函数和我的计算链上。我想这个答案是正确的。
实函数是
function fpowSol(
uint256 x,
uint256 n,
uint256 baseUnit
) public pure returns (uint256 z) {
if(x == 0) {
if(n == 0) {
return (baseUnit);
} else {
return (0);
}
}
if(n % 2 == 0) {
z = baseUnit;
} else {
z = x;
}
uint256 half = baseUnit >> 1;
for(n >>= 1; n > 0; n >>= 1) {
uint256 xx = x * x;
if(xx / x != x) { require(false, "xx overvlowed"); }
uint256 xxRound = xx + half;
if(xxRound < xx) { require(false, "xxRound overflowed"); }
x = xxRound / baseUnit;
if(n % 2 != 0) { // THIS HAS CHANGED
uint256 zx = z * x;
require(zx / x == z, "zx overflowed");
uint256 zxRound = zx + half;
if(zxRound < zx) { require(false, "zxRound overflowed"); }
z = zxRound / baseUnit;
}
}
return (z);
}https://ethereum.stackexchange.com/questions/137922
复制相似问题