Repository: cupy/cupy

Issue:
Support NumPy 1.22
## [Tasks](https://github.com/cupy/cupy/wiki/Actions-Needed-for-Dependency-Update)

- [x] Read Release Notes.
- [x] Update FlexCI schema/matrix to test against the version. #6323
- [x] For NumPy/SciPy, update requirements in `setup.py`.
  - [x] Update the pinned upper bound version (see #4773) #6323
  - [x] Backport. #6354
- [x] Update documentation
  - [x] Update Requirements section in [Installation Guide](https://docs.cupy.dev/en/latest/install.html). The baseline version must be updated in the development branch. #6323
  - [x] Update `docs/requirements.txt` to use the latest versions. #6323
  - [x] Backport. Do not update the baseline version in backport. #6354
- [x] Update CuPy codebase (if needed) and backport.


----

Test result with NumPy 1.22.0rc1: https://ci.preferred.jp/cupy.linux.cuda-head/88054/

Output dtype must be `float32` instead of `float64` (ref #5583):

```
cupy_tests/linalg_tests/test_decomposition.py::TestQRDecomposition_param_1_{mode='raw'}::test_empty_array	
cupy_tests/linalg_tests/test_decomposition.py::TestQRDecomposition_param_1_{mode='raw'}::test_mode	
cupy_tests/linalg_tests/test_decomposition.py::TestQRDecomposition_param_1_{mode='raw'}::test_mode_rank3	
cupy_tests/linalg_tests/test_decomposition.py::TestQRDecomposition_param_1_{mode='raw'}::test_mode_rank4	
```

Add `method` option (`interpolation` deprecated) in `quantile` and `percentile`:

```
cupy_tests/statistics_tests/test_order.py::TestPercentileMonotonic_param_0_{magic_value=-29}::test_percentile_monotonic	
cupy_tests/statistics_tests/test_order.py::TestPercentileMonotonic_param_1_{magic_value=-53}::test_percentile_monotonic	
cupy_tests/statistics_tests/test_order.py::TestPercentileMonotonic_param_2_{magic_value=-207}::test_percentile_monotonic	
cupy_tests/statistics_tests/test_order.py::TestPercentileMonotonic_param_3_{magic_value=-16373}::test_percentile_monotonic	
cupy_tests/statistics_tests/test_order.py::TestPercentileMonotonic_param_4_{magic_value=-99999}::test_percentile_monotonic	
cupy_tests/statistics_tests/test_order.py::TestOrder::test_percentile_bad_q	
cupy_tests/statistics_tests/test_order.py::TestOrder::test_percentile_defaults	
cupy_tests/statistics_tests/test_order.py::TestOrder::test_percentile_keepdims	
cupy_tests/statistics_tests/test_order.py::TestOrder::test_percentile_neg_axis	
cupy_tests/statistics_tests/test_order.py::TestOrder::test_percentile_no_axis	
cupy_tests/statistics_tests/test_order.py::TestOrder::test_percentile_out	
cupy_tests/statistics_tests/test_order.py::TestOrder::test_percentile_out_of_range_q	
cupy_tests/statistics_tests/test_order.py::TestOrder::test_percentile_q_list	
cupy_tests/statistics_tests/test_order.py::TestOrder::test_percentile_scalar_q	
cupy_tests/statistics_tests/test_order.py::TestOrder::test_percentile_tuple_axis	
cupy_tests/statistics_tests/test_order.py::TestOrder::test_percentile_unexpected_interpolation	
cupy_tests/statistics_tests/test_order.py::TestOrder::test_quantile_bad_q	
cupy_tests/statistics_tests/test_order.py::TestOrder::test_quantile_defaults	
cupy_tests/statistics_tests/test_order.py::TestOrder::test_quantile_keepdims	
cupy_tests/statistics_tests/test_order.py::TestOrder::test_quantile_neg_axis	
cupy_tests/statistics_tests/test_order.py::TestOrder::test_quantile_no_axis	
cupy_tests/statistics_tests/test_order.py::TestOrder::test_quantile_out	
cupy_tests/statistics_tests/test_order.py::TestOrder::test_quantile_out_of_range_q	
cupy_tests/statistics_tests/test_order.py::TestOrder::test_quantile_q_list	
cupy_tests/statistics_tests/test_order.py::TestOrder::test_quantile_scalar_q	
cupy_tests/statistics_tests/test_order.py::TestOrder::test_quantile_tuple_axis	
cupy_tests/statistics_tests/test_order.py::TestOrder::test_quantile_unexpected_interpolation	
```



Discussion:

Resolving patch:
diff --git a/cupy/linalg/_decomposition.py b/cupy/linalg/_decomposition.py
--- a/cupy/linalg/_decomposition.py
+++ b/cupy/linalg/_decomposition.py
@@ -226,9 +226,6 @@ def _qr_batched(a, mode):
     if batch_size == 0 or m == 0 or n == 0:
         # support float32, float64, complex64, and complex128
         dtype, out_dtype = _util.linalg_common_type(a)
-        if mode == 'raw':
-            # compatibility with numpy.linalg.qr
-            out_dtype = numpy.promote_types(out_dtype, 'd')
 
         if mode == 'reduced':
             return (cupy.empty(batch_shape + (m, 0), out_dtype),
@@ -251,7 +248,7 @@ def _qr_batched(a, mode):
     q, r = out
     q = q.reshape(batch_shape + q.shape[-2:])
     idx = -1 if mode == 'raw' else -2
-    r.reshape(batch_shape + r.shape[idx:])
+    r = r.reshape(batch_shape + r.shape[idx:])
     return (q, r)
 
 
@@ -298,9 +295,6 @@ def qr(a, mode='reduced'):
 
     # support float32, float64, complex64, and complex128
     dtype, out_dtype = _util.linalg_common_type(a)
-    if mode == 'raw':
-        # compatibility with numpy.linalg.qr
-        out_dtype = numpy.promote_types(out_dtype, 'd')
 
     m, n = a.shape
     mn = min(m, n)


Test patch:
diff --git a/tests/cupy_tests/linalg_tests/test_decomposition.py b/tests/cupy_tests/linalg_tests/test_decomposition.py
--- a/tests/cupy_tests/linalg_tests/test_decomposition.py
+++ b/tests/cupy_tests/linalg_tests/test_decomposition.py
@@ -127,14 +127,23 @@ def check_mode(self, array, mode, dtype, batched=False):
         a_gpu = cupy.asarray(array, dtype=dtype)
         result_gpu = cupy.linalg.qr(a_gpu, mode=mode)
 
-        if ((not batched)
-                or (numpy.lib.NumpyVersion(numpy.__version__) >= '1.22.0')):
+        if numpy.lib.NumpyVersion(numpy.__version__) >= '1.22.0rc1':
             result_cpu = numpy.linalg.qr(a_cpu, mode=mode)
             self._check_result(result_cpu, result_gpu)
+            return
+
+        # We still want to test it to gain confidence...
+        # TODO(leofang): Use @testing.with_requires('numpy>=1.22') once
+        # NumPy 1.22 is out, and clean up this helper function
+        if not batched:
+            result_cpu = numpy.linalg.qr(a_cpu, mode=mode)
+            if mode == 'raw':
+                if dtype is numpy.float32:
+                    result_gpu = tuple(x.astype('d') for x in result_gpu)
+                elif dtype is numpy.complex64:
+                    result_gpu = tuple(x.astype('D') for x in result_gpu)
+            self._check_result(result_cpu, result_gpu)
         else:
-            # We still want to test it to gain confidence...
-            # TODO(leofang): Use @testing.with_requires('numpy>=1.22') once
-            # NumPy 1.22 is out, and clean up this helper function
             batch_shape = a_cpu.shape[:-2]
             batch_size = prod(batch_shape)
             a_cpu = a_cpu.reshape(batch_size, *a_cpu.shape[-2:])
@@ -146,10 +155,20 @@ def check_mode(self, array, mode, dtype, batched=False):
                     idx = -1 if mode == 'raw' else -2
                     r_gpu = r_gpu.reshape(batch_size, *r_gpu.shape[idx:])
                     res_gpu = (q_gpu[i], r_gpu[i])
+                    if mode == 'raw':
+                        if dtype is numpy.float32:
+                            res_gpu = tuple(x.astype('d') for x in res_gpu)
+                        elif dtype is numpy.complex64:
+                            res_gpu = tuple(x.astype('D') for x in res_gpu)
                     self._check_result(res_cpu, res_gpu)
                 else:  # mode == 'r'
                     res_gpu = result_gpu.reshape(
                         batch_size, *result_gpu.shape[-2:])[i]
+                    if mode == 'raw':
+                        if dtype is numpy.float32:
+                            res_gpu = res_gpu.astype('d')
+                        elif dtype is numpy.complex64:
+                            res_gpu = res_gpu.astype('D')
                     self._check_result(res_cpu, res_gpu)
 
     def _check_result(self, result_cpu, result_gpu):