-
-
Notifications
You must be signed in to change notification settings - Fork 11.1k
ENH: add np.divmod ufunc #9063
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
ENH: add np.divmod ufunc #9063
Changes from 1 commit
c9d1f9e
d51b538
6144637
a148978
8fbf75e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -121,6 +121,7 @@ Arithmetic operations | |
mod | ||
modf | ||
remainder | ||
divmod | ||
|
||
Handling complex numbers | ||
------------------------ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -510,6 +510,7 @@ Math operations | |
remainder | ||
mod | ||
fmod | ||
divmod | ||
absolute | ||
fabs | ||
rint | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1114,6 +1114,34 @@ NPY_NO_EXPORT void | |
} | ||
} | ||
|
||
NPY_NO_EXPORT void | ||
@TYPE@_divmod(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func)) | ||
{ | ||
BINARY_LOOP_TWO_OUT { | ||
const @type@ in1 = *(@type@ *)ip1; | ||
const @type@ in2 = *(@type@ *)ip2; | ||
/* see FIXME note for divide above */ | ||
if (in2 == 0 || (in1 == NPY_MIN_@TYPE@ && in2 == -1)) { | ||
npy_set_floatstatus_divbyzero(); | ||
*((@type@ *)op1) = 0; | ||
*((@type@ *)op2) = 0; | ||
} | ||
else { | ||
/* handle mixed case the way Python does */ | ||
const @type@ quo = in1 / in2; | ||
const @type@ rem = in1 % in2; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if we should be using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Scrap that, apparently it's better to leave the compiler to it. Might be sensible to have a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed, that is definitely clearer. Done. |
||
if ((in1 > 0) == (in2 > 0) || rem == 0) { | ||
*((@type@ *)op1) = quo; | ||
*((@type@ *)op2) = rem; | ||
} | ||
else { | ||
*((@type@ *)op1) = quo - 1; | ||
*((@type@ *)op2) = rem + in2; | ||
} | ||
} | ||
} | ||
} | ||
|
||
/**end repeat**/ | ||
|
||
/**begin repeat | ||
|
@@ -1168,6 +1196,24 @@ NPY_NO_EXPORT void | |
} | ||
} | ||
|
||
NPY_NO_EXPORT void | ||
@TYPE@_divmod(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func)) | ||
{ | ||
BINARY_LOOP_TWO_OUT { | ||
const @type@ in1 = *(@type@ *)ip1; | ||
const @type@ in2 = *(@type@ *)ip2; | ||
if (in2 == 0) { | ||
npy_set_floatstatus_divbyzero(); | ||
*((@type@ *)op1) = 0; | ||
*((@type@ *)op2) = 0; | ||
} | ||
else { | ||
*((@type@ *)op1)= in1/in2; | ||
*((@type@ *)op2) = in1 % in2; | ||
} | ||
} | ||
} | ||
|
||
/**end repeat**/ | ||
|
||
/* | ||
|
@@ -1831,6 +1877,16 @@ NPY_NO_EXPORT void | |
} | ||
} | ||
|
||
NPY_NO_EXPORT void | ||
@TYPE@_divmod(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func)) | ||
{ | ||
BINARY_LOOP_TWO_OUT { | ||
const @type@ in1 = *(@type@ *)ip1; | ||
const @type@ in2 = *(@type@ *)ip2; | ||
*((@type@ *)op1) = npy_divmod@c@(in1, in2, (@type@ *)op2); | ||
} | ||
} | ||
|
||
NPY_NO_EXPORT void | ||
@TYPE@_square(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data)) | ||
{ | ||
|
@@ -2159,6 +2215,16 @@ HALF_remainder(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNU | |
} | ||
} | ||
|
||
NPY_NO_EXPORT void | ||
HALF_divmod(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func)) | ||
{ | ||
BINARY_LOOP_TWO_OUT { | ||
const npy_half in1 = *(npy_half *)ip1; | ||
const npy_half in2 = *(npy_half *)ip2; | ||
*((npy_half *)op1) = npy_half_divmod(in1, in2, (npy_half *)op2); | ||
} | ||
} | ||
|
||
NPY_NO_EXPORT void | ||
HALF_square(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data)) | ||
{ | ||
|
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.
Nit:
resulting
should probably be in both places or neitherThere 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.
The quotient is the result of floor division, but the remainder is a by-product. So I think the current language makes sense (but I'm open to alternatives if you have a concrete suggestion).
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'm not convinced results and byproducts are disjoint sets, but I'm happy to leave this as is based on your rationale.