2

I have some code where I was experimenting with the Math library, namely the logarithm functions, and I figured these would be the perfect functions to optimize with assembly, after slightly improving them via implicit return. However I ran into some problems with their gas cost actually being more than the non-assembly versions, and there doesn't seem to be a way to optimize things any further than the first function. Perhaps it is due to me not seeing a gte assembly shortcut?

In place of gte I used gt of the original value minus 1.

contract Log10Variants {

    function _log10(uint value) public pure returns (uint result) {  unchecked  {
        if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; }
        if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; }
        if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; }
        if (value >= 10 ** 8)  { value /= 10 ** 8;  result += 8;  }
        if (value >= 10 ** 4)  { value /= 10 ** 4;  result += 4;  }
        if (value >= 10 ** 2)  { value /= 10 ** 2;  result += 2;  }
        if (value >= 10 ** 1)  { result += 1; }
    }}

    function _log10_v2(uint value) public pure returns (uint result) {  unchecked  {
        for (uint i = 64; i > 0; i /= 2) {
            if (value >= 10 ** i) { value /= 10 ** i; result += i; }
        }
    }}

    function _log10assembly(uint value) public pure returns (uint result) {  unchecked  {
        assembly {
            for { let i := 64 } gt(i, 0) { i := div(i, 2) } {
                if gt(value, sub(exp(10, i), 1)) { 
                    value := div(value, exp(10, i)) result := add(result, i)
                }
            }
        }
    }}

    function _log10assembly2(uint v) public pure returns (uint r) {  unchecked  {  assembly  {
        if gt(v, sub(exp(10,64), 1)) { v := div(v, exp(10, 64)) r := add(r, 64) }
        if gt(v, sub(exp(10,32), 1)) { v := div(v, exp(10, 32)) r := add(r, 32) }
        if gt(v, sub(exp(10,16), 1)) { v := div(v, exp(10, 16)) r := add(r, 16) }
        if gt(v, sub(exp(10,8), 1))  { v := div(v, exp(10, 8))  r := add(r, 8) }
        if gt(v, sub(exp(10,4), 1))  { v := div(v, exp(10, 4))  r := add(r, 4) }
        if gt(v, sub(exp(10,2), 1))  { v := div(v, exp(10, 2))  r := add(r, 2) }
        if gt(v, sub(exp(10,1), 1))  { r := add(r, 1) }
    }}}

}

1 Answer 1

3

There is no such opcode and no assembly function. You can use iszero(lt()) for this

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.