Skip to content
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

feat: add isqrt built-in #3069

Merged
merged 11 commits into from
Aug 25, 2022
Merged

feat: add isqrt built-in #3069

merged 11 commits into from
Aug 25, 2022

Conversation

bout3fiddy
Copy link
Contributor

@bout3fiddy bout3fiddy commented Aug 19, 2022

What I did

Inspired from [t11s's solmate fixed point sqrt utility algo].(https://github.com/transmissions11/solmate/blob/9cf1428245074e39090dceacb0c28b1f684f584c/src/utils/FixedPointMathLib.sol#L166)

Michael from Curve made a version of this in vyper. I added it as a builtin and changed a few tests.

How I did it

Take code from Michael, amend a few things, write tests

How to verify it

pytest tests/parser/types/numbers/test_sqrt_solmate.py

Commit message

Adds isqrt builtin. For a better explanation of the algorithm, refer to: https://github.com/Gaussian-Process/solmate/blob/837de01395312eb89e607fdc64fb7bb9c03207c3/src/utils/FixedPointMathLib.sol

Description for the changelog

Cute Animal Picture

rottweiler puppy

Put a link to a cute animal picture inside the parenthesis-->

Comment on lines 2691 to 2692
"sqrt": Sqrt(),
"sqrt_solmate": SqrtSolmate(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not update the original Sqrt instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was the original idea indeed, but did not want to introduce that breaking change without prompt from a core contributor.

I'll make the changes to the original sqrt then.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i don't think we should get rid of the original sqrt. sqrt on decimals is pretty useful, especially once we open up the decimals type to be generic.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, but sounds like this should basically expand the types that sqrt works with, so if it's decimals it uses the previous and if it's integers it uses this one

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think if it's possible, use the same algorithm for both types. there will be fewer gas surprises that way

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@charles-cooper It doesn't look possible since exponentiation is not allowed for decimal type. I do like the idea @fubuloubu mentioned, where sqrt(x: decimal) would just yield what it does right now and sqrt(x: uint256) would use the optimised version.

Regarding gas surprises: is that really an issue? I don't expect users to use the decimal type at all.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

discussed offline -- the gas difference is ok. @bout3fiddy added a note that we will try to reify the code paths later

@codecov-commenter
Copy link

codecov-commenter commented Aug 23, 2022

Codecov Report

Merging #3069 (9e26d40) into master (a66db89) will increase coverage by 0.02%.
The diff coverage is 100.00%.

@@            Coverage Diff             @@
##           master    #3069      +/-   ##
==========================================
+ Coverage   88.32%   88.34%   +0.02%     
==========================================
  Files          97       97              
  Lines       10980    10999      +19     
  Branches     2597     2599       +2     
==========================================
+ Hits         9698     9717      +19     
  Misses        832      832              
  Partials      450      450              
Impacted Files Coverage Δ
vyper/builtin_functions/functions.py 90.48% <100.00%> (+0.15%) ⬆️
vyper/semantics/types/value/numeric.py 80.45% <0.00%> (-4.60%) ⬇️
vyper/codegen/memory_allocator.py 66.12% <0.00%> (+6.45%) ⬆️

📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more

@bout3fiddy bout3fiddy changed the title wip: add sqrt_solmate as a new builtin feat: add isqrt as a new built-in math function Aug 23, 2022
@charles-cooper
Copy link
Member

looks like isqrt is not available in python 3.7. we probably need to backport, @bout3fiddy see

vyper/vyper/utils.py

Lines 40 to 44 in e7733e1

try:
# available py3.8+
from functools import cached_property
except ImportError:
from cached_property import cached_property # type: ignore
for the pattern

@charles-cooper charles-cooper changed the title feat: add isqrt as a new built-in math function feat: add isqrt built-in Aug 23, 2022
Copy link
Member

@charles-cooper charles-cooper left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

very nice pull request. i think the only thing i would change is in the test file, changing from math import isqrt to import math. that way the usages must be qualified as math.isqrt which helps the reader distinguish from vyper isqrt.

@@ -664,6 +664,25 @@ Math
>>> ExampleContract.foo(9.0)
3.0

.. py:function:: isqrt(x: uint256) -> uint256

Return the square root of the provided integer number, using Babylonian square root algorithm.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Return the square root of the provided integer number, using Babylonian square root algorithm.
Return the (integer) square root of the provided integer number, using the Babylonian square root algorithm. The rounding mode is to round down to the nearest integer. For instance, ``isqrt(101) == 10``.

docs/built-in-functions.rst Outdated Show resolved Hide resolved
…t: add clarification to rounding step in builtin code
@charles-cooper
Copy link
Member

looks like isqrt is not available in python 3.7. we probably need to backport

no more need to backport, 3.7 tests were dropped in #3071

@charles-cooper charles-cooper enabled auto-merge (squash) August 24, 2022 23:43
@charles-cooper charles-cooper merged commit 25c7650 into vyperlang:master Aug 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants