summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Wiebe <mwiebe@enthought.com>2011-06-16 14:49:56 -0500
committerMark Wiebe <mwiebe@enthought.com>2011-06-16 14:49:56 -0500
commit2d7d59aef203ebf25b268ceaccfa1be45237b0df (patch)
tree5a9da14c4577a9d0558045be4b9a49d56b94b26c
parente9f4e7592ae24e220bfcd0489b4bb25b9c2fc8e7 (diff)
downloadnumpy-2d7d59aef203ebf25b268ceaccfa1be45237b0df.tar.gz
ENH: datetime-ufunc: Add m8 / m8 -> f8 case to the datetime ufunc operations
-rw-r--r--numpy/core/code_generators/generate_umath.py1
-rw-r--r--numpy/core/src/umath/loops.c.src15
-rw-r--r--numpy/core/src/umath/loops.h15
-rw-r--r--numpy/core/src/umath/loops.h.src3
-rw-r--r--numpy/core/src/umath/ufunc_object.c30
-rw-r--r--numpy/core/tests/test_datetime.py16
6 files changed, 65 insertions, 15 deletions
diff --git a/numpy/core/code_generators/generate_umath.py b/numpy/core/code_generators/generate_umath.py
index 599ffddc8..957607f40 100644
--- a/numpy/core/code_generators/generate_umath.py
+++ b/numpy/core/code_generators/generate_umath.py
@@ -275,6 +275,7 @@ defdict = {
TD(intfltcmplx),
[TypeDescription('m', FullTypeDescr, 'mq', 'm'),
TypeDescription('m', FullTypeDescr, 'md', 'm'),
+ TypeDescription('m', FullTypeDescr, 'mm', 'd'),
],
TD(O, f='PyNumber_Divide'),
),
diff --git a/numpy/core/src/umath/loops.c.src b/numpy/core/src/umath/loops.c.src
index 31345ff45..b23f1018c 100644
--- a/numpy/core/src/umath/loops.c.src
+++ b/numpy/core/src/umath/loops.c.src
@@ -1229,6 +1229,21 @@ TIMEDELTA_md_m_divide(char **args, intp *dimensions, intp *steps, void *NPY_UNUS
}
}
+NPY_NO_EXPORT void
+TIMEDELTA_mm_d_divide(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func))
+{
+ BINARY_LOOP {
+ const npy_timedelta in1 = *(npy_timedelta *)ip1;
+ const npy_timedelta in2 = *(npy_timedelta *)ip2;
+ if (in1 == NPY_DATETIME_NAT || in2 == NPY_DATETIME_NAT) {
+ *((double *)op1) = NPY_NAN;
+ }
+ else {
+ *((double *)op1) = (double)in1 / (double)in2;
+ }
+ }
+}
+
/*
*****************************************************************************
** FLOAT LOOPS **
diff --git a/numpy/core/src/umath/loops.h b/numpy/core/src/umath/loops.h
index 2a827e168..2a792bf5b 100644
--- a/numpy/core/src/umath/loops.h
+++ b/numpy/core/src/umath/loops.h
@@ -2661,6 +2661,9 @@ TIMEDELTA_mq_m_divide(char **args, intp *dimensions, intp *steps, void *NPY_UNUS
NPY_NO_EXPORT void
TIMEDELTA_md_m_divide(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func));
+NPY_NO_EXPORT void
+TIMEDELTA_mm_d_divide(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func));
+
/* Special case equivalents to above functions */
#define TIMEDELTA_mq_m_true_divide TIMEDELTA_mq_m_divide
@@ -2678,27 +2681,27 @@ TIMEDELTA_md_m_divide(char **args, intp *dimensions, intp *steps, void *NPY_UNUS
*****************************************************************************
*/
-#line 511
+#line 514
NPY_NO_EXPORT void
OBJECT_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func));
-#line 511
+#line 514
NPY_NO_EXPORT void
OBJECT_not_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func));
-#line 511
+#line 514
NPY_NO_EXPORT void
OBJECT_greater(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func));
-#line 511
+#line 514
NPY_NO_EXPORT void
OBJECT_greater_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func));
-#line 511
+#line 514
NPY_NO_EXPORT void
OBJECT_less(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func));
-#line 511
+#line 514
NPY_NO_EXPORT void
OBJECT_less_equal(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func));
diff --git a/numpy/core/src/umath/loops.h.src b/numpy/core/src/umath/loops.h.src
index bf41e4187..fdedc1933 100644
--- a/numpy/core/src/umath/loops.h.src
+++ b/numpy/core/src/umath/loops.h.src
@@ -487,6 +487,9 @@ TIMEDELTA_mq_m_divide(char **args, intp *dimensions, intp *steps, void *NPY_UNUS
NPY_NO_EXPORT void
TIMEDELTA_md_m_divide(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func));
+NPY_NO_EXPORT void
+TIMEDELTA_mm_d_divide(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func));
+
/* Special case equivalents to above functions */
#define TIMEDELTA_mq_m_true_divide TIMEDELTA_mq_m_divide
diff --git a/numpy/core/src/umath/ufunc_object.c b/numpy/core/src/umath/ufunc_object.c
index 2e46fc51a..dcc29f2ba 100644
--- a/numpy/core/src/umath/ufunc_object.c
+++ b/numpy/core/src/umath/ufunc_object.c
@@ -2822,8 +2822,9 @@ type_reso_error: {
/*
* This function applies the type resolution rules for division.
* In particular, there are a number of special cases with datetime:
- * m8[<A>] / int## => m8[<A>] / int64
- * m8[<A>] / float## => m8[<A>] / float64
+ * m8[<A>] / m8[<B>] to m8[gcd(<A>,<B>)] / m8[gcd(<A>,<B>)] -> float64
+ * m8[<A>] / int## to m8[<A>] / int64 -> m8[<A>]
+ * m8[<A>] / float## to m8[<A>] / float64 -> m8[<A>]
*/
NPY_NO_EXPORT int
PyUFunc_DivisionTypeResolution(PyUFuncObject *ufunc,
@@ -2851,13 +2852,34 @@ PyUFunc_DivisionTypeResolution(PyUFuncObject *ufunc,
}
if (type_num1 == NPY_TIMEDELTA) {
+ /*
+ * m8[<A>] / m8[<B>] to
+ * m8[gcd(<A>,<B>)] / m8[gcd(<A>,<B>)] -> float64
+ */
+ if (type_num2 == NPY_TIMEDELTA) {
+ out_dtypes[0] = PyArray_PromoteTypes(PyArray_DESCR(operands[0]),
+ PyArray_DESCR(operands[1]));
+ if (out_dtypes[0] == NULL) {
+ return -1;
+ }
+ out_dtypes[1] = out_dtypes[0];
+ Py_INCREF(out_dtypes[1]);
+ out_dtypes[2] = PyArray_DescrFromType(NPY_DOUBLE);
+ if (out_dtypes[2] == NULL) {
+ Py_DECREF(out_dtypes[0]);
+ out_dtypes[0] = NULL;
+ Py_DECREF(out_dtypes[1]);
+ out_dtypes[1] = NULL;
+ return -1;
+ }
+ }
/* m8[<A>] / int## => m8[<A>] / int64 */
- if (PyTypeNum_ISINTEGER(type_num2)) {
+ else if (PyTypeNum_ISINTEGER(type_num2)) {
out_dtypes[0] = ensure_dtype_nbo(PyArray_DESCR(operands[0]));
if (out_dtypes[0] == NULL) {
return -1;
}
- out_dtypes[1] = PyArray_DescrNewFromType(NPY_LONGLONG);
+ out_dtypes[1] = PyArray_DescrFromType(NPY_LONGLONG);
if (out_dtypes[1] == NULL) {
Py_DECREF(out_dtypes[0]);
out_dtypes[0] = NULL;
diff --git a/numpy/core/tests/test_datetime.py b/numpy/core/tests/test_datetime.py
index b51febb85..c533f3b2c 100644
--- a/numpy/core/tests/test_datetime.py
+++ b/numpy/core/tests/test_datetime.py
@@ -738,31 +738,37 @@ class TestDateTime(TestCase):
assert_raises(TypeError, np.multiply, 1.5, dta)
def test_datetime_divide(self):
- for dta, tda, tdb, tdc in \
+ for dta, tda, tdb, tdc, tdd in \
[
# One-dimensional arrays
(np.array(['2012-12-21'], dtype='M8[D]'),
np.array([6], dtype='m8[h]'),
np.array([9], dtype='m8[h]'),
- np.array([12], dtype='m8[h]')),
+ np.array([12], dtype='m8[h]'),
+ np.array([6], dtype='m8[m]')),
# NumPy scalars
(np.datetime64('2012-12-21', '[D]'),
np.timedelta64(6, '[h]'),
np.timedelta64(9, '[h]'),
- np.timedelta64(12, '[h]'))]:
+ np.timedelta64(12, '[h]'),
+ np.timedelta64(6, '[m]'))]:
# m8 / int
assert_equal(tdc / 2, tda)
assert_equal((tdc / 2).dtype, np.dtype('m8[h]'))
# m8 / float
assert_equal(tda / 0.5, tdc)
assert_equal((tda / 0.5).dtype, np.dtype('m8[h]'))
+ # m8 / m8
+ assert_equal(tda / tdb, 6.0 / 9.0)
+ assert_equal(tdb / tda, 9.0 / 6.0)
+ assert_equal((tda / tdb).dtype, np.dtype('f8'))
+ assert_equal(tda / tdd, 60.0)
+ assert_equal(tdd / tda, 1.0 / 60.0)
# int / m8
assert_raises(TypeError, np.divide, 2, tdb)
# float / m8
assert_raises(TypeError, np.divide, 0.5, tdb)
- # m8 / m8
- assert_raises(TypeError, np.divide, tda, tdb)
# m8 / M8
assert_raises(TypeError, np.divide, dta, tda)
# M8 / m8