Visual Tools
Calculators
Tables
Mathematical Keyboard
Converters
Other Tools


Gram Schmidt Process






Converting Any Basis into an Orthogonal One

The Gram-Schmidt process takes a set of linearly independent vectors and produces an orthogonal (or orthonormal) set spanning the same subspace. It works by sequentially stripping each vector of its components along previously computed directions, leaving only the perpendicular remainder. The result is a constructive proof that orthonormal bases always exist — and the matrix version of this process is the QR decomposition.



The Goal

The input is a set of linearly independent vectors {v1,v2,,vk}\{\mathbf{v}_1, \mathbf{v}_2, \dots, \mathbf{v}_k\} in an inner product space. The output is an orthogonal set {u1,u2,,uk}\{\mathbf{u}_1, \mathbf{u}_2, \dots, \mathbf{u}_k\} satisfying two conditions: the vectors are pairwise perpendicular (uiuj=0\mathbf{u}_i \cdot \mathbf{u}_j = 0 for iji \neq j), and they span the same subspace (Span{u1,,uj}=Span{v1,,vj}\text{Span}\{\mathbf{u}_1, \dots, \mathbf{u}_j\} = \text{Span}\{\mathbf{v}_1, \dots, \mathbf{v}_j\} at every step jj).

Optionally, each ui\mathbf{u}_i is normalized to unit length, producing an orthonormal set {q1,,qk}\{\mathbf{q}_1, \dots, \mathbf{q}_k\}.

The process is the constructive proof that every finite-dimensional inner product space has an orthonormal basis. Given any basis, Gram-Schmidt produces an orthonormal one for the same space.

The Algorithm: Two Vectors

Start with two independent vectors v1\mathbf{v}_1 and v2\mathbf{v}_2.

Set u1=v1\mathbf{u}_1 = \mathbf{v}_1.

Subtract the projection of v2\mathbf{v}_2 onto u1\mathbf{u}_1:

u2=v2u1v2u1u1u1\mathbf{u}_2 = \mathbf{v}_2 - \frac{\mathbf{u}_1 \cdot \mathbf{v}_2}{\mathbf{u}_1 \cdot \mathbf{u}_1}\,\mathbf{u}_1


The subtracted term is the component of v2\mathbf{v}_2 along u1\mathbf{u}_1. Removing it leaves only the component perpendicular to u1\mathbf{u}_1, so u1u2=0\mathbf{u}_1 \cdot \mathbf{u}_2 = 0.

Worked Example


v1=(1,1,0)\mathbf{v}_1 = (1, 1, 0), v2=(1,0,1)\mathbf{v}_2 = (1, 0, 1).

u1=(1,1,0)\mathbf{u}_1 = (1, 1, 0). u1v2u1u1=12\frac{\mathbf{u}_1 \cdot \mathbf{v}_2}{\mathbf{u}_1 \cdot \mathbf{u}_1} = \frac{1}{2}. u2=(1,0,1)12(1,1,0)=(12,12,1)\mathbf{u}_2 = (1, 0, 1) - \frac{1}{2}(1, 1, 0) = (\frac{1}{2}, -\frac{1}{2}, 1).

Check: u1u2=1212+0=0\mathbf{u}_1 \cdot \mathbf{u}_2 = \frac{1}{2} - \frac{1}{2} + 0 = 0.
V3×3v1,1v1,2v1,3v2,1v2,2v2,3v3,1v3,2v3,3U3×3v1,1v1,2v1,3v2,1c2,1u1,1v2,2c2,1u1,2v2,3c2,1u1,3v3,1c3,1u1,1c3,2u2,1v3,2c3,1u1,2c3,2u2,2v3,3c3,1u1,3c3,2u2,3
The overlap removed from the second vector

The projection of this vector onto the direction already fixed is being subtracted away. What survives is orthogonal to that direction by construction, not by luck — the subtraction removes precisely the component that would have made the dot product non-zero. Watch the next vector go through the same treatment on the Gram-Schmidt visualizer.

The general case below repeats this step once per vector already fixed, which is the only way the algorithm grows.

The Algorithm: General Case

For kk independent vectors v1,,vk\mathbf{v}_1, \dots, \mathbf{v}_k:

u1=v1\mathbf{u}_1 = \mathbf{v}_1


Gram-Schmidt Process
uj=vji=1j1uivjuiuiuifor j=2,3,,k\mathbf{u}_j = \mathbf{v}_j - \sum_{i=1}^{j-1} \frac{\mathbf{u}_i \cdot \mathbf{v}_j}{\mathbf{u}_i \cdot \mathbf{u}_i}\,\mathbf{u}_i \quad \text{for } j = 2, 3, \dots, k

At each step, vj\mathbf{v}_j has its projections onto all previously computed orthogonal vectors subtracted. What remains is the component of vj\mathbf{v}_j perpendicular to Span{u1,,uj1}\text{Span}\{\mathbf{u}_1, \dots, \mathbf{u}_{j-1}\}.

Because vj\mathbf{v}_j is independent of {v1,,vj1}\{\mathbf{v}_1, \dots, \mathbf{v}_{j-1}\} — and therefore not in Span{u1,,uj1}\text{Span}\{\mathbf{u}_1, \dots, \mathbf{u}_{j-1}\} — this perpendicular component is nonzero. So each uj0\mathbf{u}_j \neq \mathbf{0}, and the process never breaks down.

At every stage, Span{u1,,uj}=Span{v1,,vj}\text{Span}\{\mathbf{u}_1, \dots, \mathbf{u}_j\} = \text{Span}\{\mathbf{v}_1, \dots, \mathbf{v}_j\}. The span is preserved because each uj\mathbf{u}_j is a linear combination of vj\mathbf{v}_j and the earlier ui\mathbf{u}_i's (which are themselves combinations of v1,,vj1\mathbf{v}_1, \dots, \mathbf{v}_{j-1}).

Gram-Schmidt Notation

Notation

Gram-Schmidt Notation

An algorithm's notation has to record not just what the objects are but the order they were built in — so this page runs three letters for three stages of the same vector, and a sum whose upper limit moves with the step it appears in. All catalogued among the linear algebra symbols.
proj\operatorname{proj} and its subscript come from projection notation; the dot from dot product notation; v\|\mathbf{v}\| and the unit hat from norm notation; Span\operatorname{Span} from span notation; δij\delta_{ij} and QQ from orthogonal set notation.
vjujej\mathbf{v}_j \to \mathbf{u}_j \to \mathbf{e}_j
input, orthogonalised, normalised
Three letters for three stages of the same vector: vj\mathbf{v}_j is what you started with, uj\mathbf{u}_j what survives after the projections are removed, and ej\mathbf{e}_j the unit version — Normalization below performs that last step. The subscript stays fixed across all three; only the letter records how far the vector has been processed.
CasesSources that skip the orthogonal stage write qj\mathbf{q}_j directly for the normalised output, matching the QQ of the decomposition below; others reuse vj\mathbf{v}_j throughout and overwrite in place, which is how the algorithm is actually implemented but loses the ability to refer to an earlier stage.
Do not confuseej\mathbf{e}_j as a standard basis vector. Here it is the jj-th vector this process produced, not the jj-th axis — the letter is borrowed for "unit vector", and only the surrounding construction says which unit vector is meant.
uj=vji=1j1projui(vj)\mathbf{u}_j = \mathbf{v}_j - \sum_{i=1}^{j-1} \operatorname{proj}_{\mathbf{u}_i}(\mathbf{v}_j)
subtract the projections onto everything built so far
The upper limit is the notational content: j1j-1 means everything already constructed, so the sum's length grows as the algorithm proceeds and the formula refers to its own earlier outputs. This is a recursive definition written as a formula, not a closed expression.
CasesThe first step is the empty case — at j=1j = 1 the sum has no terms, which is why u1=v1\mathbf{u}_1 = \mathbf{v}_1 needs no separate rule; and the projections are onto the ui\mathbf{u}_i, never the vi\mathbf{v}_i, which is the one substitution that silently breaks the algorithm.
Do not confuseA fixed sum over all kk vectors. Reading the limit as kk rather than j1j-1 asks the formula to use vectors that do not exist yet — the range is the whole reason the construction terminates.
A=QRA = QR
A factors into an orthonormal Q and an upper-triangular R
Letters as a contract, in the family pattern decomposition notation describes: QQ carries the orthonormal columns this process produces, RR collects the coefficients it discarded along the way — The QR Decomposition below reads them off directly.
CasesRR comes out upper triangular for a reason the notation encodes: vj\mathbf{v}_j is built only from u1,,uj\mathbf{u}_1, \dots, \mathbf{u}_j, so every entry below the diagonal is a coefficient that was never used.
Do not confuseRR as the real numbers. Blackboard R\mathbb{R} is the field; italic RR here is one specific triangular matrix, and the two sit close together in exactly the equations where both appear.

Normalization

After computing the orthogonal set {u1,,uk}\{\mathbf{u}_1, \dots, \mathbf{u}_k\}, normalization produces an orthonormal set:

qi=uiui\mathbf{q}_i = \frac{\mathbf{u}_i}{\|\mathbf{u}_i\|}


Each vector is divided by its length, making qi=1\|\mathbf{q}_i\| = 1 while preserving direction. The resulting set satisfies qiqj=δij\mathbf{q}_i \cdot \mathbf{q}_j = \delta_{ij}.

Normalization can be done at each step (normalize uj\mathbf{u}_j immediately before moving to vj+1\mathbf{v}_{j+1}) or all at the end. The result is the same in exact arithmetic. In practice, normalizing at each step is slightly preferable for numerical stability, as it keeps the vectors well-scaled throughout the computation.
U3×3v1,1v1,2v1,3v2,1c2,1u1,1v2,2c2,1u1,2v2,3c2,1u1,3v3,1c3,1u1,1c3,2u2,1v3,2c3,1u1,2c3,2u2,2v3,3c3,1u1,3c3,2u2,3E3×3u1,1/u1u1,2/u1u1,3/u1??????
Scaling the survivor to unit length

Orthogonality was settled by the subtraction; this step only fixes the length. Splitting the two concerns is why the algorithm can be stated for an orthogonal basis and then upgraded to an orthonormal one without changing its structure. Toggle normalisation on and off on the Gram-Schmidt visualizer.

Dividing by a very small length is where the classical algorithm loses accuracy, which is the subject of the stability section later.

Worked Example: Three Vectors in R³

Orthogonalize v1=(1,1,1)\mathbf{v}_1 = (1, 1, 1), v2=(1,0,1)\mathbf{v}_2 = (1, 0, 1), v3=(0,1,1)\mathbf{v}_3 = (0, 1, 1).

u1=(1,1,1)\mathbf{u}_1 = (1, 1, 1).

For u2\mathbf{u}_2: u1v2u1u1=1+0+13=23\frac{\mathbf{u}_1 \cdot \mathbf{v}_2}{\mathbf{u}_1 \cdot \mathbf{u}_1} = \frac{1 + 0 + 1}{3} = \frac{2}{3}. u2=(1,0,1)23(1,1,1)=(13,23,13)\mathbf{u}_2 = (1, 0, 1) - \frac{2}{3}(1, 1, 1) = (\frac{1}{3}, -\frac{2}{3}, \frac{1}{3}).

Check: u1u2=1323+13=0\mathbf{u}_1 \cdot \mathbf{u}_2 = \frac{1}{3} - \frac{2}{3} + \frac{1}{3} = 0.

For u3\mathbf{u}_3: u1v3u1u1=0+1+13=23\frac{\mathbf{u}_1 \cdot \mathbf{v}_3}{\mathbf{u}_1 \cdot \mathbf{u}_1} = \frac{0 + 1 + 1}{3} = \frac{2}{3} and u2v3u2u2=023+1319+49+19=1369=12\frac{\mathbf{u}_2 \cdot \mathbf{v}_3}{\mathbf{u}_2 \cdot \mathbf{u}_2} = \frac{0 - \frac{2}{3} + \frac{1}{3}}{\frac{1}{9} + \frac{4}{9} + \frac{1}{9}} = \frac{-\frac{1}{3}}{\frac{6}{9}} = \frac{-1}{2}.

u3=(0,1,1)23(1,1,1)(12)(13,23,13)=(0,1,1)(23,23,23)+(16,13,16)=(12,0,12)\mathbf{u}_3 = (0, 1, 1) - \frac{2}{3}(1, 1, 1) - (-\frac{1}{2})(\frac{1}{3}, -\frac{2}{3}, \frac{1}{3}) = (0, 1, 1) - (\frac{2}{3}, \frac{2}{3}, \frac{2}{3}) + (\frac{1}{6}, -\frac{1}{3}, \frac{1}{6}) = (-\frac{1}{2}, 0, \frac{1}{2}).

Check: u1u3=12+0+12=0\mathbf{u}_1 \cdot \mathbf{u}_3 = -\frac{1}{2} + 0 + \frac{1}{2} = 0 and u2u3=16+0+16=0\mathbf{u}_2 \cdot \mathbf{u}_3 = -\frac{1}{6} + 0 + \frac{1}{6} = 0.

Normalizing: u1=3\|\mathbf{u}_1\| = \sqrt{3}, u2=6/3\|\mathbf{u}_2\| = \sqrt{6}/3, u3=1/2\|\mathbf{u}_3\| = 1/\sqrt{2}. The orthonormal basis is {u1/3,  3u2/6,  2u3}\{\mathbf{u}_1/\sqrt{3}, \; 3\mathbf{u}_2/\sqrt{6}, \; \sqrt{2}\,\mathbf{u}_3\}.

Why It Works

At each step, uj\mathbf{u}_j is constructed as vj\mathbf{v}_j minus everything in vj\mathbf{v}_j that lies in the subspace Wj1=Span{u1,,uj1}W_{j-1} = \text{Span}\{\mathbf{u}_1, \dots, \mathbf{u}_{j-1}\}. Since {u1,,uj1}\{\mathbf{u}_1, \dots, \mathbf{u}_{j-1}\} is orthogonal, the projection formula decomposes cleanly into independent terms — one projection per basis vector.

What remains after subtraction is the component of vj\mathbf{v}_j orthogonal to Wj1W_{j-1}. This component is nonzero because vjWj1\mathbf{v}_j \notin W_{j-1} — guaranteed by the independence of the original set.

The span is preserved at each step. Each uj\mathbf{u}_j is a linear combination of vj\mathbf{v}_j and u1,,uj1\mathbf{u}_1, \dots, \mathbf{u}_{j-1}, and each earlier ui\mathbf{u}_i is a combination of v1,,vi\mathbf{v}_1, \dots, \mathbf{v}_i. So ujSpan{v1,,vj}\mathbf{u}_j \in \text{Span}\{\mathbf{v}_1, \dots, \mathbf{v}_j\}, and the reverse inclusion follows because vj\mathbf{v}_j can be recovered from uj\mathbf{u}_j and the earlier ui\mathbf{u}_i's.

The QR Decomposition

Applying Gram-Schmidt to the columns a1,,an\mathbf{a}_1, \dots, \mathbf{a}_n of an m×nm \times n matrix AA (with independent columns) produces the QR decomposition:

A=QRA = QR


QQ is m×nm \times n with orthonormal columns (the normalized qi\mathbf{q}_i's). RR is n×nn \times n upper triangular with positive diagonal entries.

The entries of RR are the dot products computed during Gram-Schmidt: Rij=qiajR_{ij} = \mathbf{q}_i \cdot \mathbf{a}_j for iji \leq j, and Rij=0R_{ij} = 0 for i>ji > j (because aj\mathbf{a}_j's projection onto qi\mathbf{q}_i is zero when i>ji > j — that direction hasn't been subtracted yet).

The factorization captures two complementary pieces of information. QQ stores the orthonormal directions. RR stores the coefficients that express the original columns in terms of those directions: aj=R1jq1+R2jq2++Rjjqj\mathbf{a}_j = R_{1j}\mathbf{q}_1 + R_{2j}\mathbf{q}_2 + \cdots + R_{jj}\mathbf{q}_j.
Orthogonality · QR

Where each factor comes from

Running Gram–Schmidt on the columns of AA produces both factors at once. QQ is the output and RR is the bookkeeping — the coefficients that were subtracted along the way, kept rather than discarded.

2factors
TypeConditionentriespropertieswhat it records
The output
Q — orthonormal columns§ 7m×nm \times nqj=uj/uj\mathbf{q}_j = \mathbf{u}_j / \|\mathbf{u}_j\|QTQ=InQ^{\mathsf{T}}Q = I_nan orthonormal basis for Col(A)\operatorname{Col}(A)
The bookkeeping
R — upper triangular§ 7n×nn \times nrij=qivjr_{ij} = \mathbf{q}_i \cdot \mathbf{v}_jdiagonal rjj=uj>0r_{jj} = \|\mathbf{u}_j\|>0the coefficients discarded during orthogonalization
This is why QR is not a separate algorithm from Gram–Schmidt so much as its record. Every projection coefficient computed during orthogonalization is an entry of RR, and RR is triangular precisely because vj\mathbf{v}_j is only ever projected onto vectors that came before it.
Where each factor comes from·/linear-algebra/orthogonality/gram-schmidtLearn Math Class
The triangularity of RR is worth seeing as a consequence rather than a condition. At step jj the algorithm projects vj\mathbf{v}_j onto q1,,qj1\mathbf{q}_1, \ldots, \mathbf{q}_{j-1} and no others, so every coefficient with i>ji > j is zero because that projection was never computed. Nothing was imposed on the shape — it fell out of processing the columns in order.
A3×3a1,1a1,2a1,3a2,1a2,2a2,3a3,1a3,2a3,3=Q3×3u1,1/r1,1u1,2/r2,2u1,3/r3,3u2,1/r1,1u2,2/r2,2u2,3/r3,3u3,1/r1,1u3,2/r2,2u3,3/r3,3·R3×3u1q1·a2q1·a30u2q2·a300u3
The same run, recorded as two factors

The orthonormal vectors produced have become the columns of Q, and the coefficients subtracted along the way have become the entries of R. The triangularity of R is not imposed: it reflects the fact that each vector was only ever corrected against the ones before it. Compare the two views on the QR decomposition visualizer.

Gram-Schmidt and QR are therefore one computation with two names, depending on whether the vectors or the factors are what you are after.

QR and Least Squares

The QR decomposition provides a numerically superior method for solving least-squares problems.

The normal equations ATAx^=ATbA^TA\hat{\mathbf{x}} = A^T\mathbf{b} can be rewritten using A=QRA = QR. Since ATA=RTQTQR=RTRA^TA = R^TQ^TQR = R^TR and ATb=RTQTbA^T\mathbf{b} = R^TQ^T\mathbf{b}, the normal equations become RTRx^=RTQTbR^TR\hat{\mathbf{x}} = R^TQ^T\mathbf{b}. Canceling RTR^T (which is invertible since RR has positive diagonal):

Rx^=QTbR\hat{\mathbf{x}} = Q^T\mathbf{b}


This is an upper triangular system, solved by back substitution. The computation QTbQ^T\mathbf{b} is just nn dot products (one per column of QQ).

The QR approach avoids forming ATAA^TA explicitly. This matters because the condition number of ATAA^TA is the square of the condition number of AA — squaring amplifies rounding errors. Working with QQ and RR directly preserves the original conditioning and is the standard method for least squares in numerical software.

Numerical Stability

Classical Gram-Schmidt (as presented above) can lose orthogonality in floating-point arithmetic. When the input vectors are nearly dependent, the computed uj\mathbf{u}_j's may fail to be perpendicular to machine precision, and the errors accumulate with each step.

Modified Gram-Schmidt addresses this by reorganizing the computation. Instead of computing all projections using the original vj\mathbf{v}_j, modified Gram-Schmidt updates vj\mathbf{v}_j in place after each projection is subtracted. At step jj, first subtract the projection onto u1\mathbf{u}_1 from vj\mathbf{v}_j, then subtract the projection onto u2\mathbf{u}_2 from the updated vj\mathbf{v}_j, and so on. The mathematical result is identical in exact arithmetic, but the modified version is significantly more stable numerically.

Householder reflections provide an even more robust alternative for computing the QR factorization. Householder-based QR achieves backward stability — the gold standard in numerical linear algebra — and is the default algorithm in most software libraries.
Method How it computes the orthogonal set / QR Numerical stability Typical use
Classical Gram–Schmidt at step j, all projections of the original vj onto u1, …, uj−1 are computed and subtracted at once poor — orthogonality can be lost when input vectors are nearly dependent; errors accumulate textbook / illustrative use; abstract inner product spaces where exact arithmetic is available
Modified Gram–Schmidt vj is updated in place after each individual projection is subtracted significantly better than classical; identical result in exact arithmetic educational software, moderate-precision floating-point work
Householder reflections a sequence of orthogonal reflections is applied to A to zero out below-diagonal entries column by column backward stable — the gold standard in numerical linear algebra default QR routine in LAPACK, NumPy, MATLAB, and most numerical libraries
Givens rotations a sequence of 2 × 2 plane rotations zeros out individual entries one at a time backward stable; lets the algorithm target nonzero entries only sparse matrices with structured zeros; updating an existing QR factorization

Gram-Schmidt on Abstract Inner Product Spaces

The algorithm works in any inner product space — the dot product is replaced by the general inner product ,\langle \cdot, \cdot \rangle, and the formulas are otherwise identical:

uj=vji=1j1ui,vjui,uiui\mathbf{u}_j = \mathbf{v}_j - \sum_{i=1}^{j-1} \frac{\langle \mathbf{u}_i, \mathbf{v}_j \rangle}{\langle \mathbf{u}_i, \mathbf{u}_i \rangle}\,\mathbf{u}_i


Orthogonalizing {1,x,x2}\{1, x, x^2\} in the polynomial space P2\mathcal{P}_2 with the inner product p,q=11p(x)q(x)dx\langle p, q \rangle = \int_{-1}^{1} p(x)q(x)\,dx produces the Legendre polynomials (up to normalization): P0(x)=1P_0(x) = 1, P1(x)=xP_1(x) = x, P2(x)=12(3x21)P_2(x) = \frac{1}{2}(3x^2 - 1). The polynomial xx is already orthogonal to 11 under this inner product (the integral of an odd function over a symmetric interval is zero), so the first subtraction has no effect.

On the function space C[0,2π]C[0, 2\pi] with f,g=02πf(x)g(x)dx\langle f, g \rangle = \int_0^{2\pi} f(x)g(x)\,dx, orthogonalizing appropriate function sets produces Fourier bases. The algorithm is identical in structure to the Rn\mathbb{R}^n version — only the inner product changes.

Summary: Gram-Schmidt Across Settings

Gram-Schmidt operates uniformly across many settings — ℝⁿ with the standard dot product, polynomial spaces with integral inner products, function spaces in Fourier analysis, and abstract inner product spaces in general. The table below collects the main contexts in which the process is applied, alongside the input, the inner product used, and what the algorithm produces in each case.
What follows is one algorithm listed six times. The steps are identical in every row — subtract the projections onto what has already been processed, then optionally divide by the length. The only thing that varies is which inner product those projections are computed with, and the grouping below separates the familiar dot product from the integrals that replace it elsewhere.
Orthogonality · Gram–Schmidt

The same algorithm across settings

The procedure never changes — subtract projections, optionally normalise. What changes from row to row is only the inner product being used, and with it what the word "orthogonal" turns out to mean.

6settings
The dot product on ℝⁿ3
1
input independent
uj=vji<jprojui(vj)\mathbf{u}_j = \mathbf{v}_j - \sum_{i<j} \operatorname{proj}_{\mathbf{u}_i}(\mathbf{v}_j)
Each vector loses everything it shares with the ones already processed, leaving the perpendicular remainder. The span is preserved at every prefix, so the output describes the same subspace as the input — differently oriented, not differently sized.
2
one extra division per vector
qj=uj/uj\mathbf{q}_j = \mathbf{u}_j / \|\mathbf{u}_j\|
Normalisation is a separate step and strictly optional — orthogonality is already achieved. It is worth doing because projection onto an orthonormal set is a bare dot product, with no denominator to carry.
3
AA of full column rank
A=QRA = QR, RR upper triangular
Run the algorithm on the columns of AA and the outputs are the columns of QQ; the projection coefficients discarded along the way are exactly the entries of RR. The factorization is the algorithm with its bookkeeping written down — see QR.
Other inner products3
4
applied to {1,x,x2,}\{1, x, x^2, \ldots\}
p,q=11p(x)q(x)dx\langle p, q \rangle = \int_{-1}^{1} p(x)q(x)\,dx
The monomials are independent but not orthogonal under this product. Orthogonalizing them produces the Legendre polynomials — which is to say Legendre polynomials are not a discovery so much as what Gram–Schmidt returns when handed the obvious basis.
5
sines and cosines
f,g=02πf(x)g(x)dx\langle f, g \rangle = \int_0^{2\pi} f(x)g(x)\,dx
Here the algorithm has almost nothing to do: distinct frequencies are already orthogonal under this product, so it only normalises. That is the fact the Fourier basis rests on, and the reason a Fourier coefficient is a single integral rather than a linear system.
6
finite-dimensional, any ,\langle \cdot, \cdot \rangle
orthonormal {q1,,qn}\{\mathbf{q}_1, \ldots, \mathbf{q}_n\}
The general statement the rows above are instances of. Because the algorithm terminates and uses only the axioms, it proves the existence of an orthonormal basis rather than assuming it — a constructive proof, not an abstract one.
The algorithm only ever calls two things: the inner product and scalar multiplication. It never inspects what a vector is, which is why the same code orthogonalizes tuples, polynomials and functions without modification — and why it constitutes a constructive proof that every finite-dimensional inner product space has an orthonormal basis.
The same algorithm across settings·/linear-algebra/orthogonality/gram-schmidtLearn Math Class
The second group is where the generality earns its keep. Under the integral inner product on [1,1][-1, 1] the monomials 1,x,x21, x, x^2 are independent but not orthogonal, and orthogonalizing them yields the Legendre polynomials — so those are not a separate construction but simply what this algorithm returns when handed the obvious basis. Under the inner product on [0,2π][0, 2\pi], sines and cosines of distinct frequencies are already orthogonal, and the algorithm finds nothing to subtract.
That last observation is why a Fourier coefficient is a single integral rather than the solution of a linear system: the basis was orthogonal before anyone asked. The algorithm never inspects what a vector is — it calls the inner product and scalar multiplication and nothing else — which is what lets the same procedure serve tuples, polynomials and functions, and what makes it a constructive proof that every finite-dimensional inner product space has an orthonormal basis.

Gram-Schmidt FAQ

Why does the sum stop at j1j-1 rather than running over all the vectors?

+
Because the later vectors have not been produced yet. At step jj only u1\mathbf{u}_1 through uj1\mathbf{u}_{j-1} exist, so a fixed upper limit would ask the formula to use things that do not exist. The moving limit is also why the construction terminates, and at j=1j = 1 the empty sum makes u1=v1\mathbf{u}_1 = \mathbf{v}_1 automatic.Read more →

Are the ej\mathbf{e}_j here the standard basis vectors?

+
No, they are the unit vectors this process produced, not the coordinate axes. The letter is borrowed for its association with unit length, and only the surrounding construction says which unit vector is meant. Watch the projections too: they must be onto the ui\mathbf{u}_i, never the original vi\mathbf{v}_i, which is the substitution that silently breaks the algorithm.Read more →

Why does RR come out upper triangular?

+
Because of what the algorithm builds. Each vj\mathbf{v}_j is assembled from only the first jj orthogonal vectors, so any coefficient below the diagonal would refer to a vector that never contributed. Those entries are zero not by construction but by absence. Note that italic RR here is one triangular matrix, unrelated to blackboard R\mathbb{R}.Read more →