43 std::vector<std::vector<double> > m_upper;
44 std::vector<std::vector<double> > m_lower;
47 band_matrix(
int dim,
int n_u,
int n_l);
49 void resize(
int dim,
int n_u,
int n_l);
51 int num_upper()
const {
52 return m_upper.size() - 1;
54 int num_lower()
const {
55 return m_lower.size() - 1;
58 double& operator()(
int i,
int j);
59 double operator()(
int i,
int j)
const;
61 double& saved_diag(
int i);
62 double saved_diag(
int i)
const;
64 std::vector<double> r_solve(
const std::vector<double>&
b)
const;
65 std::vector<double> l_solve(
const std::vector<double>&
b)
const;
66 std::vector<double> lu_solve(
const std::vector<double>&
b,
bool is_lu_decomposed =
false);
75 std::vector<double> m_x, m_y;
78 std::vector<double> m_a, m_b, m_c;
80 bd_type m_left, m_right;
81 double m_left_value, m_right_value;
82 bool m_force_linear_extrapolation;
87 : m_left(second_deriv),
88 m_right(second_deriv),
91 m_force_linear_extrapolation(
false) {
96 void set_boundary(bd_type
left,
double left_value, bd_type
right,
double right_value,
97 bool force_linear_extrapolation =
false);
98 void set_points(
const std::vector<double>&
x,
const std::vector<double>&
y,
bool cubic_spline =
true);
99 double operator()(
double x)
const;
109 band_matrix::band_matrix(
int dim,
int n_u,
int n_l) {
110 resize(dim, n_u, n_l);
112 void band_matrix::resize(
int dim,
int n_u,
int n_l) {
116 m_upper.resize(n_u + 1);
117 m_lower.resize(n_l + 1);
118 for (
size_t i = 0;
i < m_upper.size();
i++) {
119 m_upper[
i].resize(dim);
121 for (
size_t i = 0;
i < m_lower.size();
i++) {
122 m_lower[
i].resize(dim);
125 int band_matrix::dim()
const {
126 if (m_upper.size() > 0) {
127 return m_upper[0].size();
135 double& band_matrix::operator()(
int i,
int j) {
137 assert((
i >= 0) && (
i < dim()) && (
j >= 0) && (
j < dim()));
138 assert((-num_lower() <=
k) && (
k <= num_upper()));
141 return m_upper[
k][
i];
143 return m_lower[-
k][
i];
145 double band_matrix::operator()(
int i,
int j)
const {
147 assert((
i >= 0) && (
i < dim()) && (
j >= 0) && (
j < dim()));
148 assert((-num_lower() <=
k) && (
k <= num_upper()));
151 return m_upper[
k][
i];
153 return m_lower[-
k][
i];
156 double band_matrix::saved_diag(
int i)
const {
157 assert((
i >= 0) && (
i < dim()));
158 return m_lower[0][
i];
160 double& band_matrix::saved_diag(
int i) {
161 assert((
i >= 0) && (
i < dim()));
162 return m_lower[0][
i];
166 void band_matrix::lu_decompose() {
173 for (
int i = 0;
i < this->dim();
i++) {
174 assert(this->
operator()(i,
i) != 0.0);
175 this->saved_diag(
i) = 1.0 / this->operator()(
i,
i);
176 j_min =
std::max(0,
i - this->num_lower());
177 j_max =
std::min(this->dim() - 1,
i + this->num_upper());
178 for (
int j = j_min;
j <= j_max;
j++) {
179 this->operator()(
i,
j) *= this->saved_diag(
i);
181 this->operator()(
i,
i) = 1.0;
185 for (
int k = 0;
k < this->dim();
k++) {
186 i_max =
std::min(this->dim() - 1,
k + this->num_lower());
187 for (
int i =
k + 1;
i <= i_max;
i++) {
188 assert(this->
operator()(
k,
k) != 0.0);
189 x = -this->operator()(
i,
k) / this->operator()(
k,
k);
190 this->operator()(
i,
k) = -
x;
191 j_max =
std::min(this->dim() - 1,
k + this->num_upper());
192 for (
int j =
k + 1;
j <= j_max;
j++) {
194 this->operator()(
i,
j) = this->operator()(
i,
j) +
x * this->operator()(
k,
j);
200 std::vector<double> band_matrix::l_solve(
const std::vector<double>&
b)
const {
201 assert(this->dim() == (
int)
b.size());
202 std::vector<double>
x(this->dim());
205 for (
int i = 0;
i < this->dim();
i++) {
207 j_start =
std::max(0,
i - this->num_lower());
208 for (
int j = j_start;
j <
i;
j++)
209 sum += this->
operator()(
i,
j) * x[
j];
210 x[
i] = (
b[
i] * this->saved_diag(
i)) - sum;
215 std::vector<double> band_matrix::r_solve(
const std::vector<double>&
b)
const {
216 assert(this->dim() == (
int)
b.size());
217 std::vector<double>
x(this->dim());
220 for (
int i = this->dim() - 1;
i >= 0;
i--) {
222 j_stop =
std::min(this->dim() - 1,
i + this->num_upper());
223 for (
int j =
i + 1;
j <= j_stop;
j++)
224 sum += this->
operator()(
i,
j) * x[
j];
225 x[
i] = (
b[
i] - sum) / this->
operator()(
i,
i);
230 std::vector<double> band_matrix::lu_solve(
const std::vector<double>&
b,
bool is_lu_decomposed) {
231 assert(this->dim() == (
int)
b.size());
232 std::vector<double>
x,
y;
233 if (is_lu_decomposed ==
false) {
234 this->lu_decompose();
236 y = this->l_solve(
b);
237 x = this->r_solve(
y);
244 void spline::set_boundary(spline::bd_type
left,
double left_value, spline::bd_type
right,
double right_value,
245 bool force_linear_extrapolation) {
246 assert(m_x.size() == 0);
249 m_left_value = left_value;
250 m_right_value = right_value;
251 m_force_linear_extrapolation = force_linear_extrapolation;
254 void spline::set_points(
const std::vector<double>&
x,
const std::vector<double>&
y,
bool cubic_spline) {
255 assert(
x.size() ==
y.size());
256 assert(
x.size() > 2);
261 for (
int i = 0;
i < n - 1;
i++) {
262 assert(m_x[
i] < m_x[
i + 1]);
265 if (cubic_spline ==
true) {
268 band_matrix
A(n, 1, 1);
269 std::vector<double> rhs(n);
270 for (
int i = 1;
i < n - 1;
i++) {
271 A(
i,
i - 1) = 1.0 / 3.0 * (
x[
i] -
x[
i - 1]);
272 A(
i,
i) = 2.0 / 3.0 * (
x[
i + 1] -
x[
i - 1]);
273 A(
i,
i + 1) = 1.0 / 3.0 * (
x[
i + 1] -
x[
i]);
274 rhs[
i] = (
y[
i + 1] -
y[
i]) / (
x[
i + 1] -
x[
i]) - (
y[
i] -
y[
i - 1]) / (
x[
i] -
x[
i - 1]);
277 if (m_left == spline::second_deriv) {
281 rhs[0] = m_left_value;
285 A(0, 0) = 2.0 * (
x[1] -
x[0]);
286 A(0, 1) = 1.0 * (
x[1] -
x[0]);
287 rhs[0] = 3.0 * ((
y[1] -
y[0]) / (
x[1] -
x[0]) - m_left_value);
291 if (m_right == spline::second_deriv) {
293 A(n - 1, n - 1) = 2.0;
294 A(n - 1, n - 2) = 0.0;
295 rhs[n - 1] = m_right_value;
300 A(n - 1, n - 1) = 2.0 * (
x[n - 1] -
x[n - 2]);
301 A(n - 1, n - 2) = 1.0 * (
x[n - 1] -
x[n - 2]);
302 rhs[n - 1] = 3.0 * (m_right_value - (
y[n - 1] -
y[n - 2]) / (
x[n - 1] -
x[n - 2]));
308 m_b =
A.lu_solve(rhs);
313 for (
int i = 0;
i < n - 1;
i++) {
314 m_a[
i] = 1.0 / 3.0 * (m_b[
i + 1] - m_b[
i]) / (
x[
i + 1] -
x[
i]);
315 m_c[
i] = (
y[
i + 1] -
y[
i]) / (
x[
i + 1] -
x[
i]) -
316 1.0 / 3.0 * (2.0 * m_b[
i] + m_b[
i + 1]) * (
x[
i + 1] -
x[
i]);
322 for (
int i = 0;
i < n - 1;
i++) {
325 m_c[
i] = (m_y[
i + 1] - m_y[
i]) / (m_x[
i + 1] - m_x[
i]);
330 m_b0 = (m_force_linear_extrapolation ==
false) ? m_b[0] : 0.0;
335 double h =
x[n - 1] -
x[n - 2];
338 m_c[n - 1] = 3.0 * m_a[n - 2] *
h *
h + 2.0 * m_b[n - 2] *
h + m_c[n - 2];
339 if (m_force_linear_extrapolation ==
true)
343 double spline::operator()(
double x)
const {
344 size_t n = m_x.size();
346 std::vector<double>::const_iterator it;
347 it = std::lower_bound(m_x.begin(), m_x.end(),
x);
348 int idx =
std::max(
int(it - m_x.begin()) - 1, 0);
350 double h =
x - m_x[idx];
354 interpol = (m_b0 *
h + m_c0) *
h + m_y[0];
355 }
else if (
x > m_x[n - 1]) {
357 interpol = (m_b[n - 1] *
h + m_c[n - 1]) *
h + m_y[n - 1];
360 interpol = ((m_a[idx] *
h + m_b[idx]) *
h + m_c[idx]) *
h + m_y[idx];