@@ -1357,3 +1357,130 @@ def test_trapz_1dim_with_x_and_dx(self, xp, dtype):
13571357 a = testing .shaped_arange ((5 ,), xp , dtype )
13581358 x = testing .shaped_arange ((5 ,), xp , dtype )
13591359 return xp .trapezoid (a , x = x , dx = 0.1 )
1360+
1361+
1362+ @testing .with_requires ("numpy>=2.1" )
1363+ @pytest .mark .parametrize ("func" , ["cumulative_sum" , "cumulative_prod" ])
1364+ class TestCumulativeSumProd :
1365+
1366+ @testing .for_all_dtypes ()
1367+ @testing .numpy_cupy_allclose (rtol = 1e-6 )
1368+ def test_1d (self , xp , dtype , func ):
1369+ a = testing .shaped_arange ((5 ,), xp , dtype )
1370+ return getattr (xp , func )(a )
1371+
1372+ @testing .for_all_dtypes ()
1373+ @testing .numpy_cupy_allclose (rtol = 1e-6 , contiguous_check = False )
1374+ def test_axis (self , xp , dtype , func ):
1375+ a = testing .shaped_arange ((3 , 4 , 5 ), xp , dtype )
1376+ return getattr (xp , func )(a , axis = 1 )
1377+
1378+ @testing .for_all_dtypes ()
1379+ @testing .numpy_cupy_allclose (rtol = 1e-6 )
1380+ def test_negative_axis (self , xp , dtype , func ):
1381+ a = testing .shaped_arange ((3 , 4 , 5 ), xp , dtype )
1382+ return getattr (xp , func )(a , axis = - 1 )
1383+
1384+ @testing .for_all_dtypes (no_bool = True )
1385+ @testing .numpy_cupy_allclose (rtol = 1e-6 )
1386+ def test_dtype (self , xp , dtype , func ):
1387+ a = testing .shaped_arange ((5 ,), xp , numpy .int16 )
1388+ return getattr (xp , func )(a , dtype = dtype )
1389+
1390+ @testing .for_all_dtypes ()
1391+ @testing .numpy_cupy_allclose (rtol = 1e-6 )
1392+ def test_1d_include_initial (self , xp , dtype , func ):
1393+ a = testing .shaped_arange ((5 ,), xp , dtype )
1394+ return getattr (xp , func )(a , include_initial = True )
1395+
1396+ @testing .for_all_dtypes ()
1397+ @testing .numpy_cupy_allclose (rtol = 1e-6 , contiguous_check = False )
1398+ def test_axis_include_initial (self , xp , dtype , func ):
1399+ a = testing .shaped_arange ((3 , 4 , 5 ), xp , dtype )
1400+ return getattr (xp , func )(a , axis = 1 , include_initial = True )
1401+
1402+ @testing .for_all_dtypes ()
1403+ @testing .numpy_cupy_allclose (rtol = 1e-6 )
1404+ def test_negative_axis_include_initial (self , xp , dtype , func ):
1405+ a = testing .shaped_arange ((3 , 4 , 5 ), xp , dtype )
1406+ return getattr (xp , func )(a , axis = - 1 , include_initial = True )
1407+
1408+ @testing .for_all_dtypes ()
1409+ @testing .numpy_cupy_allclose (rtol = 1e-6 )
1410+ def test_out (self , xp , dtype , func ):
1411+ a = testing .shaped_arange ((3 , 4 , 5 ), xp , dtype )
1412+ out = xp .zeros ((3 , 4 , 5 ), dtype = dtype )
1413+ getattr (xp , func )(a , axis = 1 , out = out )
1414+ return out
1415+
1416+ @testing .for_all_dtypes ()
1417+ @testing .numpy_cupy_allclose (rtol = 1e-6 )
1418+ def test_out_include_initial (self , xp , dtype , func ):
1419+ a = testing .shaped_arange ((3 , 4 , 5 ), xp , dtype )
1420+ out = xp .zeros ((3 , 5 , 5 ), dtype = dtype )
1421+ getattr (xp , func )(a , axis = 1 , out = out , include_initial = True )
1422+ return out
1423+
1424+ @testing .for_all_dtypes ()
1425+ def test_axis_none_requires_1d (self , dtype , func ):
1426+ for xp in (numpy , cupy ):
1427+ a = testing .shaped_arange ((3 , 4 ), xp , dtype )
1428+ with pytest .raises (ValueError ):
1429+ getattr (xp , func )(a )
1430+
1431+ @testing .for_all_dtypes ()
1432+ def test_invalid_axis (self , dtype , func ):
1433+ for xp in (numpy , cupy ):
1434+ a = testing .shaped_arange ((3 , 4 ), xp , dtype )
1435+ with pytest .raises (AxisError ):
1436+ getattr (xp , func )(a , axis = 3 )
1437+
1438+ def test_out_shape_mismatch (self , func ):
1439+ a = testing .shaped_arange ((3 , 4 ), cupy , numpy .float32 )
1440+ out = cupy .zeros ((3 , 5 ), dtype = numpy .float32 )
1441+ with pytest .raises (ValueError ):
1442+ getattr (cupy , func )(a , axis = 1 , out = out )
1443+
1444+ @pytest .mark .skip ("implementation-defined acc to Python array API" )
1445+ @testing .for_all_dtypes ()
1446+ @testing .numpy_cupy_allclose (rtol = 1e-6 )
1447+ def test_0d (self , xp , dtype , func ):
1448+ # numpy accepts 0-D input; cupy matches via atleast_1d.
1449+ a = xp .asarray (3 , dtype = dtype )
1450+ return getattr (xp , func )(a )
1451+
1452+ @testing .for_all_dtypes ()
1453+ @testing .numpy_cupy_allclose (rtol = 1e-6 )
1454+ def test_0d_include_initial (self , xp , dtype , func ):
1455+ a = xp .asarray (3 , dtype = dtype )
1456+ return getattr (xp , func )(a , include_initial = True )
1457+
1458+ @testing .for_all_dtypes ()
1459+ @testing .numpy_cupy_allclose (rtol = 1e-6 )
1460+ def test_empty_axis (self , xp , dtype , func ):
1461+ a = xp .empty ((3 , 0 , 4 ), dtype = dtype )
1462+ return getattr (xp , func )(a , axis = 1 )
1463+
1464+ @testing .for_all_dtypes ()
1465+ @testing .numpy_cupy_allclose (rtol = 1e-6 )
1466+ def test_empty_axis_include_initial (self , xp , dtype , func ):
1467+ a = xp .empty ((3 , 0 , 4 ), dtype = dtype )
1468+ return getattr (xp , func )(a , axis = 1 , include_initial = True )
1469+
1470+ @pytest .mark .parametrize ("in_dtype" , [numpy .int8 , numpy .uint16 ])
1471+ @testing .numpy_cupy_array_equal ()
1472+ def test_narrow_int_promotion_include_initial (self , xp , in_dtype , func ):
1473+ # Narrow integer inputs must promote to int64 / uint64 (matches
1474+ # numpy's default-platform-integer rule) even when include_initial
1475+ # takes the internal-allocation path.
1476+ a = testing .shaped_arange ((5 ,), xp , in_dtype )
1477+ return getattr (xp , func )(a , include_initial = True )
1478+
1479+ @testing .for_all_dtypes (no_bool = True )
1480+ @testing .numpy_cupy_allclose (rtol = 1e-6 )
1481+ def test_out_dtype_cast (self , xp , dtype , func ):
1482+ # out has a different dtype than x -- result must be cast.
1483+ a = testing .shaped_arange ((3 , 4 , 5 ), xp , numpy .int16 )
1484+ out = xp .zeros ((3 , 4 , 5 ), dtype = dtype )
1485+ getattr (xp , func )(a , axis = 1 , out = out )
1486+ return out
0 commit comments