8000 Merge pull request #13218 from debsankha/isfinite-datetime · pentschev/numpy@32acbd3 · GitHub
[go: up one dir, main page]

Skip to content

Commit 32acbd3

Browse files
authored
Merge pull request numpy#13218 from debsankha/isfinite-datetime
ENH: `isfinite` support for `datetime64` and `timedelta64`
2 parents 842970f + 3837444 commit 32acbd3

File tree

7 files changed

+67
-2
lines changed

7 files changed

+67
-2
lines changed

doc/release/1.17.0-notes.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,11 @@ The boolean and integer types are incapable of storing ``np.nan`` and ``np.inf``
202202
which allows us to provide specialized ufuncs that are up to 250x faster than the current
203203
approach.
204204

205+
``np.isfinite`` supports ``datetime64`` and ``timedelta64`` types
206+
-----------------------------------------------------------------
207+
Previously, `np.isfinite` used to raise a ``TypeError`` on being used on these
208+
two types.
209+
205210
New keywords added to ``np.nan_to_num``
206211
---------------------------------------
207212
``np.nan_to_num`` now accepts keywords ``nan``, ``posinf`` and ``neginf`` allowing the

numpy/core/code_generators/generate_umath.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -844,8 +844,8 @@ def english_upper(s):
844844
'isfinite':
845845
Ufunc(1, 1, None,
846846
docstrings.get('numpy.core.umath.isfinite'),
847-
None,
848-
TD(nodatetime_or_obj, out='?'),
847+
'PyUFunc_IsFiniteTypeResolver',
848+
TD(noobj, out='?'),
849849
),
850850
'signbit':
851851
Ufunc(1, 1, None,

numpy/core/src/umath/loops.c.src

Lines changed: 9 additions & 0 deletions
< 8000 /table>

numpy/core/src/umath/loops.h.src

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1171,6 +1171,15 @@ NPY_NO_EXPORT void
11711171
}
11721172
}
11731173

1174+
NPY_NO_EXPORT void
1175+
@TYPE@_isfinite(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
1176+
{
1177+
UNARY_LOOP {
1178+
const @type@ in1 = *(@type@ *)ip1;
1179+
*((npy_bool *)op1) = (in1 != NPY_DATETIME_NAT);
1180+
}
1181+
}
1182+
11741183
NPY_NO_EXPORT void
11751184
@TYPE@__ones_like(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data))
11761185
{
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,9 @@ TIMEDELTA_sign(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNU
427427
NPY_NO_EXPORT void
428428
@TYPE@_isnat(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
429429

430+
NPY_NO_EXPORT void
431+
@TYPE@_isfinite(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
432+
430433
NPY_NO_EXPORT void
431434
@TYPE@__ones_like(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data));
432435

numpy/core/src/umath/ufunc_type_resolution.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -611,6 +611,26 @@ PyUFunc_IsNaTTypeResolver(PyUFuncObject *ufunc,
611611
return 0;
612612
}
613613

614+
615+
NPY_NO_EXPORT int
616+
PyUFunc_IsFiniteTypeResolver(PyUFuncObject *ufunc,
617+
NPY_CASTING casting,
618+
PyArrayObject **operands,
619+
PyObject *type_tup,
620+
PyArray_Descr **out_dtypes)
621+
{
622+
if (!PyTypeNum_ISDATETIME(PyArray_DESCR(operands[0])->type_num)) {
623+
return PyUFunc_DefaultTypeResolver(ufunc, casting, operands,
624+
type_tup, out_dtypes);
625+
}
626+
627+
out_dtypes[0] = ensure_dtype_nbo(PyArray_DESCR(operands[0]));
628+
out_dtypes[1] = PyArray_DescrFromType(NPY_BOOL);
629+
630+
return 0;
631+
}
632+
633+
614634
/*
615635
* Creates a new NPY_TIMEDELTA dtype, copying the datetime metadata
616636
* from the given dtype.

numpy/core/src/umath/ufunc_type_resolution.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,13 @@ PyUFunc_IsNaTTypeResolver(PyUFuncObject *ufunc,
4343
PyObject *type_tup,
4444
PyArray_Descr **out_dtypes);
4545

46+
NPY_NO_EXPORT int
47+
PyUFunc_IsFiniteTypeResolver(PyUFuncObject *ufunc,
48+
NPY_CASTING casting,
49+
PyArrayObject **operands,
50+
PyObject *type_tup,
51+
PyArray_Descr **out_dtypes);
52+
4653
NPY_NO_EXPORT int
4754
PyUFunc_AdditionTypeResolver(PyUFuncObject *ufunc,
4855
NPY_CASTING casting,

numpy/core/tests/test_datetime.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2208,6 +2208,27 @@ def test_isnat_error(self):
22082208
continue
22092209
assert_raises(TypeError, np.isnat, np.zeros(10, t))
22102210

2211+
def test_isfinite(self):
2212+
assert_(not np.isfinite(np.datetime64('NaT', 'ms')))
2213+
assert_(not np.isfinite(np.datetime64('NaT', 'ns')))
2214+
assert_(np.isfinite(np.datetime64('2038-01-19T03:14:07')))
2215+
2216+
assert_(not np.isfinite(np.timedelta64('NaT', "ms")))
2217+
assert_(np.isfinite(np.timedelta64(34, "ms")))
2218+
2219+
res = np.array([True, True, False])
2220+
for unit in ['Y', 'M', 'W', 'D',
2221+
'h', 'm', 's', 'ms', 'us',
2222+
'ns', 'ps', 'fs', 'as']:
2223+
arr = np.array([123, -321, "NaT"], dtype='<datetime64[%s]' % unit)
2224+
assert_equal(np.isfinite(arr), res)
2225+
arr = np.array([123, -321, "NaT"], dtype='>datetime64[%s]' % unit)
2226+
assert_equal(np.isfinite(arr), res)
2227+
arr = np.array([123, -321, "NaT"], dtype='<timedelta64[%s]' % unit)
2228+
assert_equal(np.isfinite(arr), res)
2229+
arr = np.array([123, -321, "NaT"], dtype='>timedelta64[%s]' % unit)
2230+
assert_equal(np.isfinite(arr), res)
2231+
22112232
def test_corecursive_input(self):
22122233
# construct a co-recursive list
22132234
a, b = [], []

0 commit comments

Comments
 (0)
0