Repository: numpy/numpy
File: numpy/core/tests/test_ufunc.py (Python)

Code before:
        index = np.array([1, 2, 1], np.dtype('i').newbyteorder())
        values = np.array([1, 2, 3, 4], np.dtype('f').newbyteorder())
        np.add.at(values, index, 3)
        assert_array_equal(values, [1, 8, 6, 4])

        # Test exception thrown
        values = np.array(['a', 1], dtype=object)
        assert_raises(TypeError, np.add.at, values, [0, 1], 1)
        assert_array_equal(values, np.array(['a', 1], dtype=object))

        # Test multiple output ufuncs raise error, gh-5665
        assert_raises(ValueError, np.modf.at, np.arange(10), [1])

        # Test maximum
        a = np.array([1, 2, 3])
        np.maximum.at(a, [0], 0)
        assert_equal(a, np.array([1, 2, 3]))

    def test_at_not_none_signature(self):
        # Test ufuncs with non-trivial signature raise a TypeError
        a = np.ones((2, 2, 2))
        b = np.ones((1, 2, 2))
        assert_raises(TypeError, np.matmul.at, a, [0], b)

        a = np.array([[[1, 2], [3, 4]]])
        assert_raises(TypeError, np.linalg._umath_linalg.det.at, a, [0])

    def test_at_no_loop_for_op(self):
        # str dtype does not have a ufunc loop for np.add
        arr = np.ones(10, dtype=str)
        with pytest.raises(np.core._exceptions._UFuncNoLoopError):
            np.add.at(arr, [0, 1], [0, 1])

    def test_at_output_casting(self):
        arr = np.array([-1])
        np.equal.at(arr, [0], [0])
        assert arr[0] == 0

    def test_at_broadcast_failure(self):
        arr = np.arange(5)
        with pytest.raises(ValueError):
            np.add.at(arr, [0, 1], [1, 2, 3])


    def test_reduce_arguments(self):
        f = np.add.reduce
        d = np.ones((5,2), dtype=int)
        o = np.ones((2,), dtype=d.dtype)
        r = o * 5
        assert_equal(f(d), r)
        # a, axis=0, dtype=None, out=None, keepdims=False

Review comment (bug):
An bad merge (locally) brought me here, but then I noticed that this can modify the original index array:
```
assert indxs[0] == -1
```
would fail.  I think it shows that passing pointers or full offsets rather than indices makes more sense here (we need a temporary array anyway), but I have to think about how a hot-fix should look like.
Probably either need a local buffer here, or push the fixing into the indexed loop.

(Maybe local buffer is good, since that is what I would want to do with that hot-fix anyway in some form, even if it may make sense to push the buffer for that case slightly further up.)

Code after:
        index = np.array([1, 2, 1], np.dtype('i').newbyteorder())
        values = np.array([1, 2, 3, 4], np.dtype('f').newbyteorder())
        np.add.at(values, index, 3)
        assert_array_equal(values, [1, 8, 6, 4])

        # Test exception thrown
        values = np.array(['a', 1], dtype=object)
        assert_raises(TypeError, np.add.at, values, [0, 1], 1)
        assert_array_equal(values, np.array(['a', 1], dtype=object))

        # Test multiple output ufuncs raise error, gh-5665
        assert_raises(ValueError, np.modf.at, np.arange(10), [1])

        # Test maximum
        a = np.array([1, 2, 3])
        np.maximum.at(a, [0], 0)
        assert_equal(a, np.array([1, 2, 3]))

    def test_at_negative_indexes(self):
        a = np.arange(10)
        indxs = np.array([-1, 1, -1, 2])
        np.add.at(a, indxs, 1)
        assert a[-1] == 11  # issue 24147
        assert a[1] == 2
        assert a[2] == 3

    def test_at_not_none_signature(self):
        # Test ufuncs with non-trivial signature raise a TypeError
        a = np.ones((2, 2, 2))
        b = np.ones((1, 2, 2))
        assert_raises(TypeError, np.matmul.at, a, [0], b)

        a = np.array([[[1, 2], [3, 4]]])
        assert_raises(TypeError, np.linalg._umath_linalg.det.at, a, [0])

    def test_at_no_loop_for_op(self):
        # str dtype does not have a ufunc loop for np.add
        arr = np.ones(10, dtype=str)
        with pytest.raises(np.core._exceptions._UFuncNoLoopError):
            np.add.at(arr, [0, 1], [0, 1])

    def test_at_output_casting(self):
        arr = np.array([-1])
        np.equal.at(arr, [0], [0])
        assert arr[0] == 0

    def test_at_broadcast_failure(self):
        arr = np.arange(5)
        with pytest.raises(ValueError):
            np.add.at(arr, [0, 1], [1, 2, 3])