Chebyshev2.cpp
Go to the documentation of this file.
1 /* ----------------------------------------------------------------------------
2 
3  * GTSAM Copyright 2010, Georgia Tech Research Corporation,
4  * Atlanta, Georgia 30332-0415
5  * All Rights Reserved
6  * Authors: Frank Dellaert, et al. (see THANKS for the full author list)
7 
8  * See LICENSE for the license information
9 
10  * -------------------------------------------------------------------------- */
11 
19 #include <gtsam/basis/Chebyshev2.h>
20 
21 #include <Eigen/Dense>
22 
23 #include <cassert>
24 
25 namespace gtsam {
26 
27 double Chebyshev2::Point(size_t N, int j) {
28  if (N == 1) return 0.0;
29  assert(j >= 0 && size_t(j) < N);
30  const double dTheta = M_PI / (N - 1);
31  return -cos(dTheta * j);
32 }
33 
34 double Chebyshev2::Point(size_t N, int j, double a, double b) {
35  if (N == 1) return (a + b) / 2;
36  return a + (b - a) * (Point(N, j) + 1.0) / 2.0;
37 }
38 
40  Vector points(N);
41  if (N == 1) {
42  points(0) = 0.0;
43  return points;
44  }
45  size_t half = N / 2;
46  const double dTheta = M_PI / (N - 1);
47  for (size_t j = 0; j < half; ++j) {
48  double c = cos(j * dTheta);
49  points(j) = -c;
50  points(N - 1 - j) = c;
51  }
52  if (N % 2 == 1) {
53  points(half) = 0.0;
54  }
55  return points;
56 }
57 
58 Vector Chebyshev2::Points(size_t N, double a, double b) {
59  Vector points = Points(N);
60  const double T1 = (a + b) / 2, T2 = (b - a) / 2;
61  points = T1 + (T2 * points).array();
62  return points;
63 }
64 
65 namespace {
66  // Find the index of the Chebyshev point that coincides with x
67  // within the interval [a, b]. If no such point exists, return nullopt.
68  std::optional<size_t> coincidentPoint(size_t N, double x, double a, double b, double tol = 1e-12) {
69  if (N == 0) return std::nullopt;
70  if (N == 1) {
71  double mid = (a + b) / 2;
72  if (std::abs(x - mid) < tol) return 0;
73  } else {
74  // Compute normalized value y such that cos(j*dTheta) = y.
75  double y = 1.0 - 2.0 * (x - a) / (b - a);
76  if (y < -1.0 || y > 1.0) return std::nullopt;
77  double dTheta = M_PI / (N - 1);
78  double jCandidate = std::acos(y) / dTheta;
79  size_t jRounded = static_cast<size_t>(std::round(jCandidate));
80  if (std::abs(jCandidate - jRounded) < tol) return jRounded;
81  }
82  return std::nullopt;
83  }
84 
85  // Get signed distances from x to all Chebyshev points
86  Vector signedDistances(size_t N, double x, double a, double b) {
87  Vector result(N);
88  const Vector points = Chebyshev2::Points(N, a, b);
89  for (size_t j = 0; j < N; j++) {
90  const double dj = x - points[j];
91  result(j) = dj;
92  }
93  return result;
94  }
95 
96  // Helper function to calculate a row of the differentiation matrix, [-1,1] interval
97  Vector differentiationMatrixRow(size_t N, const Vector& points, size_t i) {
98  Vector row(N);
99  const size_t K = N - 1;
100  double xi = points(i);
101  for (size_t j = 0; j < N; j++) {
102  if (i == j) {
103  // Diagonal elements
104  if (i == 0 || i == K)
105  row(j) = (i == 0 ? -1 : 1) * (2.0 * K * K + 1) / 6.0;
106  else
107  row(j) = -xi / (2.0 * (1.0 - xi * xi));
108  }
109  else {
110  double xj = points(j);
111  double ci = (i == 0 || i == K) ? 2. : 1.;
112  double cj = (j == 0 || j == K) ? 2. : 1.;
113  double t = ((i + j) % 2) == 0 ? 1 : -1;
114  row(j) = (ci / cj) * t / (xi - xj);
115  }
116  }
117  return row;
118  }
119 } // namespace
120 
121 Weights Chebyshev2::CalculateWeights(size_t N, double x, double a, double b) {
122  // We start by getting distances from x to all Chebyshev points
123  const Vector distances = signedDistances(N, x, a, b);
124 
125  Weights weights(N);
126  if (auto j = coincidentPoint(N, x, a, b)) {
127  // exceptional case: x coincides with a Chebyshev point
128  weights.setZero();
129  weights(*j) = 1;
130  return weights;
131  }
132 
133  // Beginning of interval, j = 0, x(0) = a
134  weights(0) = 0.5 / distances(0);
135 
136  // All intermediate points j=1:N-2
137  double d = weights(0), s = -1; // changes sign s at every iteration
138  for (size_t j = 1; j < N - 1; j++, s = -s) {
139  weights(j) = s / distances(j);
140  d += weights(j);
141  }
142 
143  // End of interval, j = N-1, x(N-1) = b
144  weights(N - 1) = 0.5 * s / distances(N - 1);
145  d += weights(N - 1);
146 
147  // normalize
148  return weights / d;
149 }
150 
151 Weights Chebyshev2::DerivativeWeights(size_t N, double x, double a, double b) {
152  if (auto j = coincidentPoint(N, x, a, b)) {
153  // exceptional case: x coincides with a Chebyshev point
154  return differentiationMatrixRow(N, Points(N), *j) / ((b - a) / 2.0);
155  }
156 
157  // This section of code computes the derivative of
158  // the Barycentric Interpolation weights formula by applying
159  // the chain rule on the original formula.
160 
161  // g and k are multiplier terms which represent the derivatives of
162  // the numerator and denominator
163  double g = 0, k = 0;
164  double w;
165 
166  const Vector distances = signedDistances(N, x, a, b);
167  for (size_t j = 0; j < N; j++) {
168  if (j == 0 || j == N - 1) {
169  w = 0.5;
170  } else {
171  w = 1.0;
172  }
173 
174  double t = (j % 2 == 0) ? 1 : -1;
175 
176  double c = t / distances(j);
177  g += w * c;
178  k += (w * c / distances(j));
179  }
180 
181  double s = 1; // changes sign s at every iteration
182  double g2 = g * g;
183 
184  Weights weightDerivatives(N);
185  for (size_t j = 0; j < N; j++) {
186  // Beginning of interval, j = 0, x0 = -1.0 and end of interval, j = N-1,
187  // x0 = 1.0
188  if (j == 0 || j == N - 1) {
189  w = 0.5;
190  } else {
191  // All intermediate points j=1:N-2
192  w = 1.0;
193  }
194  weightDerivatives(j) = (w * -s / (g * distances(j) * distances(j))) -
195  (w * -s * k / (g2 * distances(j)));
196  s *= -1;
197  }
198 
199  return weightDerivatives;
200 }
201 
203  DiffMatrix D(N, N);
204  if (N == 1) {
205  D(0, 0) = 1;
206  return D;
207  }
208 
209  const Vector points = Points(N);
210  for (size_t i = 0; i < N; i++) {
211  D.row(i) = differentiationMatrixRow(N, points, i);
212  }
213  return D;
214 }
215 
217  DiffMatrix D(N, N);
218  if (N == 1) {
219  D(0, 0) = 1;
220  return D;
221  }
222 
223  // Calculate for [-1,1] and scale for [a,b]
224  return DifferentiationMatrix(N) / ((b - a) / 2.0);
225 }
226 
228  // Obtain the differentiation matrix.
229  const Matrix D = DifferentiationMatrix(N);
230 
231  // Compute the pseudo-inverse of the differentiation matrix.
233  const auto& S = svd.singularValues();
234  Matrix invS = Matrix::Zero(N, N);
235  for (size_t i = 0; i < N - 1; ++i) invS(i, i) = 1.0 / S(i);
236  Matrix P = svd.matrixV() * invS * svd.matrixU().transpose();
237 
238  // Return a version of P that makes sure (P*f)(0) = 0.
239  const Weights row0 = P.row(0);
240  P.rowwise() -= row0;
241  return P;
242 }
243 
244 Matrix Chebyshev2::IntegrationMatrix(size_t N, double a, double b) {
245  return IntegrationMatrix(N) * (b - a) / 2.0;
246 }
247 
248 /*
249  Trefethen00book, pg 128, clencurt.m
250  Note that N in clencurt.m is 1 less than our N, we call it K below.
251  K = N-1;
252  theta = pi*(0:K)'/K;
253  w = zeros(1,N); ii = 2:K; v = ones(K-1, 1);
254  if mod(K,2) == 0
255  w(1) = 1/(K^2-1); w(N) = w(1);
256  for k=1:K/2-1, v = v-2*cos(2*k*theta(ii))/(4*k^2-1); end
257  v = v - cos(K*theta(ii))/(K^2-1);
258  else
259  w(1) = 1/K^2; w(N) = w(1);
260  for k=1:K/2, v = v-2*cos(2*k*theta(ii))/(4*k^2-1); end
261  end
262  w(ii) = 2*v/K;
263 */
265  Weights weights(N);
266  const size_t K = N - 1, // number of intervals between N points
267  K2 = K * K;
268 
269  // Compute endpoint weight.
270  weights(0) = 1.0 / (K2 + K % 2 - 1);
271  weights(N - 1) = weights(0);
272 
273  // Compute up to the middle; mirror symmetry holds.
274  const size_t mid = (N - 1) / 2;
275  double dTheta = M_PI / K;
276  for (size_t i = 1; i <= mid; ++i) {
277  double w = (K % 2 == 0) ? 1 - cos(i * M_PI) / (K2 - 1) : 1;
278  const size_t last_k = K / 2 + K % 2 - 1;
279  const double theta = i * dTheta;
280  for (size_t k = 1; k <= last_k; ++k)
281  w -= 2.0 * cos(2 * k * theta) / (4 * k * k - 1);
282  w *= 2.0 / K;
283  weights(i) = w;
284  weights(N - 1 - i) = w;
285  }
286  return weights;
287 }
288 
289 Weights Chebyshev2::IntegrationWeights(size_t N, double a, double b) {
290  return IntegrationWeights(N) * (b - a) / 2.0;
291 }
292 
294  // we have w * P, where w are the Clenshaw-Curtis weights and P is the integration matrix
295  // But P does not by default return a function starting at zero.
297 }
298 
301 }
302 
306 Vector Chebyshev2::vector(std::function<double(double)> f, size_t N, double a, double b) {
307  Vector fvals(N);
308  const Vector points = Points(N, a, b);
309  for (size_t j = 0; j < N; j++) fvals(j) = f(points(j));
310  return fvals;
311 }
312 
313 } // namespace gtsam
w
RowVector3d w
Definition: Matrix_resize_int.cpp:3
Chebyshev2.h
Pseudo-spectral parameterization for Chebyshev polynomials of the second kind.
D
MatrixXcd D
Definition: EigenSolver_EigenSolver_MatrixType.cpp:14
array
int array[24]
Definition: Map_general_stride.cpp:1
s
RealScalar s
Definition: level1_cplx_impl.h:126
e
Array< double, 1, 3 > e(1./3., 0.5, 2.)
d
static const double d[K][N]
Definition: igam.h:11
screwPose2::xi
Vector xi
Definition: testPose2.cpp:169
gtsam::Chebyshev2::DifferentiationMatrix
static DiffMatrix DifferentiationMatrix(size_t N)
Definition: Chebyshev2.cpp:202
gtsam::Chebyshev2::IntegrationMatrix
static Matrix IntegrationMatrix(size_t N)
Definition: Chebyshev2.cpp:227
c
Scalar Scalar * c
Definition: benchVecAdd.cpp:17
x
set noclip points set clip one set noclip two set bar set border lt lw set xdata set ydata set zdata set x2data set y2data set boxwidth set dummy x
Definition: gnuplot_common_settings.hh:12
gtsam::Matrix
Eigen::MatrixXd Matrix
Definition: base/Matrix.h:39
K2
static const Cal3Bundler K2(625, 1e-3, 1e-3)
gtsam::Vector
Eigen::VectorXd Vector
Definition: Vector.h:39
result
Values result
Definition: OdometryOptimize.cpp:8
ceres::acos
Jet< T, N > acos(const Jet< T, N > &f)
Definition: jet.h:432
ceres::cos
Jet< T, N > cos(const Jet< T, N > &f)
Definition: jet.h:426
j
std::ptrdiff_t j
Definition: tut_arithmetic_redux_minmax.cpp:2
gtsam::row
const MATRIX::ConstRowXpr row(const MATRIX &A, size_t j)
Definition: base/Matrix.h:215
Eigen::ComputeThinU
@ ComputeThinU
Definition: Constants.h:395
g2
Pose3 g2(g1.expmap(h *V1_g1))
round
double round(double x)
Definition: round.c:38
T2
static const Pose3 T2(Rot3::Rodrigues(0.3, 0.2, 0.1), P2)
g
void g(const string &key, int i)
Definition: testBTree.cpp:41
y
Scalar * y
Definition: level1_cplx_impl.h:124
gtsam::svd
void svd(const Matrix &A, Matrix &U, Vector &S, Matrix &V)
Definition: Matrix.cpp:548
gtsam::Chebyshev2::IntegrationWeights
static Weights IntegrationWeights(size_t N)
Definition: Chebyshev2.cpp:264
tree::f
Point2(* f)(const Point3 &, OptionalJacobian< 2, 3 >)
Definition: testExpression.cpp:218
gtsam::b
const G & b
Definition: Group.h:79
Eigen::JacobiSVD
Two-sided Jacobi SVD decomposition of a rectangular matrix.
Definition: ForwardDeclarations.h:278
gtsam::Chebyshev2::CalculateWeights
static Weights CalculateWeights(size_t N, double x, double a=-1, double b=1)
Definition: Chebyshev2.cpp:121
a
ArrayXXi a
Definition: Array_initializer_list_23_cxx11.cpp:1
Eigen::ComputeThinV
@ ComputeThinV
Definition: Constants.h:399
gtsam
traits
Definition: SFMdata.h:40
K
#define K
Definition: igam.h:8
gtsam::Chebyshev2::Points
static Vector Points(size_t N)
All Chebyshev points.
Definition: Chebyshev2.cpp:39
P
static double P[]
Definition: ellpe.c:68
gtsam::tol
const G double tol
Definition: Group.h:79
Eigen::Matrix< double, 1, -1 >
abs
#define abs(x)
Definition: datatypes.h:17
N
#define N
Definition: igam.h:9
Eigen::PlainObjectBase::setZero
EIGEN_DEVICE_FUNC Derived & setZero(Index size)
Definition: CwiseNullaryOp.h:562
M_PI
#define M_PI
Definition: mconf.h:117
T1
static const Similarity3 T1(R, Point3(3.5, -8.2, 4.2), 1)
align_3::t
Point2 t(10, 10)
gtsam::Chebyshev2::DoubleIntegrationWeights
static Weights DoubleIntegrationWeights(size_t N)
Definition: Chebyshev2.cpp:293
gtsam::Chebyshev2::vector
static Vector vector(std::function< double(double)> f, size_t N, double a=-1, double b=1)
Create matrix of values at Chebyshev points given vector-valued function.
Definition: Chebyshev2.cpp:306
gtsam::Chebyshev2::Point
static double Point(size_t N, int j)
Specific Chebyshev point, within [-1,1] interval.
Definition: Chebyshev2.cpp:27
i
int i
Definition: BiCGSTAB_step_by_step.cpp:9
gtsam::Chebyshev2::DerivativeWeights
static Weights DerivativeWeights(size_t N, double x, double a=-1, double b=1)
Definition: Chebyshev2.cpp:151
S
DiscreteKey S(1, 2)


gtsam
Author(s):
autogenerated on Fri Mar 28 2025 03:01:13