-
Notifications
You must be signed in to change notification settings - Fork 11.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add log2, log10 and log256 functions #3670
Conversation
contracts/utils/math/Math.sol
Outdated
*/ | ||
function log10(uint256 value) internal pure returns (uint256) { | ||
uint256 result = 0; | ||
if (value >= 10**64) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Amxx what about this one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tested both, and this change makes it more expensive :/
it looks like the compiler does the -1
operation at runtime
contracts/utils/math/Math.sol
Outdated
if (x >> 2 > 0) { | ||
result <<= 1; | ||
} | ||
uint256 result = 1 << (log2(a) / 2); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can replace 1 << (log2(a) / 2)
by 1 << (log2(a) >> 2)
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is interresting, but the correct formula would be 1 << (log2(a) >> 1)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ohh, sorry. It >>1.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Before changing that I would check if Solidity does not make that optimization on its own.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tested both. using >> 1
saves 54 gas compared to / 2
(0.8.16 with optimizations)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Amxx Because It happen due to solidity checking underflow that. But When we are use shift operator it bypass that check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overflow check make sens for +, - and * ... not for /
The only reasonable check is that we don't divide by 0 ... but there is no reason to check that here.
…com:Amxx/openzeppelin-contracts into feature/math/logX
Edit: Just realized that |
Yes, hex chars go by pairs. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! Looking forward to fuzzing too.
Logs are already used in different places:
Math.sqrt
, we do a log in base 4 (log2 divided by 2)String.toString(uint256)
, we do a log base 10String.toHexString(uint256)
, we do a log base 256In #3573, it was mentioned that these operation should all be in math, rather then scattered all over the code base. This rationalizes the code, and allow reuse by devs.
PR Checklist