There's an issue from 2017 that I'm working on fixing:
https://github.com/numpy/numpy/issues/8463.

The issue is that currently, the `sign` ufunc applied to a
`timedelta64` instance returns a `timedelta64` instance. This means
that the `sign` function for this type does not satisfy the properties
that one would expect. For example, one would expect that, in general,
`sign(x) * abs(x) == x`. But this does not work for `timedelta64`:

```
In [35]: x = timedelta64(-123, 's')

In [36]: sign(x) * abs(x)
[...]
UFuncTypeError: ufunc 'multiply' cannot use operands with types
dtype('<m8[s]') and dtype('<m8[s]')
```

Also mentioned in that issue is that one would expect
`sign(timedelta64(123, 's')) == sign(timedelta64(999, 'm'))`, but
currently those have different values:

```
In [41]: sign(timedelta64(123, 's'))
Out[41]: np.timedelta64(1,'s')

In [42]: sign(timedelta64(999, 'm'))
Out[42]: np.timedelta64(1,'m')
```
The first has the value 1 *second*, and the second has the value 1
*minute*, and those values are not equal.

In fact, the sign should not have units. The first natural choice for
the sign of a `timedelta64` would be an integer, either -1, 0, or 1.
However, a `timedelta64` instance might also be `NaT`, and none of
those values are correct in that case. Instead we can use floats, and
return `nan` for `sign(timedelta64('NaT', 's'))`. So the possible
values are -1.0, 0.0, 1.0 and nan. There is some discussion of this
choice in https://github.com/numpy/numpy/issues/8463.

This is implemented as a draft PR: https://github.com/numpy/numpy/pull/30194.

For such a change, we would usually go through a deprecation cycle. In
this case, we are proposing to simply make the change, for the
following reasons:

* We can't really see it leading to bad results for users; the
numerical values are still mathematically the same[1].
* Only few people should notice the change (even among users).
* Generally, a warning is more annoying than any transition path that
we or a user might try to implement. There isn't a good way to provide
a deprecation phase where the user can opt-in to the new behavior
during the deprecation phase and get rid of the warning.

One can also argue that this is "just" a bug fix, but the current
behavior has been around for a long time, so that argument doesn't
carry much weight.

We would be sure to not merge this right before a major release. It
should be in the main development branch long enough for any
downstream libraries or users (at least those that test with the
development branch) to adapt to the change, or for us to revert it if
the impact is bigger than expected.

What do you think?

Warren

-----

[1] Incidentally, we'll also fix the bug where
`sign(timedelta64('NaT'))` incorrectly returns -1
(https://github.com/numpy/numpy/issues/29496).
_______________________________________________
NumPy-Discussion mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/numpy-discussion.python.org
Member address: [email protected]

Reply via email to