Translating Yul to Solidity

I have this Yul function that I am trying to reverse to Solidity for learning purposes. My results with the solidity function are different than the original functions and I don't see what I am missing.

Initial Yul function:

``````    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.

// 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.

// Revert if zx + half overflowed.
if lt(zxRound, zx) {
revert(0, 0)
}

// Return properly scaled zxRound.
z := div(zxRound, baseUnit)
}
}
}
}
}
``````

My Solidity function:

``````    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);
}
``````

How would you rewrite this Yul function in solidity

or

Where am I wrong in my translation from Yul to solidity ?

The reason why I wasn't able to get the same result is because of the last `if` statement which was misleading to me

``````                    // If n is even:
if mod(n, 2) { ... }
``````

Actually this is not `if(n%0 != 0)` and is in reality "if n is not even".

I'm new to yul so correct me if I'm wrong but I have been able to get consistent results to the main function and also to my calculation off chain. I assume this answer is correct.

Real function is

``````    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);
}
``````