-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgram_schmidt.h
79 lines (65 loc) · 1.92 KB
/
gram_schmidt.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
//
// Copyright Chong Peng 2017
//
#ifndef CODE_EXAMLE_GRAM_SCHMIDT_H_
#define CODE_EXAMLE_GRAM_SCHMIDT_H_
#include <vector>
namespace code_example {
/**
* Gram-Schmidt Algorithm
*
* Orthonormalising a set of vectors, which is templated as Array
*
* Required interface for Array
*
* - `element_type dot_product(const Array& a, const Array& b)` return dot product of 2 Array a and b
* - `void scale(Array& y , element_type a)` scale Array y by factor a
* - `void axpy(Array&y , element_tye a, const Array& x)` performs y += a*x
* - `element_type norm2(const Array& a)` return the L^2 norm of Array a
*/
/**
* orthonomalize all Array in vector V, starting from position 0
*/
template <typename Array>
void gram_schmidt(std::vector<Array> &V, std::size_t start = 0) {
const auto original_k = V.size();
const auto k = V.size();
std::size_t n_neglect = 0;
assert(start < k);
for (std::size_t i = start; i < k; ++i) {
for (std::size_t j = 0; j < i; ++j) {
const auto tmp = dot_product(V[i], V[j]);
axpy(V[i], -tmp, V[j]);
}
// normalize
auto norm = norm2(V[i]);
scale(V[i], 1.0 / norm2(V[i]));
}
}
/**
* vector V1 is already orthonormalized
* orthonormalize V2 with respect to V1
*/
template <typename Array>
void gram_schmidt(const std::vector<Array> &V1, std::vector<Array> &V2) {
const auto original_k = V2.size();
const auto k1 = V1.size();
auto k2 = V2.size();
std::size_t n_neglect = 0;
for (std::size_t i = 0; i < k2; ++i) {
// loop over all vector in V1
for (std::size_t j = 0; j < k1; ++j) {
auto tmp = dot_product(V2[i], V1[j]);
axpy(V2[i], -tmp, V1[j]);
}
// loop over other vector in V2
for (std::size_t k = 0; k < i; ++k) {
auto tmp = dot_product(V2[i], V2[k]);
axpy(V2[i], -tmp, V2[k]);
}
auto norm = norm2(V2[i]);
scale(V2[i], 1.0 / norm);
}
}
} // namespace code_example
#endif // CODE_EXAMLE_GRAM_SCHMIDT_H_