Skip to content

Implement Number Protocol #3507

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

Merged
merged 7 commits into from
May 29, 2022
Merged

Conversation

qingshi163
Copy link
Contributor

@qingshi163 qingshi163 commented Dec 20, 2021

number protocol of #3244

@youknowone
Copy link
Member

@qingshi163 what have to be done to finish this PR?

@youknowone
Copy link
Member

awesome!

Copy link
Member

@youknowone youknowone left a comment

Choose a reason for hiding this comment

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

I have questions about cow and OnceCell part, but it looks working!
This is the way to go and we can fix other stuff later.

Do you have remaining plans to do on this PR?

@@ -0,0 +1,242 @@
use std::borrow::Cow;

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

@@ -263,7 +265,10 @@ impl Constructor for PyInt {
val
};

try_int(&val, vm)
// try_int(&val, vm)
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
// try_int(&val, vm)

pub trait AsNumber: PyPayload {
#[inline]
#[pyslot]
fn slot_as_number(zelf: &PyObject, vm: &VirtualMachine) -> Cow<'static, PyNumberMethods> {
Copy link
Member

Choose a reason for hiding this comment

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

Does this slot need to return Cow? Which part prevent this to be &'static PyNumberMethods?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think for heap object we need to use Cow::Owned witch implemented in as_number_wrapper

Copy link
Member

Choose a reason for hiding this comment

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

They are not decided by object, but decided by type. Then I think the type can hold a cloned PyNumberMethods with edited values. instead of Cow for every object when as_number is called.

Copy link
Member

Choose a reason for hiding this comment

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

I found AsMapping has the same mechanism. Then it is ok for now.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, it should be stored in the type struct, but we can fix it later

@qingshi163
Copy link
Contributor Author

There is quite a lot of things not done yet, i think all the mathematic operations should be implemented via number protocol

@youknowone
Copy link
Member

How about finishing this PR as current state as core implementation of AsNumber trait, and working on other types in following other PRs?
Keeping a huge PR will be a burden to maintain (to rebase everything after other merge)

@youknowone
Copy link
Member

@qingshi163 are you going to make this ready for review? or do you want to do more work on it?

@qingshi163
Copy link
Contributor Author

I am still busy with it

@qingshi163 qingshi163 marked this pull request as ready for review May 29, 2022 06:53
@qingshi163 qingshi163 requested a review from youknowone May 29, 2022 06:53
@youknowone youknowone changed the title [WIP] Implement Number Protocol Implement Number Protocol May 29, 2022
Copy link
Member

@youknowone youknowone left a comment

Choose a reason for hiding this comment

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

I think #3750 changes also be able to be adapt here.
They can be done later, but I attached a commit simplifying AsNumber interfaces.

if let Some(f) = val.try_to_f64(vm)? {
f
if cls.is(vm.ctx.types.float_type) && val.class().is(PyFloat::class(vm)) {
unsafe { val.downcast_unchecked::<PyFloat>().value }
Copy link
Member

Choose a reason for hiding this comment

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

here is a regression. val object will not be reused even for same type.

negative: Some(|number, vm| {
Self::number_downcast(number)
.value
.clone()
Copy link
Member

Choose a reason for hiding this comment

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

https://docs.rs/num/latest/num/struct.BigInt.html#impl-Neg-1

Neg is also implemented for &BigInt. This clone is redundant.

absolute: Some(|number, vm| Self::number_downcast(number).value.abs().to_pyresult(vm)),
boolean: Some(|number, _vm| Ok(Self::number_downcast(number).value.is_zero())),
invert: Some(|number, vm| {
let value = Self::number_downcast(number).value.clone();
Copy link
Member

Choose a reason for hiding this comment

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

Comment on lines +14 to +13
/* Number implementations must check *both*
arguments for proper type and implement the necessary conversions
in the slot functions themselves. */
Copy link
Member

Choose a reason for hiding this comment

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

Does this mean we need to check the first argument(&PyNumber) is a correct PyNumber object?
In this case, I feel like the type will fit better in &PyObject rather than &PyNumber

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The comment is from cpython but as the source shows that cpython only does the check for binary operations which could be called invertly but assume the type is correct for other functions

@youknowone
Copy link
Member

+-----------+----------------------------------+-----------------------------------+----------------------------------------+
| Benchmark | benches/out/cpython38/nbody.json | benches/out/rustpython/nbody.json | benches/out/rustpython-3507/nbody.json |
+===========+==================================+===================================+========================================+
| nbody     | 103 ms                           | 1.79 sec: 17.39x slower           | 1.82 sec: 17.70x slower                |
+-----------+----------------------------------+-----------------------------------+----------------------------------------+

@youknowone
Copy link
Member

at least, no regression after using references

+-----------+----------------------------------+-----------------------------------+----------------------------------------+--------------------------------------------+
| Benchmark | benches/out/cpython38/nbody.json | benches/out/rustpython/nbody.json | benches/out/rustpython-3507/nbody.json | benches/out/rustpython-3507/nbody-ref.json |
+===========+==================================+===================================+========================================+============================================+
| nbody     | 103 ms                           | 1.79 sec: 17.39x slower           | 1.82 sec: 17.70x slower                | 1.79 sec: 17.38x slower                    |
+-----------+----------------------------------+-----------------------------------+----------------------------------------+--------------------------------------------+

@youknowone youknowone force-pushed the number-protocol branch 2 times, most recently from 1b9b663 to 7a61d07 Compare May 29, 2022 22:34
@youknowone youknowone merged commit c40bc62 into RustPython:main May 29, 2022
@qingshi163 qingshi163 deleted the number-protocol branch July 3, 2022 19:19
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.

2 participants