🎓How I Study AIHISA
📖Read
📄Papers📰Blogs🎬Courses
💡Learn
🛤️Paths📚Topics💡Concepts🎴Shorts
🎯Practice
⏱️Coach🧩Problems🧠Thinking🎯Prompts🧠Review
SearchSettings
How I Study AI - Learn AI Papers & Lectures the Easy Way
∑MathAdvanced

Hilbert Spaces

Key Points

  • •
    A Hilbert space is an inner product space that is complete, meaning Cauchy sequences converge to points inside the space.
  • •
    It generalizes Euclidean geometry to possibly infinite dimensions while keeping angles, lengths, and orthogonal projections meaningful.
  • •
    Classic examples include Rn with the dot product, the sequence space l2, and the function space L2 over an interval.
  • •
    Orthogonality and projections are central: every vector has a unique closest point in any closed subspace.
  • •
    Orthonormal bases let you expand vectors as convergent infinite series (e.g., Fourier series in L2).
  • •
    Key theorems include Cauchy–Schwarz, Pythagoras, Projection Theorem, Parseval’s identity, and Riesz representation.
  • •
    In computation, we approximate infinite-dimensional problems by finite bases and use algorithms like Gram–Schmidt and numerical integration.
  • •
    C++ implementations usually represent finite-dimensional Hilbert spaces with vectors, inner products, norms, and projection operations.

Prerequisites

  • →Linear algebra (vectors, matrices, dot product) — Hilbert spaces generalize Euclidean geometry, requiring comfort with inner products and orthogonality.
  • →Metric spaces and Cauchy sequences — Completeness is defined via the metric induced by the norm, and Cauchy sequences are central.
  • →Real and complex analysis (integration, series) — L^2 spaces, Fourier series, and convergence notions rely on integration and infinite series.
  • →Numerical analysis (quadrature, stability) — Practical computations in L^2 use numerical integration and stable orthonormalization.
  • →Algorithms and complexity basics — To analyze costs of Gram–Schmidt, projections, and quadrature in C++ implementations.
  • →Floating-point arithmetic — Understanding rounding errors and the need for stable algorithms like modified Gram–Schmidt.
  • →Fourier analysis (introductory level) — Fourier series exemplify orthonormal expansions and projections in Hilbert spaces.
  • →C++ programming (vectors, functions, standard library) — To implement inner products, orthonormalization, and numerical integration cleanly.

Detailed Explanation

Tap terms for definitions

01Overview

A Hilbert space is a vector space equipped with an inner product where every Cauchy sequence converges within the space. Intuitively, it is the natural setting for extending Euclidean geometry to higher (even infinite) dimensions while retaining the familiar notions of length, angle, and orthogonality. In finite dimensions, any inner product space is automatically complete, so every finite-dimensional inner product space is a Hilbert space. The real power emerges in infinite dimensions: spaces like l^2 (square-summable sequences) and L^2 (square-integrable functions) behave geometrically like Euclidean spaces in many crucial ways. This structure enables orthogonal projections onto subspaces, orthonormal bases, and expansions of vectors as (possibly infinite) sums of basis elements—think Fourier series as coordinates of a function in a trigonometric basis. Completeness guarantees that limits of approximating sequences (e.g., partial sums or numerical approximations) land back in the space. As a result, Hilbert spaces underpin large parts of modern analysis, signal processing, machine learning (kernel methods), numerical PDEs (Galerkin methods), and quantum mechanics, where state vectors live in complex Hilbert spaces and observables act as linear operators.

02Intuition & Analogies

Imagine standing in an endlessly wide, perfectly flat room where you can walk in infinitely many independent directions. That is the geometric feeling of a Hilbert space: it is like Euclidean space but with possibly infinitely many coordinates. The inner product is your angle-and-length measuring device—like a smart tape measure that also tells you the cosine of the angle between two directions. From this, the norm (length) and the idea of being perpendicular (orthogonal) come for free. Now picture shining a flashlight from a point onto a wall: the shadow is the nearest point on that wall. In Hilbert spaces, a closed subspace is like a perfectly flat wall, and the orthogonal projection is the unique “shadow” that minimizes distance. This makes approximation natural: to approximate a complicated vector (say, a function), choose a convenient family of directions (basis functions) and drop the perpendicular—this is least squares in geometric clothing. If you keep adding more basis vectors, your approximation improves. Completeness says you never “fall out of the room”: even as you refine with infinitely many steps, the limit remains inside. For functions, Fourier series make this vivid—represent a complex waveform as a sum of sines and cosines. Each added term captures more detail, and completeness ensures the series converges in the L^2 sense. In computation we simulate this story by selecting a finite set of basis functions, computing coefficients (inner products), and forming truncated sums; the Hilbert space guarantees that, in principle, the truncations approach the true signal.

03Formal Definition

Let H be a vector space over \(R\) or \(C\) equipped with an inner product \(⟨ ⋅, ⋅ ⟩\) that is linear in its first argument, conjugate symmetric \(⟨ x, y ⟩ = ⟨y,x⟩​\), and positive definite \(⟨ x, x ⟩ > 0\) for \(x = 0\). The induced norm is \(\∣x∥ = ⟨x,x⟩​\), and the metric is \(d(x,y) = \∣x−y∥\). The space (H, \(⟨ ⋅, ⋅ ⟩\)) is a Hilbert space if it is complete with respect to this metric: every Cauchy sequence converges to a limit in H. A subspace M \(⊆\) H is closed if it contains all its limit points; for closed subspaces, the Projection Theorem asserts the existence of a unique decomposition \(x=PM​ x + (x - PM​ x)\) with \(PM​ x ∈ M\) and \(x - PM​ x ⊥ M\). An orthonormal set \(\{ei​\}_{i ∈ I}\) satisfies \(⟨ ei​, ej​ ⟩ = δij​\). If its linear span is dense in H, it is an orthonormal basis, and every \(x ∈ H\) has a (possibly infinite) expansion \(x = ∑i∈I​ ⟨ x, ei​ ⟩ ei​\), converging in norm. Canonical examples include \(Rn\) with the dot product, \(ℓ2 = \{(xk​): ∑ ∣xk​∣^2 < ∞\}\) with \(⟨ x, y ⟩ = ∑ xk​ yk​​\), and \(L2(Ω)\) with \(⟨ f, g ⟩ = ∫Ω​ f g​ \, dμ\).

04When to Use

Use Hilbert spaces when problems naturally involve geometry (lengths, angles) of potentially infinite-dimensional objects like functions or sequences. They are ideal for least-squares approximation and projection: fitting data, solving overdetermined systems, or projecting onto subspaces (e.g., filtering signals). In numerical PDEs, Galerkin and spectral methods choose a finite basis in a Hilbert space (often (L^2) or Sobolev spaces) and enforce orthogonality of the residual, turning differential equations into algebraic systems. In signal processing and harmonic analysis, trigonometric systems or wavelets serve as orthonormal bases; Parseval’s identity links energy in time and frequency domains. In machine learning, kernel methods can be interpreted in reproducing kernel Hilbert spaces (RKHS), where inner products are evaluated via kernels. In quantum mechanics, state vectors live in complex Hilbert spaces; observables are represented by self-adjoint operators, and orthogonal projections model measurements. Prefer Hilbert spaces over general Banach spaces when you need orthogonality, projections, or Pythagorean decompositions; choose other (L^p) spaces ((p \neq 2)) if the application’s natural metric or constraints demand it, but remember you lose inner-product geometry there.

⚠️Common Mistakes

  1. Confusing norms with inner products: not every norm comes from an inner product (e.g., (\ell^1) and (\ell^\infty)). To check, use the parallelogram law; if it fails, no inner product induces the norm. 2) Assuming completeness automatically: subspaces like smooth functions can be dense in (L^2) but not complete; work with closures or explicitly complete the space. 3) Misusing orthogonality in non-inner-product spaces: notions like projections that minimize distance rely on inner products; in general Banach spaces, nearest points need not be unique. 4) Forgetting to normalize bases: in computations (e.g., Fourier series), missing factors (like (1/\sqrt{2}) for the constant term) break orthonormality and distort coefficients. 5) Ignoring closedness: the Projection Theorem requires closed subspaces; projecting onto a non-closed subspace can fail to have a minimizer inside it. 6) Numerical pitfalls: classical Gram–Schmidt can lose orthogonality due to floating-point errors; prefer modified Gram–Schmidt or Householder QR. 7) Confusing pointwise and (L^2) convergence: Fourier series can converge in (L^2) without converging pointwise everywhere; the metric of the space dictates the notion of closeness. 8) Mixing real and complex conventions: inner product linearity may be in the first or second argument depending on the field; be consistent, especially when implementing adjoints.

Key Formulas

Inner product axioms

⟨x,y⟩=⟨y,x⟩​,⟨ax1​+bx2​,y⟩=a⟨x1​,y⟩+b⟨x2​,y⟩,⟨x,x⟩>0 (x=0)

Explanation: These properties define an inner product: conjugate symmetry, linearity, and positive definiteness. They ensure we can measure angles and lengths consistently.

Norm and metric from inner product

∥x∥=⟨x,x⟩​,d(x,y)=∥x−y∥

Explanation: The inner product induces a norm (length) and thus a distance function. This lets us talk about convergence and completeness.

Hilbert space criterion

Hilbert space⟺(H,⟨⋅,⋅⟩) is complete w.r.t. d(x,y)=∥x−y∥

Explanation: A Hilbert space is precisely an inner product space where every Cauchy sequence converges under the induced metric.

Cauchy–Schwarz

∣⟨x,y⟩∣≤∥x∥∥y∥

Explanation: The absolute value of the inner product is at most the product of the lengths. It bounds correlations and underlies many inequalities.

Parallelogram law

∥x+y∥2+∥x−y∥2=2∥x∥2+2∥y∥2

Explanation: Norms coming from inner products satisfy this identity; conversely, a norm that satisfies it arises from some inner product.

Triangle inequality

∥x+y∥≤∥x∥+∥y∥

Explanation: The length of a sum is at most the sum of lengths. It follows from Cauchy–Schwarz and the norm definition.

Pythagorean theorem (projection)

∥x∥2=∥PM​x∥2+∥x−PM​x∥2

Explanation: Decomposing a vector into a projection onto a closed subspace M and an orthogonal residual preserves energy.

Projection onto finite orthonormal set

PM​x=i=1∑n​⟨x,ei​⟩ei​

Explanation: To project onto the span of orthonormal vectors ei​, sum their inner-product coefficients times each basis vector.

Orthonormal expansion and Parseval

x=i∈I∑​⟨x,ei​⟩ei​,∥x∥2=i∈I∑​∣⟨x,ei​⟩∣2

Explanation: In a Hilbert space, an orthonormal basis gives coordinates for any vector, and total energy equals the sum of squared coefficients.

Bessel’s inequality

i=1∑n​∣⟨x,ei​⟩∣2≤∥x∥2

Explanation: Using only finitely many orthonormal vectors underestimates the total energy. Equality holds when the set spans the vector.

Fourier coefficients (orthonormalized on [0,2\pi])

a0​=⟨f,2​1​⟩,ak​=⟨f,cos(kx)⟩,bk​=⟨f,sin(kx)⟩

Explanation: With inner product \(⟨ f,g ⟩ = π1​ ∫02π​ f g\,dx\), the set {1/√2, cos kx, sin kx} is orthonormal and these are the coefficients.

Truncated Fourier series

SK​(x)=2​a0​​+k=1∑K​(ak​cos(kx)+bk​sin(kx))

Explanation: The best \(L2\)-approximation of f by trigonometric polynomials of degree K is its orthogonal projection onto that span.

L^2 inner product and norm

⟨f,g⟩=∫Ω​f(x)g(x)​dμ(x),∥f∥2​=∫Ω​∣f∣2dμ​

Explanation: This defines the Hilbert space structure on square-integrable functions over a measure space (\(Ω,μ\)).

Riesz representation

T(x)=⟨x,yT​⟩(∃! yT​∈H)

Explanation: Every continuous linear functional T on a Hilbert space H can be written as an inner product with a unique vector yT​.

Complexity Analysis

Finite-dimensional Hilbert space computations reduce to linear algebra. Basic operations on n-dimensional vectors—inner product, norm, and projection onto a single vector—take O(n) time and O(1) extra space. Projection onto a k-dimensional subspace spanned by an orthonormal set uses k inner products and k scaled vector additions, costing O(nk). If the basis is not orthonormal, you must solve a small k×k linear system (normal equations or QR), typically O(nk + k3) using QR for numerical stability. Orthonormalization of m vectors in Rn with modified Gram–Schmidt (MGS) costs O(n m2) time and O(n m) space for storing the basis. Householder QR has similar asymptotic cost O(n m2) but better numerical stability; classical Gram–Schmidt is faster in practice but can lose orthogonality due to rounding. For repeated projections of many vectors onto the same subspace, the upfront O(n m2) to build an orthonormal basis amortizes the cost of later O(n m) projections. Approximating L2 inner products and Fourier coefficients via numerical quadrature on N sample points with K modes costs O(NK) time and O(1)–O(N) space depending on whether you stream or store samples. If you instead use an FFT on uniform grids for trigonometric bases, you can reduce complexity to O(N log N) for all coefficients simultaneously. However, quadrature accuracy depends on smoothness and periodicity; trapezoidal rules are spectrally accurate for periodic smooth functions but degrade with discontinuities (Gibbs phenomenon), affecting the convergence in practice though L2 convergence still holds. Memory usage is modest: vectors require O(n) storage, orthonormal sets O(n m), and sampled functions O(N). Numerical stability concerns (loss of orthogonality, cancellation in inner products) should guide the choice of algorithms (MGS/Householder, compensated summation) when high accuracy is required.

Code Examples

Inner product, norm, and projection onto a line in R^n
1#include <bits/stdc++.h>
2using namespace std;
3
4// Compute inner product (dot product) in R^n
5double inner_product_vec(const vector<double>& x, const vector<double>& y) {
6 assert(x.size() == y.size());
7 // Kahan compensated summation to reduce floating-point error
8 double sum = 0.0, c = 0.0;
9 for (size_t i = 0; i < x.size(); ++i) {
10 double prod = x[i] * y[i] - c;
11 double t = sum + prod;
12 c = (t - sum) - prod;
13 sum = t;
14 }
15 return sum;
16}
17
18// Euclidean norm induced by the inner product
19double norm_vec(const vector<double>& x) {
20 return sqrt(max(0.0, inner_product_vec(x, x)));
21}
22
23// Project y onto the (closed) subspace span{x}. If x is the zero vector, returns zero vector.
24vector<double> project_onto_vector(const vector<double>& y, const vector<double>& x) {
25 vector<double> proj(y.size(), 0.0);
26 double denom = inner_product_vec(x, x);
27 if (denom == 0.0) return proj; // projection onto {0}
28 double alpha = inner_product_vec(y, x) / denom; // coefficient ⟨y,x⟩ / ⟨x,x⟩
29 for (size_t i = 0; i < y.size(); ++i) proj[i] = alpha * x[i];
30 return proj;
31}
32
33int main() {
34 // Example vectors in R^5
35 vector<double> x = {1, 2, 0, -1, 3};
36 vector<double> y = {4, 0, 1, 2, -2};
37
38 cout << fixed << setprecision(6);
39 cout << "<x,y> = " << inner_product_vec(x, y) << "\n";
40 cout << "||x|| = " << norm_vec(x) << ", ||y|| = " << norm_vec(y) << "\n";
41
42 vector<double> p = project_onto_vector(y, x);
43 // Residual r = y - p is orthogonal to x in exact arithmetic
44 vector<double> r(y.size());
45 for (size_t i = 0; i < y.size(); ++i) r[i] = y[i] - p[i];
46
47 cout << "Projection of y onto span{x}: [";
48 for (size_t i = 0; i < p.size(); ++i) cout << p[i] << (i+1==p.size()? "]\n" : ", ");
49
50 cout << "Orthogonality check <x, y - P x> = " << inner_product_vec(x, r) << " (should be ~0)\n";
51 return 0;
52}
53

This program defines an inner product (with compensated summation), computes the induced norm, and projects a vector y onto the one-dimensional subspace spanned by x. The residual is orthogonal to x by construction, illustrating the Projection Theorem in a finite-dimensional Hilbert space (R^n with the dot product).

Time: O(n)Space: O(n)
Modified Gram–Schmidt orthonormalization and projection onto a subspace
1#include <bits/stdc++.h>
2using namespace std;
3
4// Inner product and norm as before
5double inner_product_vec(const vector<double>& x, const vector<double>& y) {
6 assert(x.size() == y.size());
7 double sum = 0.0, c = 0.0;
8 for (size_t i = 0; i < x.size(); ++i) {
9 double prod = x[i] * y[i] - c;
10 double t = sum + prod;
11 c = (t - sum) - prod;
12 sum = t;
13 }
14 return sum;
15}
16
17double norm_vec(const vector<double>& x) { return sqrt(max(0.0, inner_product_vec(x, x))); }
18
19// Modified Gram-Schmidt: orthonormalize columns in V (vectors of dimension n)
20vector<vector<double>> modified_gram_schmidt(const vector<vector<double>>& V) {
21 size_t m = V.size();
22 if (m == 0) return {};
23 size_t n = V[0].size();
24 for (size_t i = 1; i < m; ++i) assert(V[i].size() == n);
25
26 vector<vector<double>> Q; // orthonormal vectors
27 Q.reserve(m);
28
29 for (size_t j = 0; j < m; ++j) {
30 vector<double> v = V[j]; // copy to modify
31 // subtract projections onto previous q_i
32 for (size_t i = 0; i < Q.size(); ++i) {
33 double rij = inner_product_vec(Q[i], v);
34 for (size_t k = 0; k < n; ++k) v[k] -= rij * Q[i][k];
35 }
36 double normv = norm_vec(v);
37 if (normv > 0) {
38 for (size_t k = 0; k < n; ++k) v[k] /= normv; // normalize
39 Q.push_back(move(v));
40 } else {
41 // dependent vector; skip
42 }
43 }
44 return Q;
45}
46
47// Project vector b onto span(Q) where Q is orthonormal
48vector<double> project_onto_subspace(const vector<double>& b, const vector<vector<double>>& Q) {
49 size_t n = b.size();
50 vector<double> p(n, 0.0);
51 for (const auto& q : Q) {
52 double coeff = inner_product_vec(b, q); // ⟨b, q⟩
53 for (size_t i = 0; i < n; ++i) p[i] += coeff * q[i];
54 }
55 return p;
56}
57
58int main() {
59 // Columns (as vectors) of a design matrix in R^4
60 vector<vector<double>> V = {
61 {1, 1, 1, 1}, // constant
62 {-1, 0, 1, 2}, // linear-ish
63 {1, 0, 1, 4} // quadratic-ish
64 };
65 // Orthonormalize columns
66 auto Q = modified_gram_schmidt(V);
67
68 // Vector to approximate (e.g., measurements)
69 vector<double> b = {0.9, 1.0, 2.2, 2.8};
70
71 auto p = project_onto_subspace(b, Q); // least-squares approximation
72
73 cout << fixed << setprecision(6);
74 cout << "Orthonormal basis size: " << Q.size() << "\n";
75 // Check orthonormality
76 for (size_t i = 0; i < Q.size(); ++i) {
77 for (size_t j = i; j < Q.size(); ++j) {
78 cout << "<q" << i << ", q" << j << "> = " << inner_product_vec(Q[i], Q[j]) << "\n";
79 }
80 }
81
82 // Report projection and residual norm
83 double res_norm = 0.0;
84 cout << "Projection p = [";
85 for (size_t i = 0; i < p.size(); ++i) {
86 cout << p[i] << (i + 1 == p.size() ? "]\n" : ", ");
87 }
88 vector<double> r(b.size());
89 for (size_t i = 0; i < b.size(); ++i) r[i] = b[i] - p[i];
90 cout << "Residual norm ||b - p|| = " << norm_vec(r) << "\n";
91 return 0;
92}
93

This program implements modified Gram–Schmidt to orthonormalize a set of vectors (columns of a design matrix). It then projects a data vector b onto the span of the orthonormal set, yielding the least-squares approximation. Orthonormalization makes the projection coefficients simply inner products, and the residual is orthogonal to the subspace.

Time: O(n m^2) to build Q and O(n m) per projectionSpace: O(n m)
Fourier projection in L^2(0, 2π) via numerical integration (trapezoidal rule)
1#include <bits/stdc++.h>
2using namespace std;
3
4// Approximate the inner product <f,g> = (1/pi) * ∫_0^{2π} f(x) g(x) dx using the trapezoidal rule.
5// For periodic smooth functions, this rule is highly accurate on uniform grids.
6const double PI = acos(-1.0);
7
8double inner_product_periodic(function<double(double)> f,
9 function<double(double)> g,
10 int N) {
11 // N uniform samples on [0, 2π]
12 double h = 2.0 * PI / N;
13 auto w = [&](int i){ return (i==0 || i==N) ? 0.5 : 1.0; }; // trapezoid weights at endpoints
14
15 double sum = 0.0;
16 for (int i = 0; i <= N; ++i) {
17 double x = i * h;
18 double fx = f(x);
19 double gx = g(x);
20 sum += w(i) * fx * gx;
21 }
22 return (1.0 / PI) * h * sum; // (1/π) * integral approximation
23}
24
25// Orthonormal trigonometric system on [0, 2π] under <f,g> = (1/π)∫ f g : {1/√2, cos(kx), sin(kx)}
26struct FourierCoeffs {
27 double a0_over_sqrt2; // coefficient for 1/√2
28 vector<double> a; // cos coefficients
29 vector<double> b; // sin coefficients
30};
31
32FourierCoeffs project_fourier(function<double(double)> f, int K, int Nsamples) {
33 FourierCoeffs c; c.a.resize(K+1); c.b.resize(K+1);
34 // constant basis e0 = 1/√2
35 c.a0_over_sqrt2 = inner_product_periodic(f, [](double){ return 1.0 / sqrt(2.0); }, Nsamples);
36 for (int k = 1; k <= K; ++k) {
37 auto cosk = [k](double x){ return cos(k * x); };
38 auto sink = [k](double x){ return sin(k * x); };
39 c.a[k] = inner_product_periodic(f, cosk, Nsamples);
40 c.b[k] = inner_product_periodic(f, sink, Nsamples);
41 }
42 return c;
43}
44
45// Evaluate truncated Fourier series S_K at x
46double fourier_partial_sum(const FourierCoeffs& c, double x) {
47 int K = (int)c.a.size() - 1;
48 double s = c.a0_over_sqrt2 / sqrt(2.0); // a0 * (1/√2)
49 for (int k = 1; k <= K; ++k) s += c.a[k] * cos(k*x) + c.b[k] * sin(k*x);
50 return s;
51}
52
53int main() {
54 cout << fixed << setprecision(6);
55
56 // Target function in L^2(0,2π): f(x) = x (not periodic in value, but square-integrable; expect Gibbs near endpoints)
57 auto f = [](double x){ return x; };
58
59 int K = 10; // number of Fourier modes
60 int N = 4096; // quadrature samples (even, large improves accuracy)
61
62 auto coeffs = project_fourier(f, K, N);
63
64 // Report a few coefficients
65 cout << "a0/√2 = " << coeffs.a0_over_sqrt2 << "\n";
66 for (int k = 1; k <= min(K, 5); ++k) {
67 cout << "a[" << k << "] = " << coeffs.a[k] << ", b[" << k << "] = " << coeffs.b[k] << "\n";
68 }
69
70 // Compute L^2-like error on grid: sqrt((1/π)∫ |f - S_K|^2)
71 double h = 2.0 * PI / N;
72 double sum = 0.0;
73 for (int i = 0; i <= N; ++i) {
74 double x = i * h;
75 double fx = f(x);
76 double sk = fourier_partial_sum(coeffs, x);
77 double w = (i==0 || i==N) ? 0.5 : 1.0; // trapezoid weight
78 sum += w * (fx - sk) * (fx - sk);
79 }
80 double l2err = sqrt((1.0 / PI) * h * sum);
81 cout << "Approximate L2 error with K=" << K << " is " << l2err << "\n";
82
83 // Show reconstruction at a few points
84 for (double x : {0.0, PI/2, PI, 3*PI/2, 2*PI}) {
85 cout << "x=" << x << ": f(x)=" << f(x) << ", S_K(x)=" << fourier_partial_sum(coeffs, x) << "\n";
86 }
87
88 return 0;
89}
90

This program treats L^2(0, 2π) with inner product ⟨f, g⟩ = (1/π)∫ f g and computes the orthogonal projection of a function f onto the span of the first K trigonometric basis functions using the trapezoidal rule. It prints Fourier coefficients, evaluates the truncated series, and estimates the L^2 error, illustrating projection and Parseval/least-squares ideas in Hilbert spaces.

Time: O(N K) for K coefficients on N samplesSpace: O(1) additional space beyond storing a few vectors
#hilbert space#inner product#l2 space#orthonormal basis#projection theorem#gram-schmidt#parseval identity#fourier series#cauchy schwarz#least squares#closed subspace#riesz representation#bessel inequality#modified gram schmidt#trapezoidal rule