summaryrefslogtreecommitdiff
path: root/numpy/core
diff options
context:
space:
mode:
authorGanesh Kathiresan <ganesh3597@gmail.com>2020-11-13 12:02:03 +0530
committerGanesh Kathiresan <ganesh3597@gmail.com>2020-11-13 12:02:03 +0530
commitc85c44a8091dffc921ac81059280f99b9d4dc198 (patch)
tree46637412a020aba9f2e240d64017deb267000eae /numpy/core
parent0ce0ebd3b895678f2a59797564e17a0aedad6872 (diff)
downloadnumpy-c85c44a8091dffc921ac81059280f99b9d4dc198.tar.gz
ENH: Added libdivide to timedelta
Diffstat (limited to 'numpy/core')
-rw-r--r--numpy/core/src/umath/loops.c.src87
1 files changed, 68 insertions, 19 deletions
diff --git a/numpy/core/src/umath/loops.c.src b/numpy/core/src/umath/loops.c.src
index b37f4c427..a7c0cb365 100644
--- a/numpy/core/src/umath/loops.c.src
+++ b/numpy/core/src/umath/loops.c.src
@@ -862,7 +862,7 @@ NPY_NO_EXPORT void
{
BINARY_LOOP_BASE
- if(!is2) {
+ if (!is2) {
const @type@ in2 = *(@type@ *)ip2;
/* Creating a divisor of 0 is treated as an error by libdivide */
@@ -1403,14 +1403,33 @@ TIMEDELTA_dm_m_multiply(char **args, npy_intp const *dimensions, npy_intp const
NPY_NO_EXPORT void
TIMEDELTA_mq_m_divide(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
{
- BINARY_LOOP {
- const npy_timedelta in1 = *(npy_timedelta *)ip1;
+ BINARY_LOOP_BASE
+
+ if (!is2) {
const npy_int64 in2 = *(npy_int64 *)ip2;
- if (in1 == NPY_DATETIME_NAT || in2 == 0) {
- *((npy_timedelta *)op1) = NPY_DATETIME_NAT;
+
+ /* Creating a divisor of 0 is treated as an error by libdivide */
+ struct libdivide_s64_t fast_d = in2 ? libdivide_s64_gen(in2) : (struct libdivide_s64_t){0};
+ BINARY_LOOP_FIXED {
+ const npy_timedelta in1 = *(npy_timedelta *)ip1;
+ if (in1 == NPY_DATETIME_NAT || in2 == 0) {
+ *((npy_timedelta *)op1) = NPY_DATETIME_NAT;
+ }
+ else {
+ *((npy_timedelta *)op1) = libdivide_s64_do(in1, &fast_d);;
+ }
}
- else {
- *((npy_timedelta *)op1) = in1 / in2;
+ }
+ else {
+ BINARY_LOOP_SLIDING {
+ const npy_timedelta in1 = *(npy_timedelta *)ip1;
+ const npy_int64 in2 = *(npy_int64 *)ip2;
+ if (in1 == NPY_DATETIME_NAT || in2 == 0) {
+ *((npy_timedelta *)op1) = NPY_DATETIME_NAT;
+ }
+ else {
+ *((npy_timedelta *)op1) = in1 / in2;
+ }
}
}
}
@@ -1482,23 +1501,53 @@ TIMEDELTA_mm_m_remainder(char **args, npy_intp const *dimensions, npy_intp const
NPY_NO_EXPORT void
TIMEDELTA_mm_q_floor_divide(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
{
- BINARY_LOOP {
- const npy_timedelta in1 = *(npy_timedelta *)ip1;
+ /* TODO: This code is similar to array floor divide*/
+ BINARY_LOOP_BASE
+
+ if (!is2) {
const npy_timedelta in2 = *(npy_timedelta *)ip2;
- if (in1 == NPY_DATETIME_NAT || in2 == NPY_DATETIME_NAT) {
- npy_set_floatstatus_invalid();
- *((npy_int64 *)op1) = 0;
- }
- else if (in2 == 0) {
- npy_set_floatstatus_divbyzero();
- *((npy_int64 *)op1) = 0;
+
+ /* Creating a divisor of 0 is treated as an error by libdivide */
+ struct libdivide_s64_t fast_d = in2 ? libdivide_s64_gen(in2) : (struct libdivide_s64_t){0};
+ BINARY_LOOP_FIXED {
+ const npy_timedelta in1 = *(npy_timedelta *)ip1;
+ if (in1 == NPY_DATETIME_NAT || in2 == NPY_DATETIME_NAT) {
+ npy_set_floatstatus_invalid();
+ *((npy_int64 *)op1) = 0;
+ }
+ else if (in2 == 0) {
+ npy_set_floatstatus_divbyzero();
+ *((npy_int64 *)op1) = 0;
+ }
+ else {
+ *((npy_int64 *)op1) = libdivide_s64_do(in1, &fast_d);
+
+ /* Negative quotients needs to be rounded down */
+ if (((in1 > 0) != (in2 > 0)) && (*((npy_int64 *)op1) * in2 != in1)) {
+ *((npy_int64 *)op1) = *((npy_int64 *)op1) - 1;
+ }
+ }
}
- else {
- if (((in1 > 0) != (in2 > 0)) && (in1 % in2 != 0)) {
- *((npy_int64 *)op1) = in1/in2 - 1;
+ }
+ else {
+ BINARY_LOOP_SLIDING {
+ const npy_timedelta in1 = *(npy_timedelta *)ip1;
+ const npy_timedelta in2 = *(npy_timedelta *)ip2;
+ if (in1 == NPY_DATETIME_NAT || in2 == NPY_DATETIME_NAT) {
+ npy_set_floatstatus_invalid();
+ *((npy_int64 *)op1) = 0;
+ }
+ else if (in2 == 0) {
+ npy_set_floatstatus_divbyzero();
+ *((npy_int64 *)op1) = 0;
}
else {
*((npy_int64 *)op1) = in1/in2;
+
+ /* Negative quotients needs to be rounded down */
+ if (((in1 > 0) != (in2 > 0)) && (*((npy_int64 *)op1) * in2 != in1)) {
+ *((npy_int64 *)op1) = *((npy_int64 *)op1) - 1;
+ }
}
}
}