-
-
Notifications
You must be signed in to change notification settings - Fork 31.5k
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
bpo-35606: Implement math.prod #11359
Conversation
Doc/library/math.rst
Outdated
@@ -218,6 +229,7 @@ platform C double type), in which case any float *x* with ``abs(x) >= 2**52`` | |||
necessarily has no fractional bits. | |||
|
|||
|
|||
|
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.
unnecessary line?
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.
Fixed
Look.
This isn't normal, right? |
@eamanu Is the same result you will get if you use a simple reduce algorithm:
This raises the question if we should ban certain data types as lists/dicts...etc but that behaviour is totally normal for that input. |
@pablogsal If we based on |
@eamanu Why not? This is perfectly valid and an analogous is in the test suite:
We can decide to limit the API to not accept list/tuples/etc but people can get away and subclass them or implement their own containers. I think the text in the doc and docstring is enough. |
Ok, yes, you are right. A test with the form |
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
Modules/mathmodule.c
Outdated
return PyFloat_FromDouble(f_result); | ||
} | ||
if (PyFloat_CheckExact(item)) { | ||
PyFPE_START_PROTECT("prod", Py_DECREF(item); Py_DECREF(iter); return 0) |
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.
Support for these macros was dropped in 3.7, so you can leave them out. We still define the macros to avoid breaking pre-existing third-party code but the macros don't do anything, they are empty.
When you're done making the requested changes, leave the comment: |
Please add an entry to whatsnew/3.8.rst. Otherwise, this all looks good :-) |
a97b7f6
to
a9ffb24
Compare
Can you please fix-up the CI bot failures. Likely, it wants the trailing whitespace cleaned-up. |
self.assertRaises(TypeError, prod, ['a', 'b', 'c'], '') | ||
self.assertRaises(TypeError, prod, [b'a', b'c'], b'') | ||
values = [bytearray(b'a'), bytearray(b'b')] | ||
self.assertRaises(TypeError, prod, values, bytearray(b'')) | ||
self.assertRaises(TypeError, prod, [[1], [2], [3]]) | ||
self.assertRaises(TypeError, prod, [{2:3}]) | ||
self.assertRaises(TypeError, prod, [{2:3}]*2, {2:3}) | ||
self.assertRaises(TypeError, prod, [[1], [2], [3]], []) | ||
with self.assertRaises(TypeError): | ||
prod([10, 20], [30, 40]) # start is a keyword-only argument |
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.
@rhettinger / @pablogsal - Skulpt committer here - implementing these tests in our own project.
I was wondering if the intention wasn't quite right with some of these TypeError tests?
Most of them fail because start is a keyword only argument.
Whereas it looks like - for most of them except the final test - the intention is to check multiplication across incompatible types within the prod function.
} | ||
|
||
if (result == NULL) { | ||
result = PyLong_FromLong(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.
You can use _PyLong_One
.
} | ||
/* Loop over all the items in the iterable until we finish, we overflow | ||
* or we found a non integer element */ | ||
while(result == NULL) { |
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.
Add a space between while
and (
.
} | ||
if (PyLong_CheckExact(item)) { | ||
long b = PyLong_AsLongAndOverflow(item, &overflow); | ||
long x = i_result * b; |
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.
Signed integer overflow is an undefined behavior.
/* Continue if there is no overflow */ | ||
if (overflow == 0 | ||
&& x < INT_MAX && x > INT_MIN | ||
&& !(b != 0 && x / i_result != b)) { |
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.
Possible division by 0.
double f_result = PyFloat_AS_DOUBLE(result); | ||
Py_DECREF(result); | ||
result = NULL; | ||
while(result == NULL) { |
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.
Add a space between while
and (
.
@serhiy-storchaka Thanks for the review. This PR is already merged so I can do a separate PR if you wish |
Please address @s-cork comment. Tests do not work as intended. |
Ah, I started reviewing after seen @s-cork comment, without noticing that this PR was merged years ago. |
Yeah, most of these things are already fixed, although is possible that some of these still remain. I will do a check. |
Comparison between
math.prod
andreduce
+operator.mul
https://bugs.python.org/issue35606
Note: This PR is a reference implementation to further discuss the addition of
prod
to themath
module.