Does [V,D] = eig(A) always return normalized eigenvectors for any real matrix A?

I’m looking for clarification on the eig function in MATLAB. When I use the syntax [V, D] = eig(A) for a real matrix A, are the eigenvectors returned in the columns of V guaranteed to be normalized to unit magnitude ( )?
Does this behavior change if the matrix is non-symmetric or if I use the generalized form eig(A, B) or in any other case for a real matrix A?
Thanks!

4 Comments

A = gallery("circul",3)
A = 3×3
1 2 3 3 1 2 2 3 1
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
[V,D] = eig(A)
V =
-0.5774 + 0.0000i 0.5774 + 0.0000i 0.5774 + 0.0000i -0.5774 + 0.0000i -0.2887 - 0.5000i -0.2887 + 0.5000i -0.5774 + 0.0000i -0.2887 + 0.5000i -0.2887 - 0.5000i
D =
6.0000 + 0.0000i 0.0000 + 0.0000i 0.0000 + 0.0000i 0.0000 + 0.0000i -1.5000 + 0.8660i 0.0000 + 0.0000i 0.0000 + 0.0000i 0.0000 + 0.0000i -1.5000 - 0.8660i
sqrt(V(:,1).^2 + V(:,2).^2 + V(:,3).^2)
ans = 3×1
1.0000 0.0000 0.0000
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
So, NO, the magnitude of the second and third columns are 0.
I think the intent of Ali's phrase "normalized to unit magnitude" was asking more about this result from your example (regardless of his actual use of nomenclature):
A = gallery("circul",3)
A = 3×3
1 2 3 3 1 2 2 3 1
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
[V,D] = eig(A)
V =
-0.5774 + 0.0000i 0.5774 + 0.0000i 0.5774 + 0.0000i -0.5774 + 0.0000i -0.2887 - 0.5000i -0.2887 + 0.5000i -0.5774 + 0.0000i -0.2887 + 0.5000i -0.2887 - 0.5000i
D =
6.0000 + 0.0000i 0.0000 + 0.0000i 0.0000 + 0.0000i 0.0000 + 0.0000i -1.5000 + 0.8660i 0.0000 + 0.0000i 0.0000 + 0.0000i 0.0000 + 0.0000i -1.5000 - 0.8660i
sqrt(sum(conj(V).*V))
ans = 1×3
1 1 1
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
At least that is how I read his question.
A = gallery("circul",3);
[V,D] = eig(A);
arrayfun(@(i)norm(V(:,i)),1:width(V))
ans = 1×3
1 1 1
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
The individual eigenvectors are, per the documentation, however....
"[V,D] = eig(A) returns matrix V, whose columns are the right eigenvectors of A such that A*V = V*D. The eigenvectors in V are normalized so that the 2-norm of each is 1."
"If A is real symmetric, Hermitian, or skew-Hermitian, then the right eigenvectors V are orthonormal."
I think the above is true although I don't know that can prove it; probably somebody can illustrate a failing case.
Hi dpb,
For the 'ortho' part of orthonomal he only 'failing' cases occur for two or more eigenvectors that have identical (degenerate) eigenvalues. These need not be mutually perpendicular but can be made so by constructing a mutually perpendicular set with appropriate linear combinations. For distinct eigenvalues, the eigenvectors are always mutually perpendicular for the real symmetric, hermitian or skew hermitian cases.
The 'normal' part is less fundamental and depends on how eig is called, as has been discussed. If there is any doubt on normalization, suppose you have m column eigenvectors each of length n that constitute an nxm matrix A (m<=n so not all of the eigenvectors are necessarily included). If you are confident that they are at least mutually orthogonal, you can use
n = sqrt(sum(A.*conj(A)));
Anew = A./n;
to get an orthonormal set.

Sign in to comment.

 Accepted Answer

Whether or not the columns of V are normalized to unit magnitude depends on how eig is called.
See eig - Eigenvalues and eigenvectors - MATLAB for all of the documented possibilities.

More Answers (2)

A discussion of eigenvector normalization can be found in the doc. In some cases, the answer is yes they are "normalized to unit magnitude" as you put it. But the answer can be no dependeing on the inputs.

1 Comment

I am only interested in the case where A is positive semidefinite real matrix. I am sorry I did not read the documentation before posting this question. The documentation for the eig function states that [V,D] = eig(A) returns matrix V, whose columns are the right eigenvectors of A such that A*V = V*D. The eigenvectors in V are normalized so that the 2-norm of each is 1. This answers my question.

Sign in to comment.

Be a little careful that A is not in symbolic form, even if it is real and SPD.
A = randn(4,3); A = A'*A % A MUST clearly be SPD
A = 3×3
6.7750 -0.4223 -0.3969 -0.4223 0.5515 -0.1101 -0.3969 -0.1101 3.1915
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
[V,D] = eig(A)
V = 3×3
-0.0705 0.1021 -0.9923 -0.9962 -0.0585 0.0647 -0.0514 0.9930 0.1059
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
D = 3×3
0.5159 0 0 0 3.1572 0 0 0 6.8449
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
It is true the columns of V are unit normalized when A is single or double precision.
diag(V'*V)
ans = 3×1
1.0000 1.0000 1.0000
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
However, the symbolic version of A will not produce the same unit 2-normalized vectors.
[Vs,Ds] = eig(sym(A));
vpa(diag(Vs'*Vs))
ans = 

8 Comments

Side Note on this calculation:
A = A'*A % A MUST clearly be SPD
The reason this is true numerically, as well as mathematically, is that MATLAB uses a BLAS symmetric matrix multiply routine in the background that enforces an exact symmetric result down to the least significant bit for this particular syntax. I.e., it only does about 1/2 of the calculations and then copies the results to get the exact numerical symmetry.
E.g., the following calculation would call a BLAS generic matrix multiply routine in the background, which is not guaranteed to generate an exact symmetric result:
AT = A';
A = AT * A; % A not guaranteed to be exactly symmetric
Any idea how Matlab handles
A.' * A
Does Matlab check if A is real and use the BLAS symmetric matrix multiply in that case and use the generic matrix multiply if A is complex?
For A.' * A
Fact: BLAS library assumes interleaved storage for complex variables. To see routines available and interfaces you can go to this site (LAPACK and other library information is here also):
MATLAB always has to check if A is real to do the calculation. Once that is known, it will definitely call a BLAS real symmetric matrix multiply routine in the background (e.g., ssyrk or dsyrk) and produce an exact symmetric result if A is real. For complex A, I haven't checked which routine it will call. There are complex generic and symmetric and Hermitian routines available. For sure, it will not call the complex Hermitian routine (e.g., cherk or zherk) in the background of course. Whether it is smart enough to call the complex symmetric routine (e.g., csyrk or zsyrk) to save computation time and guarantee exact symmetric result with data copies or not, I don't know. I would hope so, but I simply haven't checked this stuff in detail since MATLAB went to interleaved complex storage.
E.g., consider the timings on this:
A = rand(7000) + rand(7000)*i;
AT = A.';
tic
ATA1 = A.'*A;
toc
Elapsed time is 2.585722 seconds.
tic
ATA2 = AT*A;
toc
Elapsed time is 3.812424 seconds.
isequal(ATA1,ATA2)
ans = logical
1
isequal(ATA1.',ATA1)
ans = logical
1
The timings suggest that different routines were called in the background. I would have to construct a mex routine that links with the BLAS library to confirm exactly which routines were called in the background, but the simple test above certainly supports the theory that the BLAS complex symmetric routine was called in the background for the first case.
SIDE NOTE: Back in the separate complex storage days pre R2018a, MATLAB would have to repeatedly call the BLAS real routines in the background with the real and imaginary pieces and combine the individual results to deal with complex matrix multiplies. But for R2018a onwards, since the background storage is interleaved it can call the BLAS complex matrix multiply routines directly. I'm confident MATLAB uses the Hermitian routines in the background when appropriate. I just haven't double checked the complex symmetric case (i.e., straight transpose instead of conjugate transpose) even though I would be surprised if they didn't take advantage of the complex symmetric routines and guarantee exact symmetric result via data copies.
If two different routines were called, is it surprising that they yielded the exact same result? I thought that one advantage of the ATA1 method is to ensure exact symmetry, but that seems to also obtain with ATA2 method.
Test case with a larger input.
rng(100);
A = rand(10000) + rand(10000)*i;
AT = A.';
tic
ATA1 = A.'*A;
toc
Elapsed time is 9.129359 seconds.
tic
ATA2 = AT*A;
toc
Elapsed time is 15.939243 seconds.
isequal(ATA1,ATA2)
ans = logical
1
isequal(ATA1.',ATA1)
ans = logical
1
I can't confirm this, but I believe this has changed slightly over the years in an attempt to make the two routines yield the same results even though one routine does about twice the actual calculations of the other. Earlier versions of MATLAB, I can confirm, do not necessarily yield exact symmetric results for generic matrix multiplies. I'm pretty sure there are some older posts of mine that demonstrate this. Whether this is still the case with recent versions of MATLAB is anyone's guess since I don't think the doc comments on it. Regardless, I wouldn't rely on it in any code I wrote, particularly if I wanted that code to port to older versions of MATLAB.
Quick test with non-square matrix:
A = rand(5000,4000);
AT = A.';
B = AT * A;
isequal(B.',B)
ans = logical
1
But on my R2021a Win64 PC:
>> A = rand(5000,4000);
>> AT = A.';
>> B = AT * A;
>> isequal(B.',B)
ans =
logical
0
Draw your own conclusions ...
That is interesting. Is that difference in R2021a only seen with rectangular A?
I suppose it's possible that the difference we're seeing could be influenced by running here on the forum compared to your PC, but I doubt that the exact symmetry seen here is just happenstance.
I know that Mathworks doesn't guarantee identical results from release to release, but I'd think that a change in behavior of such a core functionality as matrix muliplication would be worthy of a bold mention in the release notes, which I checked and didn't find anything on this topic.
Results on my R2021a Win64 PC are below. And I get the same results on R2023a also. So, all results are symmetric/Hermitian except the real non-square case. The fact that the complex non-square case passes but the real non-square case fails is interesting. Also note that the only case where the inline vs saved variable transpose results match is the complex non-square case. All other case results don't match, even when the results are symmetric/Hermitian. I'm not posing any theories at this time because I haven't really looked at this in detail since MATLAB went to interleaved storage for complex variables.
The timings and different results clearly indicate that different routines are called in the background for inline transposing vs saved variable transposing.
---------------------------------------------------
>> trantest
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
A is real 5000 x 5000
Number of cases = 20
Number of cases A.' * A is symmetric = 20 , Ave time = 3.531615e-01
Number of cases A' * A is Hermitian = 20 , Ave time = 3.457570e-01
Number of cases AT * A is symmetric = 20 , Ave time = 4.915746e-01
Number of cases AC * A is Hermitian = 20 , Ave time = 4.918128e-01
Number of cases A.' * A == AT * A = 0
Number of cases A' * A == AC * A = 0
>> trantest
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
A is real 5000 x 4000
Number of cases = 20
Number of cases A.' * A is symmetric = 20 , Ave time = 2.351747e-01
Number of cases A' * A is Hermitian = 20 , Ave time = 2.346623e-01
Number of cases AT * A is symmetric = 0 , Ave time = 3.144102e-01
Number of cases AC * A is Hermitian = 0 , Ave time = 3.147649e-01
Number of cases A.' * A == AT * A = 0
Number of cases A' * A == AC * A = 0
>> trantest
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
A is complex 5000 x 5000
Number of cases = 20
Number of cases A.' * A is symmetric = 20 , Ave time = 1.233667e+00
Number of cases A' * A is Hermitian = 20 , Ave time = 1.213396e+00
Number of cases AT * A is symmetric = 20 , Ave time = 2.002871e+00
Number of cases AC * A is Hermitian = 20 , Ave time = 2.009287e+00
Number of cases A.' * A == AT * A = 0
Number of cases A' * A == AC * A = 0
>> trantest
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
A is complex 5000 x 4000
Number of cases = 20
Number of cases A.' * A is symmetric = 20 , Ave time = 7.757201e-01
Number of cases A' * A is Hermitian = 20 , Ave time = 8.060675e-01
Number of cases AT * A is symmetric = 20 , Ave time = 1.283597e+00
Number of cases AC * A is Hermitian = 20 , Ave time = 1.291259e+00
Number of cases A.' * A == AT * A = 20
Number of cases A' * A == AC * A = 20
---------------------------------------------------
The code:
% Run specific parameters:
N = 20; % Number of runs to make
m = 5000; n = 4000; % size of matrix
r = false; % real flag
% end run specific parameters
issymt1 = 0;
issymt2 = 0;
issymc1 = 0;
issymc2 = 0;
iseqt = 0;
iseqc = 0;
timt1 = 0;
timt2 = 0;
timc1 = 0;
timc2 = 0;
for k=1:N
fprintf("%d ",k)
if( r )
A = rand(m,n);
else
A = rand(m,n) + rand(m,n)*1i;
end
clear B1 B2
tic
B1 = A.' * A;
timt1 = timt1 + toc;
AT = A.';
tic
B2 = AT*A;
timt2 = timt2 + toc;
issymt1 = issymt1 + isequal(B1.',B1);
issymt2 = issymt2 + isequal(B2.',B2);
iseqt = iseqt + isequal(B1,B2);
clear B1 B2
tic
B1 = A' * A;
timc1 = timc1 + toc;
AC = A';
tic
B2 = AC*A;
timc2 = timc2 + toc;
issymc1 = issymc1 + isequal(B1',B1);
issymc2 = issymc2 + isequal(B2',B2);
iseqc = iseqc + isequal(B1,B2);
end
disp(' ')
if( r )
fprintf("A is real %d x %d\n",m,n);
else
fprintf("A is complex %d x %d\n",m,n);
end
fprintf("Number of cases = %d\n",N);
fprintf("Number of cases A.' * A is symmetric = %d , Ave time = %d\n",issymt1,timt1/N);
fprintf("Number of cases A' * A is Hermitian = %d , Ave time = %d\n",issymc1,timc1/N);
fprintf("Number of cases AT * A is symmetric = %d , Ave time = %d\n",issymt2,timt2/N);
fprintf("Number of cases AC * A is Hermitian = %d , Ave time = %d\n",issymc2,timc2/N);
fprintf("Number of cases A.' * A == AT * A = %d\n",iseqt);
fprintf("Number of cases A' * A == AC * A = %d\n",iseqc);

Sign in to comment.

Categories

Find more on Linear Algebra in Help Center and File Exchange

Asked:

on 17 Mar 2026 at 18:28

Edited:

on 27 Mar 2026 at 21:21

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!