We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Got ValueError when `ord` in `cupy.linalg.norm()` is 2 or -2
Reproducer:
```python
>>> import numpy as np
>>> a  = [[2, 0, 1], [-1, 1, 0], [-3, 3, 0]]
>>> a = np.asarray(a, dtype=np.float64)
>>> np.linalg.norm(a, ord=2)
4.723421263784789
>>>
>>> import cupy as cp
>>> b = cp.asarray(a)
>>> cp.linalg.norm(b, ord=2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/leofang/test/cupy2/cupy/linalg/norms.py", line 124, in norm
    raise ValueError('Invalid norm order for matrices.')
ValueError: Invalid norm order for matrices.
```
`ord=2` returns the largest singular value and `-2` the smallest. 

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `cupy/linalg/norms.py`
Content:
```
1 import numpy
2 from numpy import linalg
3 
4 import cupy
5 from cupy.linalg import decomposition
6 from cupy.linalg import util
7 
8 
9 def norm(x, ord=None, axis=None, keepdims=False):
10     """Returns one of matrix norms specified by ``ord`` parameter.
11 
12     See numpy.linalg.norm for more detail.
13 
14     Args:
15         x (cupy.ndarray): Array to take norm. If ``axis`` is None,
16             ``x`` must be 1-D or 2-D.
17         ord (non-zero int, inf, -inf, 'fro'): Norm type.
18         axis (int, 2-tuple of ints, None): 1-D or 2-D norm is cumputed over
19             ``axis``.
20         keepdims (bool): If this is set ``True``, the axes which are normed
21             over are left.
22 
23     Returns:
24         cupy.ndarray
25 
26     """
27     if not issubclass(x.dtype.type, numpy.inexact):
28         x = x.astype(float)
29 
30     # Immediately handle some default, simple, fast, and common cases.
31     if axis is None:
32         ndim = x.ndim
33         if (ord is None or (ndim == 1 and ord == 2) or
34                 (ndim == 2 and ord in ('f', 'fro'))):
35             if x.dtype.kind == 'c':
36                 s = abs(x.ravel())
37                 s *= s
38                 ret = cupy.sqrt(s.sum())
39             else:
40                 ret = cupy.sqrt((x * x).sum())
41             if keepdims:
42                 ret = ret.reshape((1,) * ndim)
43             return ret
44 
45     # Normalize the `axis` argument to a tuple.
46     nd = x.ndim
47     if axis is None:
48         axis = tuple(range(nd))
49     elif not isinstance(axis, tuple):
50         try:
51             axis = int(axis)
52         except Exception:
53             raise TypeError(
54                 '\'axis\' must be None, an integer or a tuple of integers')
55         axis = (axis,)
56 
57     if len(axis) == 1:
58         if ord == numpy.Inf:
59             return abs(x).max(axis=axis, keepdims=keepdims)
60         elif ord == -numpy.Inf:
61             return abs(x).min(axis=axis, keepdims=keepdims)
62         elif ord == 0:
63             # Zero norm
64             # Convert to Python float in accordance with NumPy
65             return (x != 0).astype(x.real.dtype).sum(
66                 axis=axis, keepdims=keepdims)
67         elif ord == 1:
68             # special case for speedup
69             return abs(x).sum(axis=axis, keepdims=keepdims)
70         elif ord is None or ord == 2:
71             # special case for speedup
72             if x.dtype.kind == 'c':
73                 s = abs(x)
74                 s *= s
75             else:
76                 s = x * x
77             return cupy.sqrt(s.sum(axis=axis, keepdims=keepdims))
78         else:
79             try:
80                 float(ord)
81             except TypeError:
82                 raise ValueError('Invalid norm order for vectors.')
83 
84             absx = abs(x)
85             absx **= ord
86             ret = absx.sum(axis=axis, keepdims=keepdims)
87             ret **= cupy.reciprocal(ord, dtype=ret.dtype)
88             return ret
89     elif len(axis) == 2:
90         row_axis, col_axis = axis
91         if row_axis < 0:
92             row_axis += nd
93         if col_axis < 0:
94             col_axis += nd
95         if not (0 <= row_axis < nd and 0 <= col_axis < nd):
96             raise ValueError('Invalid axis %r for an array with shape %r' %
97                              (axis, x.shape))
98         if row_axis == col_axis:
99             raise ValueError('Duplicate axes given.')
100         if ord == 1:
101             if col_axis > row_axis:
102                 col_axis -= 1
103             ret = abs(x).sum(axis=row_axis).max(axis=col_axis)
104         elif ord == numpy.Inf:
105             if row_axis > col_axis:
106                 row_axis -= 1
107             ret = abs(x).sum(axis=col_axis).max(axis=row_axis)
108         elif ord == -1:
109             if col_axis > row_axis:
110                 col_axis -= 1
111             ret = abs(x).sum(axis=row_axis).min(axis=col_axis)
112         elif ord == -numpy.Inf:
113             if row_axis > col_axis:
114                 row_axis -= 1
115             ret = abs(x).sum(axis=col_axis).min(axis=row_axis)
116         elif ord in [None, 'fro', 'f']:
117             if x.dtype.kind == 'c':
118                 s = abs(x)
119                 s *= s
120                 ret = cupy.sqrt(s.sum(axis=axis))
121             else:
122                 ret = cupy.sqrt((x * x).sum(axis=axis))
123         else:
124             raise ValueError('Invalid norm order for matrices.')
125         if keepdims:
126             ret_shape = list(x.shape)
127             ret_shape[axis[0]] = 1
128             ret_shape[axis[1]] = 1
129             ret = ret.reshape(ret_shape)
130         return ret
131     else:
132         raise ValueError('Improper number of dimensions to norm.')
133 
134 
135 # TODO(okuta): Implement cond
136 
137 
138 def det(a):
139     """Retruns the deteminant of an array.
140 
141     Args:
142         a (cupy.ndarray): The input matrix with dimension ``(..., N, N)``.
143 
144     Returns:
145         cupy.ndarray: Determinant of ``a``. Its shape is ``a.shape[:-2]``.
146 
147     .. seealso:: :func:`numpy.linalg.det`
148     """
149     sign, logdet = slogdet(a)
150     return sign * cupy.exp(logdet)
151 
152 
153 def matrix_rank(M, tol=None):
154     """Return matrix rank of array using SVD method
155 
156     Args:
157         M (cupy.ndarray): Input array. Its `ndim` must be less than or equal to
158             2.
159         tol (None or float): Threshold of singular value of `M`.
160             When `tol` is `None`, and `eps` is the epsilon value for datatype
161             of `M`, then `tol` is set to `S.max() * max(M.shape) * eps`,
162             where `S` is the singular value of `M`.
163             It obeys :func:`numpy.linalg.matrix_rank`.
164 
165     Returns:
166         cupy.ndarray: Rank of `M`.
167 
168     .. seealso:: :func:`numpy.linalg.matrix_rank`
169     """
170     if M.ndim < 2:
171         return (M != 0).any().astype(int)
172     S = decomposition.svd(M, compute_uv=False)
173     if tol is None:
174         tol = (S.max(axis=-1, keepdims=True) * max(M.shape[-2:]) *
175                numpy.finfo(S.dtype).eps)
176     return (S > tol).sum(axis=-1, dtype=numpy.intp)
177 
178 
179 def slogdet(a):
180     """Returns sign and logarithm of the determinant of an array.
181 
182     It calculates the natural logarithm of the determinant of a given value.
183 
184     Args:
185         a (cupy.ndarray): The input matrix with dimension ``(..., N, N)``.
186 
187     Returns:
188         tuple of :class:`~cupy.ndarray`:
189             It returns a tuple ``(sign, logdet)``. ``sign`` represents each
190             sign of the determinant as a real number ``0``, ``1`` or ``-1``.
191             'logdet' represents the natural logarithm of the absolute of the
192             determinant.
193             If the determinant is zero, ``sign`` will be ``0`` and ``logdet``
194             will be ``-inf``.
195             The shapes of both ``sign`` and ``logdet`` are equal to
196             ``a.shape[:-2]``.
197 
198     .. warning::
199         This function calls one or more cuSOLVER routine(s) which may yield
200         invalid results if input conditions are not met.
201         To detect these invalid results, you can set the `linalg`
202         configuration to a value that is not `ignore` in
203         :func:`cupyx.errstate` or :func:`cupyx.seterr`.
204 
205     .. warning::
206         To produce the same results as :func:`numpy.linalg.slogdet` for
207         singular inputs, set the `linalg` configuration to `raise`.
208 
209     .. seealso:: :func:`numpy.linalg.slogdet`
210     """
211     if a.ndim < 2:
212         msg = ('%d-dimensional array given. '
213                'Array must be at least two-dimensional' % a.ndim)
214         raise linalg.LinAlgError(msg)
215     util._assert_nd_squareness(a)
216 
217     dtype = numpy.promote_types(a.dtype.char, 'f')
218     real_dtype = dtype
219 
220     # TODO(kataoka): support complex types
221     if dtype not in (numpy.float32, numpy.float64):
222         msg = ('dtype must be float32 or float64'
223                ' (actual: {})'.format(a.dtype))
224         raise ValueError(msg)
225 
226     a_shape = a.shape
227     shape = a_shape[:-2]
228     n = a_shape[-2]
229 
230     if a.size == 0:
231         # empty batch (result is empty, too) or empty matrices det([[]]) == 1
232         sign = cupy.ones(shape, dtype)
233         logdet = cupy.zeros(shape, real_dtype)
234         return sign, logdet
235 
236     lu, ipiv, dev_info = decomposition._lu_factor(a, dtype)
237 
238     # dev_info < 0 means illegal value (in dimensions, strides, and etc.) that
239     # should never happen even if the matrix contains nan or inf.
240     # TODO(kataoka): assert dev_info >= 0 if synchronization is allowed for
241     # debugging purposes.
242 
243     diag = cupy.diagonal(lu, axis1=-2, axis2=-1)
244 
245     # ipiv is 1-origin
246     non_zero = (cupy.count_nonzero(ipiv != cupy.arange(1, n + 1), axis=-1) +
247                 cupy.count_nonzero(diag < 0, axis=-1))
248 
249     # Note: sign == -1 ** (non_zero % 2)
250     sign = (non_zero % 2) * -2 + 1
251     logdet = cupy.log(abs(diag)).sum(axis=-1)
252 
253     singular = dev_info > 0
254     return (
255         cupy.where(singular, dtype.type(0), sign.astype(dtype)).reshape(shape),
256         cupy.where(singular, real_dtype.type('-inf'), logdet).reshape(shape),
257     )
258 
259 
260 def trace(a, offset=0, axis1=0, axis2=1, dtype=None, out=None):
261     """Returns the sum along the diagonals of an array.
262 
263     It computes the sum along the diagonals at ``axis1`` and ``axis2``.
264 
265     Args:
266         a (cupy.ndarray): Array to take trace.
267         offset (int): Index of diagonals. Zero indicates the main diagonal, a
268             positive value an upper diagonal, and a negative value a lower
269             diagonal.
270         axis1 (int): The first axis along which the trace is taken.
271         axis2 (int): The second axis along which the trace is taken.
272         dtype: Data type specifier of the output.
273         out (cupy.ndarray): Output array.
274 
275     Returns:
276         cupy.ndarray: The trace of ``a`` along axes ``(axis1, axis2)``.
277 
278     .. seealso:: :func:`numpy.trace`
279 
280     """
281     # TODO(okuta): check type
282     return a.trace(offset, axis1, axis2, dtype, out)
283
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/cupy/linalg/norms.py b/cupy/linalg/norms.py
--- a/cupy/linalg/norms.py
+++ b/cupy/linalg/norms.py
@@ -5,6 +5,14 @@
 from cupy.linalg import decomposition
 from cupy.linalg import util
 
+import functools
+
+
+def _multi_svd_norm(x, row_axis, col_axis, op):
+    y = cupy.moveaxis(x, (row_axis, col_axis), (-2, -1))
+    result = op(decomposition.svd(y, compute_uv=False), axis=-1)
+    return result
+
 
 def norm(x, ord=None, axis=None, keepdims=False):
     """Returns one of matrix norms specified by ``ord`` parameter.
@@ -97,7 +105,13 @@
                              (axis, x.shape))
         if row_axis == col_axis:
             raise ValueError('Duplicate axes given.')
-        if ord == 1:
+        if ord == 2:
+            op_max = functools.partial(cupy.take, indices=0)
+            ret = _multi_svd_norm(x, row_axis, col_axis, op_max)
+        elif ord == -2:
+            op_min = functools.partial(cupy.take, indices=-1)
+            ret = _multi_svd_norm(x, row_axis, col_axis, op_min)
+        elif ord == 1:
             if col_axis > row_axis:
                 col_axis -= 1
             ret = abs(x).sum(axis=row_axis).max(axis=col_axis)
@@ -120,6 +134,8 @@
                 ret = cupy.sqrt(s.sum(axis=axis))
             else:
                 ret = cupy.sqrt((x * x).sum(axis=axis))
+        elif ord == 'nuc':
+            ret = _multi_svd_norm(x, row_axis, col_axis, cupy.sum)
         else:
             raise ValueError('Invalid norm order for matrices.')
         if keepdims:

{"golden_diff": "diff --git a/cupy/linalg/norms.py b/cupy/linalg/norms.py\n--- a/cupy/linalg/norms.py\n+++ b/cupy/linalg/norms.py\n@@ -5,6 +5,14 @@\n from cupy.linalg import decomposition\n from cupy.linalg import util\n \n+import functools\n+\n+\n+def _multi_svd_norm(x, row_axis, col_axis, op):\n+    y = cupy.moveaxis(x, (row_axis, col_axis), (-2, -1))\n+    result = op(decomposition.svd(y, compute_uv=False), axis=-1)\n+    return result\n+\n \n def norm(x, ord=None, axis=None, keepdims=False):\n     \"\"\"Returns one of matrix norms specified by ``ord`` parameter.\n@@ -97,7 +105,13 @@\n                              (axis, x.shape))\n         if row_axis == col_axis:\n             raise ValueError('Duplicate axes given.')\n-        if ord == 1:\n+        if ord == 2:\n+            op_max = functools.partial(cupy.take, indices=0)\n+            ret = _multi_svd_norm(x, row_axis, col_axis, op_max)\n+        elif ord == -2:\n+            op_min = functools.partial(cupy.take, indices=-1)\n+            ret = _multi_svd_norm(x, row_axis, col_axis, op_min)\n+        elif ord == 1:\n             if col_axis > row_axis:\n                 col_axis -= 1\n             ret = abs(x).sum(axis=row_axis).max(axis=col_axis)\n@@ -120,6 +134,8 @@\n                 ret = cupy.sqrt(s.sum(axis=axis))\n             else:\n                 ret = cupy.sqrt((x * x).sum(axis=axis))\n+        elif ord == 'nuc':\n+            ret = _multi_svd_norm(x, row_axis, col_axis, cupy.sum)\n         else:\n             raise ValueError('Invalid norm order for matrices.')\n         if keepdims:\n", "issue": "Got ValueError when `ord` in `cupy.linalg.norm()` is 2 or -2\nReproducer:\r\n```python\r\n>>> import numpy as np\r\n>>> a  = [[2, 0, 1], [-1, 1, 0], [-3, 3, 0]]\r\n>>> a = np.asarray(a, dtype=np.float64)\r\n>>> np.linalg.norm(a, ord=2)\r\n4.723421263784789\r\n>>>\r\n>>> import cupy as cp\r\n>>> b = cp.asarray(a)\r\n>>> cp.linalg.norm(b, ord=2)\r\nTraceback (most recent call last):\r\n  File \"<stdin>\", line 1, in <module>\r\n  File \"/home/leofang/test/cupy2/cupy/linalg/norms.py\", line 124, in norm\r\n    raise ValueError('Invalid norm order for matrices.')\r\nValueError: Invalid norm order for matrices.\r\n```\r\n`ord=2` returns the largest singular value and `-2` the smallest. \n", "before_files": [{"content": "import numpy\nfrom numpy import linalg\n\nimport cupy\nfrom cupy.linalg import decomposition\nfrom cupy.linalg import util\n\n\ndef norm(x, ord=None, axis=None, keepdims=False):\n    \"\"\"Returns one of matrix norms specified by ``ord`` parameter.\n\n    See numpy.linalg.norm for more detail.\n\n    Args:\n        x (cupy.ndarray): Array to take norm. If ``axis`` is None,\n            ``x`` must be 1-D or 2-D.\n        ord (non-zero int, inf, -inf, 'fro'): Norm type.\n        axis (int, 2-tuple of ints, None): 1-D or 2-D norm is cumputed over\n            ``axis``.\n        keepdims (bool): If this is set ``True``, the axes which are normed\n            over are left.\n\n    Returns:\n        cupy.ndarray\n\n    \"\"\"\n    if not issubclass(x.dtype.type, numpy.inexact):\n        x = x.astype(float)\n\n    # Immediately handle some default, simple, fast, and common cases.\n    if axis is None:\n        ndim = x.ndim\n        if (ord is None or (ndim == 1 and ord == 2) or\n                (ndim == 2 and ord in ('f', 'fro'))):\n            if x.dtype.kind == 'c':\n                s = abs(x.ravel())\n                s *= s\n                ret = cupy.sqrt(s.sum())\n            else:\n                ret = cupy.sqrt((x * x).sum())\n            if keepdims:\n                ret = ret.reshape((1,) * ndim)\n            return ret\n\n    # Normalize the `axis` argument to a tuple.\n    nd = x.ndim\n    if axis is None:\n        axis = tuple(range(nd))\n    elif not isinstance(axis, tuple):\n        try:\n            axis = int(axis)\n        except Exception:\n            raise TypeError(\n                '\\'axis\\' must be None, an integer or a tuple of integers')\n        axis = (axis,)\n\n    if len(axis) == 1:\n        if ord == numpy.Inf:\n            return abs(x).max(axis=axis, keepdims=keepdims)\n        elif ord == -numpy.Inf:\n            return abs(x).min(axis=axis, keepdims=keepdims)\n        elif ord == 0:\n            # Zero norm\n            # Convert to Python float in accordance with NumPy\n            return (x != 0).astype(x.real.dtype).sum(\n                axis=axis, keepdims=keepdims)\n        elif ord == 1:\n            # special case for speedup\n            return abs(x).sum(axis=axis, keepdims=keepdims)\n        elif ord is None or ord == 2:\n            # special case for speedup\n            if x.dtype.kind == 'c':\n                s = abs(x)\n                s *= s\n            else:\n                s = x * x\n            return cupy.sqrt(s.sum(axis=axis, keepdims=keepdims))\n        else:\n            try:\n                float(ord)\n            except TypeError:\n                raise ValueError('Invalid norm order for vectors.')\n\n            absx = abs(x)\n            absx **= ord\n            ret = absx.sum(axis=axis, keepdims=keepdims)\n            ret **= cupy.reciprocal(ord, dtype=ret.dtype)\n            return ret\n    elif len(axis) == 2:\n        row_axis, col_axis = axis\n        if row_axis < 0:\n            row_axis += nd\n        if col_axis < 0:\n            col_axis += nd\n        if not (0 <= row_axis < nd and 0 <= col_axis < nd):\n            raise ValueError('Invalid axis %r for an array with shape %r' %\n                             (axis, x.shape))\n        if row_axis == col_axis:\n            raise ValueError('Duplicate axes given.')\n        if ord == 1:\n            if col_axis > row_axis:\n                col_axis -= 1\n            ret = abs(x).sum(axis=row_axis).max(axis=col_axis)\n        elif ord == numpy.Inf:\n            if row_axis > col_axis:\n                row_axis -= 1\n            ret = abs(x).sum(axis=col_axis).max(axis=row_axis)\n        elif ord == -1:\n            if col_axis > row_axis:\n                col_axis -= 1\n            ret = abs(x).sum(axis=row_axis).min(axis=col_axis)\n        elif ord == -numpy.Inf:\n            if row_axis > col_axis:\n                row_axis -= 1\n            ret = abs(x).sum(axis=col_axis).min(axis=row_axis)\n        elif ord in [None, 'fro', 'f']:\n            if x.dtype.kind == 'c':\n                s = abs(x)\n                s *= s\n                ret = cupy.sqrt(s.sum(axis=axis))\n            else:\n                ret = cupy.sqrt((x * x).sum(axis=axis))\n        else:\n            raise ValueError('Invalid norm order for matrices.')\n        if keepdims:\n            ret_shape = list(x.shape)\n            ret_shape[axis[0]] = 1\n            ret_shape[axis[1]] = 1\n            ret = ret.reshape(ret_shape)\n        return ret\n    else:\n        raise ValueError('Improper number of dimensions to norm.')\n\n\n# TODO(okuta): Implement cond\n\n\ndef det(a):\n    \"\"\"Retruns the deteminant of an array.\n\n    Args:\n        a (cupy.ndarray): The input matrix with dimension ``(..., N, N)``.\n\n    Returns:\n        cupy.ndarray: Determinant of ``a``. Its shape is ``a.shape[:-2]``.\n\n    .. seealso:: :func:`numpy.linalg.det`\n    \"\"\"\n    sign, logdet = slogdet(a)\n    return sign * cupy.exp(logdet)\n\n\ndef matrix_rank(M, tol=None):\n    \"\"\"Return matrix rank of array using SVD method\n\n    Args:\n        M (cupy.ndarray): Input array. Its `ndim` must be less than or equal to\n            2.\n        tol (None or float): Threshold of singular value of `M`.\n            When `tol` is `None`, and `eps` is the epsilon value for datatype\n            of `M`, then `tol` is set to `S.max() * max(M.shape) * eps`,\n            where `S` is the singular value of `M`.\n            It obeys :func:`numpy.linalg.matrix_rank`.\n\n    Returns:\n        cupy.ndarray: Rank of `M`.\n\n    .. seealso:: :func:`numpy.linalg.matrix_rank`\n    \"\"\"\n    if M.ndim < 2:\n        return (M != 0).any().astype(int)\n    S = decomposition.svd(M, compute_uv=False)\n    if tol is None:\n        tol = (S.max(axis=-1, keepdims=True) * max(M.shape[-2:]) *\n               numpy.finfo(S.dtype).eps)\n    return (S > tol).sum(axis=-1, dtype=numpy.intp)\n\n\ndef slogdet(a):\n    \"\"\"Returns sign and logarithm of the determinant of an array.\n\n    It calculates the natural logarithm of the determinant of a given value.\n\n    Args:\n        a (cupy.ndarray): The input matrix with dimension ``(..., N, N)``.\n\n    Returns:\n        tuple of :class:`~cupy.ndarray`:\n            It returns a tuple ``(sign, logdet)``. ``sign`` represents each\n            sign of the determinant as a real number ``0``, ``1`` or ``-1``.\n            'logdet' represents the natural logarithm of the absolute of the\n            determinant.\n            If the determinant is zero, ``sign`` will be ``0`` and ``logdet``\n            will be ``-inf``.\n            The shapes of both ``sign`` and ``logdet`` are equal to\n            ``a.shape[:-2]``.\n\n    .. warning::\n        This function calls one or more cuSOLVER routine(s) which may yield\n        invalid results if input conditions are not met.\n        To detect these invalid results, you can set the `linalg`\n        configuration to a value that is not `ignore` in\n        :func:`cupyx.errstate` or :func:`cupyx.seterr`.\n\n    .. warning::\n        To produce the same results as :func:`numpy.linalg.slogdet` for\n        singular inputs, set the `linalg` configuration to `raise`.\n\n    .. seealso:: :func:`numpy.linalg.slogdet`\n    \"\"\"\n    if a.ndim < 2:\n        msg = ('%d-dimensional array given. '\n               'Array must be at least two-dimensional' % a.ndim)\n        raise linalg.LinAlgError(msg)\n    util._assert_nd_squareness(a)\n\n    dtype = numpy.promote_types(a.dtype.char, 'f')\n    real_dtype = dtype\n\n    # TODO(kataoka): support complex types\n    if dtype not in (numpy.float32, numpy.float64):\n        msg = ('dtype must be float32 or float64'\n               ' (actual: {})'.format(a.dtype))\n        raise ValueError(msg)\n\n    a_shape = a.shape\n    shape = a_shape[:-2]\n    n = a_shape[-2]\n\n    if a.size == 0:\n        # empty batch (result is empty, too) or empty matrices det([[]]) == 1\n        sign = cupy.ones(shape, dtype)\n        logdet = cupy.zeros(shape, real_dtype)\n        return sign, logdet\n\n    lu, ipiv, dev_info = decomposition._lu_factor(a, dtype)\n\n    # dev_info < 0 means illegal value (in dimensions, strides, and etc.) that\n    # should never happen even if the matrix contains nan or inf.\n    # TODO(kataoka): assert dev_info >= 0 if synchronization is allowed for\n    # debugging purposes.\n\n    diag = cupy.diagonal(lu, axis1=-2, axis2=-1)\n\n    # ipiv is 1-origin\n    non_zero = (cupy.count_nonzero(ipiv != cupy.arange(1, n + 1), axis=-1) +\n                cupy.count_nonzero(diag < 0, axis=-1))\n\n    # Note: sign == -1 ** (non_zero % 2)\n    sign = (non_zero % 2) * -2 + 1\n    logdet = cupy.log(abs(diag)).sum(axis=-1)\n\n    singular = dev_info > 0\n    return (\n        cupy.where(singular, dtype.type(0), sign.astype(dtype)).reshape(shape),\n        cupy.where(singular, real_dtype.type('-inf'), logdet).reshape(shape),\n    )\n\n\ndef trace(a, offset=0, axis1=0, axis2=1, dtype=None, out=None):\n    \"\"\"Returns the sum along the diagonals of an array.\n\n    It computes the sum along the diagonals at ``axis1`` and ``axis2``.\n\n    Args:\n        a (cupy.ndarray): Array to take trace.\n        offset (int): Index of diagonals. Zero indicates the main diagonal, a\n            positive value an upper diagonal, and a negative value a lower\n            diagonal.\n        axis1 (int): The first axis along which the trace is taken.\n        axis2 (int): The second axis along which the trace is taken.\n        dtype: Data type specifier of the output.\n        out (cupy.ndarray): Output array.\n\n    Returns:\n        cupy.ndarray: The trace of ``a`` along axes ``(axis1, axis2)``.\n\n    .. seealso:: :func:`numpy.trace`\n\n    \"\"\"\n    # TODO(okuta): check type\n    return a.trace(offset, axis1, axis2, dtype, out)\n", "path": "cupy/linalg/norms.py"}], "after_files": [{"content": "import numpy\nfrom numpy import linalg\n\nimport cupy\nfrom cupy.linalg import decomposition\nfrom cupy.linalg import util\n\nimport functools\n\n\ndef _multi_svd_norm(x, row_axis, col_axis, op):\n    y = cupy.moveaxis(x, (row_axis, col_axis), (-2, -1))\n    result = op(decomposition.svd(y, compute_uv=False), axis=-1)\n    return result\n\n\ndef norm(x, ord=None, axis=None, keepdims=False):\n    \"\"\"Returns one of matrix norms specified by ``ord`` parameter.\n\n    See numpy.linalg.norm for more detail.\n\n    Args:\n        x (cupy.ndarray): Array to take norm. If ``axis`` is None,\n            ``x`` must be 1-D or 2-D.\n        ord (non-zero int, inf, -inf, 'fro'): Norm type.\n        axis (int, 2-tuple of ints, None): 1-D or 2-D norm is cumputed over\n            ``axis``.\n        keepdims (bool): If this is set ``True``, the axes which are normed\n            over are left.\n\n    Returns:\n        cupy.ndarray\n\n    \"\"\"\n    if not issubclass(x.dtype.type, numpy.inexact):\n        x = x.astype(float)\n\n    # Immediately handle some default, simple, fast, and common cases.\n    if axis is None:\n        ndim = x.ndim\n        if (ord is None or (ndim == 1 and ord == 2) or\n                (ndim == 2 and ord in ('f', 'fro'))):\n            if x.dtype.kind == 'c':\n                s = abs(x.ravel())\n                s *= s\n                ret = cupy.sqrt(s.sum())\n            else:\n                ret = cupy.sqrt((x * x).sum())\n            if keepdims:\n                ret = ret.reshape((1,) * ndim)\n            return ret\n\n    # Normalize the `axis` argument to a tuple.\n    nd = x.ndim\n    if axis is None:\n        axis = tuple(range(nd))\n    elif not isinstance(axis, tuple):\n        try:\n            axis = int(axis)\n        except Exception:\n            raise TypeError(\n                '\\'axis\\' must be None, an integer or a tuple of integers')\n        axis = (axis,)\n\n    if len(axis) == 1:\n        if ord == numpy.Inf:\n            return abs(x).max(axis=axis, keepdims=keepdims)\n        elif ord == -numpy.Inf:\n            return abs(x).min(axis=axis, keepdims=keepdims)\n        elif ord == 0:\n            # Zero norm\n            # Convert to Python float in accordance with NumPy\n            return (x != 0).astype(x.real.dtype).sum(\n                axis=axis, keepdims=keepdims)\n        elif ord == 1:\n            # special case for speedup\n            return abs(x).sum(axis=axis, keepdims=keepdims)\n        elif ord is None or ord == 2:\n            # special case for speedup\n            if x.dtype.kind == 'c':\n                s = abs(x)\n                s *= s\n            else:\n                s = x * x\n            return cupy.sqrt(s.sum(axis=axis, keepdims=keepdims))\n        else:\n            try:\n                float(ord)\n            except TypeError:\n                raise ValueError('Invalid norm order for vectors.')\n\n            absx = abs(x)\n            absx **= ord\n            ret = absx.sum(axis=axis, keepdims=keepdims)\n            ret **= cupy.reciprocal(ord, dtype=ret.dtype)\n            return ret\n    elif len(axis) == 2:\n        row_axis, col_axis = axis\n        if row_axis < 0:\n            row_axis += nd\n        if col_axis < 0:\n            col_axis += nd\n        if not (0 <= row_axis < nd and 0 <= col_axis < nd):\n            raise ValueError('Invalid axis %r for an array with shape %r' %\n                             (axis, x.shape))\n        if row_axis == col_axis:\n            raise ValueError('Duplicate axes given.')\n        if ord == 2:\n            op_max = functools.partial(cupy.take, indices=0)\n            ret = _multi_svd_norm(x, row_axis, col_axis, op_max)\n        elif ord == -2:\n            op_min = functools.partial(cupy.take, indices=-1)\n            ret = _multi_svd_norm(x, row_axis, col_axis, op_min)\n        elif ord == 1:\n            if col_axis > row_axis:\n                col_axis -= 1\n            ret = abs(x).sum(axis=row_axis).max(axis=col_axis)\n        elif ord == numpy.Inf:\n            if row_axis > col_axis:\n                row_axis -= 1\n            ret = abs(x).sum(axis=col_axis).max(axis=row_axis)\n        elif ord == -1:\n            if col_axis > row_axis:\n                col_axis -= 1\n            ret = abs(x).sum(axis=row_axis).min(axis=col_axis)\n        elif ord == -numpy.Inf:\n            if row_axis > col_axis:\n                row_axis -= 1\n            ret = abs(x).sum(axis=col_axis).min(axis=row_axis)\n        elif ord in [None, 'fro', 'f']:\n            if x.dtype.kind == 'c':\n                s = abs(x)\n                s *= s\n                ret = cupy.sqrt(s.sum(axis=axis))\n            else:\n                ret = cupy.sqrt((x * x).sum(axis=axis))\n        elif ord == 'nuc':\n            ret = _multi_svd_norm(x, row_axis, col_axis, cupy.sum)\n        else:\n            raise ValueError('Invalid norm order for matrices.')\n        if keepdims:\n            ret_shape = list(x.shape)\n            ret_shape[axis[0]] = 1\n            ret_shape[axis[1]] = 1\n            ret = ret.reshape(ret_shape)\n        return ret\n    else:\n        raise ValueError('Improper number of dimensions to norm.')\n\n\n# TODO(okuta): Implement cond\n\n\ndef det(a):\n    \"\"\"Retruns the deteminant of an array.\n\n    Args:\n        a (cupy.ndarray): The input matrix with dimension ``(..., N, N)``.\n\n    Returns:\n        cupy.ndarray: Determinant of ``a``. Its shape is ``a.shape[:-2]``.\n\n    .. seealso:: :func:`numpy.linalg.det`\n    \"\"\"\n    sign, logdet = slogdet(a)\n    return sign * cupy.exp(logdet)\n\n\ndef matrix_rank(M, tol=None):\n    \"\"\"Return matrix rank of array using SVD method\n\n    Args:\n        M (cupy.ndarray): Input array. Its `ndim` must be less than or equal to\n            2.\n        tol (None or float): Threshold of singular value of `M`.\n            When `tol` is `None`, and `eps` is the epsilon value for datatype\n            of `M`, then `tol` is set to `S.max() * max(M.shape) * eps`,\n            where `S` is the singular value of `M`.\n            It obeys :func:`numpy.linalg.matrix_rank`.\n\n    Returns:\n        cupy.ndarray: Rank of `M`.\n\n    .. seealso:: :func:`numpy.linalg.matrix_rank`\n    \"\"\"\n    if M.ndim < 2:\n        return (M != 0).any().astype(int)\n    S = decomposition.svd(M, compute_uv=False)\n    if tol is None:\n        tol = (S.max(axis=-1, keepdims=True) * max(M.shape[-2:]) *\n               numpy.finfo(S.dtype).eps)\n    return (S > tol).sum(axis=-1, dtype=numpy.intp)\n\n\ndef slogdet(a):\n    \"\"\"Returns sign and logarithm of the determinant of an array.\n\n    It calculates the natural logarithm of the determinant of a given value.\n\n    Args:\n        a (cupy.ndarray): The input matrix with dimension ``(..., N, N)``.\n\n    Returns:\n        tuple of :class:`~cupy.ndarray`:\n            It returns a tuple ``(sign, logdet)``. ``sign`` represents each\n            sign of the determinant as a real number ``0``, ``1`` or ``-1``.\n            'logdet' represents the natural logarithm of the absolute of the\n            determinant.\n            If the determinant is zero, ``sign`` will be ``0`` and ``logdet``\n            will be ``-inf``.\n            The shapes of both ``sign`` and ``logdet`` are equal to\n            ``a.shape[:-2]``.\n\n    .. warning::\n        This function calls one or more cuSOLVER routine(s) which may yield\n        invalid results if input conditions are not met.\n        To detect these invalid results, you can set the `linalg`\n        configuration to a value that is not `ignore` in\n        :func:`cupyx.errstate` or :func:`cupyx.seterr`.\n\n    .. warning::\n        To produce the same results as :func:`numpy.linalg.slogdet` for\n        singular inputs, set the `linalg` configuration to `raise`.\n\n    .. seealso:: :func:`numpy.linalg.slogdet`\n    \"\"\"\n    if a.ndim < 2:\n        msg = ('%d-dimensional array given. '\n               'Array must be at least two-dimensional' % a.ndim)\n        raise linalg.LinAlgError(msg)\n    util._assert_nd_squareness(a)\n\n    dtype = numpy.promote_types(a.dtype.char, 'f')\n    real_dtype = dtype\n\n    # TODO(kataoka): support complex types\n    if dtype not in (numpy.float32, numpy.float64):\n        msg = ('dtype must be float32 or float64'\n               ' (actual: {})'.format(a.dtype))\n        raise ValueError(msg)\n\n    a_shape = a.shape\n    shape = a_shape[:-2]\n    n = a_shape[-2]\n\n    if a.size == 0:\n        # empty batch (result is empty, too) or empty matrices det([[]]) == 1\n        sign = cupy.ones(shape, dtype)\n        logdet = cupy.zeros(shape, real_dtype)\n        return sign, logdet\n\n    lu, ipiv, dev_info = decomposition._lu_factor(a, dtype)\n\n    # dev_info < 0 means illegal value (in dimensions, strides, and etc.) that\n    # should never happen even if the matrix contains nan or inf.\n    # TODO(kataoka): assert dev_info >= 0 if synchronization is allowed for\n    # debugging purposes.\n\n    diag = cupy.diagonal(lu, axis1=-2, axis2=-1)\n\n    # ipiv is 1-origin\n    non_zero = (cupy.count_nonzero(ipiv != cupy.arange(1, n + 1), axis=-1) +\n                cupy.count_nonzero(diag < 0, axis=-1))\n\n    # Note: sign == -1 ** (non_zero % 2)\n    sign = (non_zero % 2) * -2 + 1\n    logdet = cupy.log(abs(diag)).sum(axis=-1)\n\n    singular = dev_info > 0\n    return (\n        cupy.where(singular, dtype.type(0), sign.astype(dtype)).reshape(shape),\n        cupy.where(singular, real_dtype.type('-inf'), logdet).reshape(shape),\n    )\n\n\ndef trace(a, offset=0, axis1=0, axis2=1, dtype=None, out=None):\n    \"\"\"Returns the sum along the diagonals of an array.\n\n    It computes the sum along the diagonals at ``axis1`` and ``axis2``.\n\n    Args:\n        a (cupy.ndarray): Array to take trace.\n        offset (int): Index of diagonals. Zero indicates the main diagonal, a\n            positive value an upper diagonal, and a negative value a lower\n            diagonal.\n        axis1 (int): The first axis along which the trace is taken.\n        axis2 (int): The second axis along which the trace is taken.\n        dtype: Data type specifier of the output.\n        out (cupy.ndarray): Output array.\n\n    Returns:\n        cupy.ndarray: The trace of ``a`` along axes ``(axis1, axis2)``.\n\n    .. seealso:: :func:`numpy.trace`\n\n    \"\"\"\n    # TODO(okuta): check type\n    return a.trace(offset, axis1, axis2, dtype, out)\n", "path": "cupy/linalg/norms.py"}]}