Skip to content

Commit 3a801d3

Browse files
ev-brkgryte
andauthored
feat: add eig and eigvals to the linalg extension
PR-URL: #978 Closes: #935 Co-authored-by: Athan Reines <[email protected]> Reviewed-by: Athan Reines <[email protected]> Reviewed-by: Ralf Gommers <[email protected]> Reviewed-by: Sebastian Berg
1 parent eeaa9fa commit 3a801d3

File tree

1 file changed

+110
-8
lines changed

1 file changed

+110
-8
lines changed

src/array_api_stubs/_draft/linalg.py

Lines changed: 110 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -187,9 +187,6 @@ def eigh(x: array, /) -> Tuple[array, array]:
187187
.. note::
188188
Whether an array library explicitly checks whether an input array is Hermitian or a symmetric matrix (or a stack of matrices) is implementation-defined.
189189
190-
.. note::
191-
The function ``eig`` will be added in a future version of the specification.
192-
193190
Parameters
194191
----------
195192
x: array
@@ -201,7 +198,7 @@ def eigh(x: array, /) -> Tuple[array, array]:
201198
a namedtuple (``eigenvalues``, ``eigenvectors``) whose
202199
203200
- first element must have the field name ``eigenvalues`` (corresponding to :math:`\operatorname{diag}\Lambda` above) and must be an array consisting of computed eigenvalues. The array containing the eigenvalues must have shape ``(..., M)`` and must have a real-valued floating-point data type whose precision matches the precision of ``x`` (e.g., if ``x`` is ``complex128``, then ``eigenvalues`` must be ``float64``).
204-
- second element have have the field name ``eigenvectors`` (corresponding to :math:`Q` above) and must be an array where the columns of the inner most matrices contain the computed eigenvectors. These matrices must be orthogonal. The array containing the eigenvectors must have shape ``(..., M, M)`` and must have the same data type as ``x``.
201+
- second element must have the field name ``eigenvectors`` (corresponding to :math:`Q` above) and must be an array where the columns of the inner most matrices contain the computed eigenvectors. These matrices must be orthogonal. The array containing the eigenvectors must have shape ``(..., M, M)`` and must have the same data type as ``x``.
205202
206203
Notes
207204
-----
@@ -227,15 +224,12 @@ def eigvalsh(x: array, /) -> array:
227224
228225
where :math:`\lambda \in \mathbb{R}` and where :math:`I_n` is the *n*-dimensional identity matrix.
229226
230-
.. note:;
227+
.. note::
231228
The eigenvalues of a complex Hermitian or real symmetric matrix are always real.
232229
233230
.. note::
234231
Whether an array library explicitly checks whether an input array is Hermitian or a symmetric matrix (or a stack of matrices) is implementation-defined.
235232
236-
.. note::
237-
The function ``eigvals`` will be added in a future version of the specification.
238-
239233
Parameters
240234
----------
241235
x: array
@@ -257,6 +251,114 @@ def eigvalsh(x: array, /) -> array:
257251
"""
258252

259253

254+
def eig(x: array, /) -> Tuple[array, array]:
255+
r"""
256+
Returns eigenvalues and eigenvectors of a real or complex matrix (or stack of matrices) ``x``.
257+
258+
Let :math:`\mathbb{K}` be the union of the set of real numbers :math:`\mathbb{R}`
259+
and the set of complex numbers, :math:`\mathbb{C}`.
260+
261+
A real or complex value :math:`lambda \in \mathbb{K}` is an **eigenvalue** of a real
262+
or complex matrix :math:`x \in \mathbb{K}^{n \times n}` if there exists a real or complex vector
263+
:math:`v \in \mathbb{K}^{n}`, such that
264+
265+
.. math::
266+
267+
x v = \lambda v
268+
269+
Then, :math:`v` is referred to as an **eigenvector** of :math:`x`, corresponding to
270+
the eigenvalue :math:`\lambda`.
271+
272+
A general matrix :math:`x \in \mathbb{K}^{n \times n}`
273+
274+
- has :math:`n` eigenvalues, which are defined as the roots (counted with multiplicity) of the
275+
polynomial :math:`p` of degree :math:`n` given by
276+
277+
.. math::
278+
279+
p(\lambda) = \operatorname{det}(x - \lambda I_n)
280+
281+
- does not in general have :math:`n` linearly independent eigenvectors if it has
282+
eigenvalues with multiplicity larger than one.
283+
284+
.. note::
285+
The eigenvalues of a non-symmetric real matrix are in general complex: for
286+
:math:x \in \mathbb{R}^{n \times n}`, the eigenvalues, :math:`\lambda \in \mathbb{C}`,
287+
may or may not reside on the real axis of the complex plane.
288+
289+
.. warning::
290+
The eigenvectors of a general matrix are not unique and are not continuous with respect to ``x``. Because eigenvectors are not unique, different hardware and software may compute different eigenvectors.
291+
292+
For eigenvalues of multiplity :math:`s=1`, the non-uniqueness stems from the fact that multiplying an eigenvector by :math:`-1` when ``x`` is real-valued and by :math:`e^{\phi j}` (:math:`\phi \in \mathbb{R}`) when ``x`` is complex produces another set of valid eigenvectors.
293+
294+
For eigenvalues of multiplity :math:`s > 1`, the :math:`s` computed eigenvectors may be repeated or
295+
have entries differ by an order of machine epsilon for the data type of :math:`x`.
296+
297+
Parameters
298+
----------
299+
x: array
300+
input array having shape ``(..., M, M)`` and whose innermost two dimensions form square matrices. Should have a floating-point data type.
301+
302+
Returns
303+
-------
304+
out: Tuple[array, array]
305+
a namedtuple (``eigenvalues``, ``eigenvectors``) whose
306+
307+
- first element must have the field name ``eigenvalues`` (corresponding to :math:`\lambda` above) and must be an array consisting of computed eigenvalues. The array containing the eigenvalues must have shape ``(..., M)`` and must have a complex floating-point array data type having the same precision as that of ``x`` (e.g., if ``x`` has a ``float32`` data type, ``eigenvalues`` must have the ``complex64`` data type; if ``x`` has a ``float64`` data type, ``eigenvalues`` have the ``complex128`` data type).
308+
309+
- second element must have the field name ``eigenvectors`` (corresponding to :math:`v` above) and must be an array where the columns of the inner most matrices contain the computed eigenvectors. These matrices must be orthogonal. The array containing the eigenvectors must have shape ``(..., M, M)`` and must have the same data type as ``eigenvalues``.
310+
311+
Notes
312+
-----
313+
314+
- Eigenvalue sort order is left unspecified and is thus implementation-dependent.
315+
316+
.. note::
317+
For real symmetric or complex Hermitian matrices, prefer using the ``eigh`` routine.
318+
319+
.. versionadded:: 2025.12
320+
"""
321+
322+
323+
def eigvals(x: array, /) -> array:
324+
r"""
325+
Returns the eigenvalues of a real or complex matrix (or a stack of matrices) ``x``.
326+
327+
If ``x`` is real-valued, let :math:`\mathbb{K}` be the union of the set of real numbers :math:`\mathbb{R}`
328+
and the set of complex numbers, :math:`\mathbb{C}`; if ``x`` is complex-valued, let :math:`\mathbb{K}` be the set of complex numbers :math:`\mathbb{C}`.
329+
330+
The **eigenvalues** of a real or complex matrix :math:`x \in\ \mathbb{K}^{n \times n}` are defined as the roots (counted with multiplicity) of the polynomial :math:`p` of degree :math:`n` given by
331+
332+
.. math::
333+
p(\lambda) = \operatorname{det}(x - \lambda I_n)
334+
335+
where :math:`\lambda \in \mathbb{K}` and where :math:`I_n` is the *n*-dimensional identity matrix.
336+
337+
.. note::
338+
The eigenvalues of a non-symmetric real matrix are in general complex: for
339+
:math:x \in \mathbb{R}^{n \times n}`, the eigenvalues :math:`\lambda \in \mathbb{C}`,
340+
may or may not reside on the real axis of the complex plane.
341+
342+
343+
Parameters
344+
----------
345+
x: array
346+
input array having shape ``(..., M, M)`` and whose innermost two dimensions form square matrices. Should have a floating-point data type.
347+
348+
Returns
349+
-------
350+
out: array
351+
an array containing the computed eigenvalues. The returned array must have shape ``(..., M)`` and have a complex floating-point array data type having the same precision as that of ``x`` (e.g., if ``x`` has a ``float32`` data type, the array must have the ``complex64`` data type; if ``x`` has a ``float64`` data type, the array has the ``complex128`` data type).
352+
353+
Notes
354+
-----
355+
356+
- Eigenvalue sort order is left unspecified and is thus implementation-dependent.
357+
358+
.. versionadded:: 2025.12
359+
"""
360+
361+
260362
def inv(x: array, /) -> array:
261363
r"""
262364
Returns the multiplicative inverse of a square matrix (or a stack of square matrices) ``x``.

0 commit comments

Comments
 (0)