Skip to content

Commit 6011f96

Browse files
committed
ENH: add eig and eigvals to the linalg extension
1 parent 18315b9 commit 6011f96

File tree

1 file changed

+124
-8
lines changed

1 file changed

+124
-8
lines changed

src/array_api_stubs/_draft/linalg.py

Lines changed: 124 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 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,128 @@ 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 a stack of matrices) ``x``.
257+
258+
If ``x`` is real-valued, 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}`; if ``x`` is complex-valued, let :math:`\mathbb{K}`
260+
be the set of complex numbers :math:`\mathbb{C}`.
261+
262+
A real or complex value :math:`lambda \in \mathbb{K}` is an **eigenvalue** of a real
263+
or complex matrix :math:`x \in \mathbb{K}^{n \times n}` if there exist a real or complex vector
264+
:math:`v \in \mathbb{K}^{n}`, such that
265+
266+
.. math::
267+
268+
x v = \lambda v
269+
270+
Then, :math:`v` is referred to as an **eigenvector** of :math:`x`, corresponding to
271+
the eigenvalue :math:`\lambda`.
272+
273+
A general matrix :math:`x \in \mathbb{K}^{n \times n}`
274+
275+
- has :math:`n` eigenvectors, which are defined as the roots (counted with multiplicity) of the
276+
polynomial :math:`p` of degree :math:`n` given by
277+
278+
.. math::
279+
280+
p(\lambda) = \operatorname{det}(x - \lambda I_n)
281+
282+
- does not in general have :math:`n` linearly independent eigenvectors if it has
283+
eigenvalues with multiplicity larger than one.
284+
285+
.. note::
286+
The eigenvalues of a non-symmetric real matrix in general are complex: for
287+
:math:x \in \mathbb{R}^{n \times n}`, the eigenvalues, :math:`\lambda \in \mathbb{C}`,
288+
and may or may not reside on the real axis of the complex plane.
289+
290+
.. warning::
291+
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.
292+
293+
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.
294+
295+
For eigenvalues of multiplity :math:`s > 1`, the :math:`s` computed eigenvectors may be repeated or
296+
have entries differ by an order of machine epsilon for the data type of :math:`x`.
297+
298+
Parameters
299+
----------
300+
x: array
301+
input array having shape ``(..., M, M)`` and whose innermost two dimensions form square matrices. Should have a floating-point data type.
302+
303+
Returns
304+
-------
305+
out: Tuple[array, array]
306+
a namedtuple (``eigenvalues``, ``eigenvectors``) whose
307+
308+
- 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 real-valued or complex-valued floating-point data type whose precision matches the precision of ``x`` (e.g., if ``x`` is ``float64``, then ``eigenvalues`` must be either ``float64`` or `complex128`).
309+
310+
- second element 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 ``x``.
311+
312+
Notes
313+
-----
314+
315+
.. note::
316+
Eigenvalue sort order is left unspecified and is thus implementation-dependent.
317+
318+
.. note::
319+
If all eigenvectors have zero imaginary parts, a conforming implementation may
320+
return either a complex-valued array or a real-valued array containing the real
321+
parts of eigenvalues.
322+
323+
.. note::
324+
For real symmetric or complex Hermitian matrices, prefer using the ``eigh`` routine.
325+
326+
.. versionadded:: 2025.12
327+
"""
328+
329+
330+
def eigvals(x: array, /) -> array:
331+
r"""
332+
Returns the eigenvalues of a real or complex (or a stack of matrices) ``x``.
333+
334+
If ``x`` is real-valued, let :math:`\mathbb{K}` be the union of the set of real numbers :math:`\mathbb{R}`
335+
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}`.
336+
337+
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
338+
339+
.. math::
340+
p(\lambda) = \operatorname{det}(x - \lambda I_n)
341+
342+
where :math:`\lambda \in \mathbb{K}` and where :math:`I_n` is the *n*-dimensional identity matrix.
343+
344+
.. note::
345+
The eigenvalues of a non-symmetric real matrix in general are complex: for
346+
:math:x \in \mathbb{R}^{n \times n}`, the eigenvalues :math:`\lambda \in \mathbb{C}`,
347+
and may or may not reside on the real axis of the complex plane.
348+
349+
350+
Parameters
351+
----------
352+
x: array
353+
input array having shape ``(..., M, M)`` and whose innermost two dimensions form square matrices. Should have a floating-point data type.
354+
355+
Returns
356+
-------
357+
out: array
358+
an array containing the computed eigenvalues. The returned array must have shape ``(..., M)`` and have a real-valued or complex-valued floating-point data type whose precision matches the precision of ``x`` (e.g., if ``x`` is ``float64``, then must have a ``float64`` or a ``complex128`` data type).
359+
360+
Notes
361+
-----
362+
363+
.. note::
364+
Eigenvalue sort order is left unspecified and is thus implementation-dependent.
365+
366+
.. note::
367+
If all eigenvectors have zero imaginary parts, a conforming implementation may
368+
return either a complex-valued array or a real-valued array containing the real
369+
parts of eigenvalues.
370+
371+
.. versionadded:: 2025.12
372+
"""
373+
374+
375+
260376
def inv(x: array, /) -> array:
261377
r"""
262378
Returns the multiplicative inverse of a square matrix (or a stack of square matrices) ``x``.

0 commit comments

Comments
 (0)