GeographicLib 2.6
Loading...
Searching...
No Matches
Trigfun.hpp
Go to the documentation of this file.
1/**
2 * \file Trigfun.hpp
3 * \brief Header for GeographicLib::Trigfun class
4 *
5 * Copyright (c) Charles Karney (2024-2025) <karney@alum.mit.edu> and licensed
6 * under the MIT/X11 License. For more information, see
7 * https://geographiclib.sourceforge.io/
8 **********************************************************************/
9
10#if !defined(GEOGRAPHICLIB_TRIGFUN_HPP)
11#define GEOGRAPHICLIB_TRIGFUN_HPP 1
12
14
15#include <functional>
16#include <utility>
17
18#if defined(_MSC_VER)
19// Squelch warnings about dll vs vector
20# pragma warning (push)
21# pragma warning (disable: 4251)
22#endif
23
24namespace GeographicLib {
25 namespace Triaxial {
26 class GeodesicLine3;
27 class Conformal3;
28 }
29 /**
30 * \brief Representing a function by a Fourier series
31 *
32 * This class mimic the functionality of Chebfun's 'trig' representation of
33 * periodic functions. Key differences are:
34 *
35 * - Only odd or even functions are allowed (i.e., only sine of only cosine
36 * terms in the Fourier series).
37 * - Can specify that the function has symmetry about the quarter-period
38 * point so that the Fourier series only includes odd harmonics.
39 * - The integral of a Trigfun is counted as a Trigfun even if it includes a
40 * secular term.
41 * - The inverse function of the integral is also a Trigfun (only makes sense
42 * if the orginal function is either strictly positive or strictly
43 * negative).
44 *
45 * Assuming the half period = \e h, the function f(x) is represented as
46 * follows, here \f$ = (\pi/h) x\f$:
47 * - \e sym = false,
48 * - \e odd = true,
49 * \f$ f(x) = C_0 y + \sum_{m = 1}^{M-1} C_m \sin my \f$;
50 * - \e odd = false,
51 * \f$ f(x) = \sum_{m = 0}^{M-1} C_m \cos my \f$;
52 * - \e sym = true,
53 * - \e odd = true,
54 * \f$ f(x) = \sum_{m = 0}^{M-1} C_m \sin 2(m+\frac12) y \f$;
55 * - \e odd = false,
56 * \f$ f(x) = \sum_{m = 0}^{M-1} C_m \cos 2(m+\frac12) y \f$.
57 * .
58 *
59 * Here we compute FFTs using the kissfft package
60 * https://github.com/mborgerding/kissfft by Mark Borgerding.
61 *
62 * Example of use:
63 * \include example-Trigfun.cpp
64 **********************************************************************/
65 class GEOGRAPHICLIB_EXPORT Trigfun {
66 private:
67 /// \cond SKIP
68 friend class TrigfunExt; // For access to root sig 2
69 friend class Triaxial::GeodesicLine3; // For access to root sig 2
70 friend class Triaxial::Conformal3; // For access to root sig 2
71 /// \endcond
72 using real = Math::real;
73 static constexpr bool debug_ = false;
74 static constexpr bool throw_ = true; // exception on convergence failure
75 static constexpr int maxit_ = 300;
76 int _m, // Number of coefficients in series
77 _n; // Number of samples in half/quarter period
78 bool _odd, _sym;
79 std::vector<real> _coeff;
80 real _h, _q; // half, quarter, whole period
81 mutable real _max;
82 static int chop(const std::vector<real>& c, real tol, real scale = -1);
83 static real tolerance(real tol) {
84 static const real eps = std::numeric_limits<real>::epsilon();
85 return tol <= 0 ? eps : tol;
86 }
87 // Function samples over half/quarter period of !sym/sym
88 // odd sym cent samples nF nC
89 // f f f |-|-|-|-|-|-|-|-| n+1 n+1 (4)
90 // t f f --|-|-|-|-|-|-|-| n n+1 (1), (2), (3), (7)
91 // f t f |-|-|-|-|-|-|-|-- n n (1)
92 // t t f --|-|-|-|-|-|-|-| n n (1)
93 // f f t -|-|-|-|-|-|-|-|- n n+1 (4), (6)
94 // t f t -|-|-|-|-|-|-|-|- n n+1 (5)
95 // f t t -|-|-|-|-|-|-|-|- n n
96 // t t t -|-|-|-|-|-|-|-|- n n
97 //
98 // (1) missing end terms presumed zero
99 // (2) included last term is usually zero, if non zero, gives secular term
100 // (3) zeroth coeff used for secular term
101 // (4) zeroth coeff gives constant.
102 // (5) secular term should have been removed from samples
103 // (6) last coeff is zero (but not for centerp)
104 // (7) last coeff is zero (but not for !centerp)
105 // Function is represented by (y = pi/h * x)
106 // sym = false, sample in f_i = f(h * i/n)
107 // odd = true (n samples, n+1 coeffs)
108 // f_0 = 0, need f_i for i in (0, n], f_n defines linear contrib
109 // f(x) = c[0] * y + sum(c[k] * sin(k * y), k, 1, n)
110 // F(x) = 0 + (-h/pi) * sum( c[k]/k * cos(k * y), k, 1, n)
111 // odd = false (n+1 samples, n+1 coeffs)
112 // need f_i for i in [0, n]
113 // f(x) = c[0] + sum(c[k] * cos(k * y), k, 1, n)
114 // F(x) = (h/pi) * (c[0] * y + sum( c[k]/k * sin(k * y), k, 1, n))
115 // sym = true, sample in f_i = f(q * i/n)
116 // odd = true (n samples, n coeffs)
117 // f_0 = 0, need f_i for i in (0, n] (n samples)
118 // f(x) = sum(c[k] * sin(2*(k+1/2) * y), k, 0, n - 1)
119 // F(x) = -(q/pi) * sum(c[k]/(k+1/2) * cos(2*(k+1/2) * y), k, 0, n - 1)
120 // odd = false (n samples, n coeffs)
121 // f_n = 0, need f_i for i in [0, n) (n samples)
122 // f(x) = sum(c[k] * cos(2*(k+1/2) * y), k, 0, n - 1)
123 // F(x) = (q/pi) * sum(c[k]/(k+1/2) * sin(2*(k+1/2) * y), k, 0, n - 1)
124
125 Trigfun(const std::vector<real>& c, bool odd, bool sym, real h)
126 : _m(int(c.size()))
127 , _n(sym ? _m : _m - 1)
128 , _odd(odd)
129 , _sym(sym)
130 , _coeff(c)
131 , _h(h)
132 , _q(_h/2)
133 , _max(-1)
134 {}
135 void refine(const Trigfun& tb);
136 real check(const std::vector<real>& F, bool centerp, real tol) const;
137 // Given z, return dx = finv(z) - nslope * z
138 // dx0 is an estimate of dx (NaN means no information)
139 // the "p" in the function name mean periodic (vs secular)
140 real inversep(real z, const std::function<real(real)>& fp,
141 real dx0, int* countn, int* countb, real tol) const;
142 static Trigfun initbysamples(const std::vector<real>& F,
143 bool odd, bool sym, real halfp, bool centerp);
144 /**
145 * Tags to indicate which routine is invoking root(). Because the root
146 * functions may be called recursively, each invocation is tagged by an
147 * indicator value \e ind. This is merely an aid to debugging.
148 **********************************************************************/
149 enum ind {
150 NONE = 0,
151 INV1,
152 INV2,
153 ARCPOS0,
154 FFUNROOT,
155 GFUNROOT,
156 INVERSEP,
157 PIINV,
158 FINV,
159 KINV,
160 OTHER,
161 };
162
163 /**
164 * Given \e z, find \e x, such that \e z = \e f(\e x).
165 *
166 * @param[in] indicator a numeric indicator to track this call (can be
167 * safely set to Trigfun::OTHER).
168 * @param[in] z the value of \e f(\e x).
169 * @param[in] fp the derivative of \e f(\e x).
170 * @param[in] x0 an estimate of the solution, i.e., \e z &asymp; \e f(\e
171 * x0). Use Math::NaN() to indicate that no estimate is known.
172 * @param[in] countn if not nullptr, a pointer to an integer that gets
173 * incremented by the number of iterations.
174 * @param[in] countb if not nullptr, a pointer to an integer that gets
175 * incremented by the number of bisection steps (which indicates how well
176 * Newton's method is working).
177 * @param[in] tol the tolerance using in terminating the root finding. \e
178 * tol = 0 (the defaulat) mean to use the machine epsilon.
179 * @return the root \e x = \e f <sup>&minus;1</sup>(\e z).
180 *
181 * Newton's method is used to find the root. At each step the bounds are
182 * adjusted. If any Newton step gives a result which lies outside the
183 * bounds, a bisection step is taken instead.
184 *
185 * \warning The routine assumes that there's a unique root. This, in turn,
186 * requires that \e f include a secular term.
187 **********************************************************************/
188 // root sig 2
189 real root(ind indicator, real z, const std::function<real(real)>& fp,
190 real x0, int* countn, int* countb, real tol) const;
191 /**
192 * A general purpose Newton solver for \e z = \e f(\e x).
193 *
194 * @param[in] indicator a numeric indicator to track this call (can be
195 * safely set to Trigfun::OTHER).
196 * @param[in] ffp a function returning \e f(\e x) and \e f'(\e x) as a
197 * pair.
198 * @param[in] z the value of \e f(\e x).
199 * @param[in] x0 an estimate of the solution, i.e., \e z &cong; \e f(\e
200 * x0).
201 * @param[in] xa a lower estimate of the solution.
202 * @param[in] xb an upper estimate of the solution.
203 * @param[in] xscale a representative scale for \e x.
204 * @param[in] zscale a representative scale for \e z.
205 * @param[in] s &plusmn;1 depending on whether \e f is an increasing or
206 * decressing function.
207 * @param[in] countn if not nullptr, a pointer to an integer that gets
208 * incremented by the number of iterations.
209 * @param[in] countb if not nullptr, a pointer to an integer that gets
210 * incremented by the number of bisection steps (which indicates how well
211 * Newton's method is working).
212 * @param[in] tol the tolerance using in terminating the root finding. \e
213 * tol = 0 (the defaulat) mean to use the machine epsilon.
214 * @return the root \e x = \e f <sup>&minus;1</sup>(\e z).
215 *
216 * This is a static function, so \e f(\e x) need not be a Trigfun. \e ffp
217 * provides both the function an its derivative in one function call to
218 * accommodate the (common) situation where the two values can be
219 * efficiently computed together.
220 *
221 * Newton's method is used to find the inverse function. At each step the
222 * bounds are adjusted. If any Newton step gives a result which lies
223 * outside the bounds, a bisection step is taken instead.
224 *
225 * \warning The rouine assumes that there's a unique root lying in the
226 * interval [\e xa, \e xb] and that \e x0 lies in the same interval.
227 **********************************************************************/
228 // root sig 4
229 static real root(ind indicator,
230 const std::function<std::pair<real, real>(real)>& ffp,
231 real z,
232 real x0, real xa, real xb,
233 real xscale = 1, real zscale = 1, int s = 1,
234 int* countn = nullptr, int* countb = nullptr,
235 real tol = 0);
236 /**
237 * Produce a Trigfun for the inverse of \e f.
238 *
239 * @param[in] fp the derivative of \e f(\e x).
240 * @param[in] countn if not nullptr, a pointer to an integer that gets
241 * incremented by the number of iterations need to create the inverse.
242 * @param[in] countb if not nullptr, a pointer to an integer that gets
243 * incremented by the number of bisection steps (which indicates how well
244 * Newton's method is working) needed to create the inverse.
245 * @param[in] nmax the maximum number of points in a quarter period
246 * (default 2^16 = 65536).
247 * @param[in] tol the tolerance using in terminating the root finding. \e
248 * tol = 0 (the defaulat) mean to use the machine epsilon.
249 * @param[in] scale; if \e scale is negative (the default), \e tol sets the
250 * error relative to the largest Fourier coeffient. Otherwise, the error
251 * is relative to the maximum of the largest Fourier coefficient and \e
252 * scale.
253 * @return the Trigfun represention of \e f <sup>&minus;1</sup>(\e z).
254 *
255 * As with the normal constructor this routine successively doubles the
256 * number of sample points, which are computed using Newton's method. A
257 * good starting guess for Newton's method is provided by the previous
258 * Fourier approximation. As a result the average number of Newton
259 * iterations per sample point is about 1 or 2.
260 *
261 * \note Computing the inverse is only possible with a Trigfun with a
262 * secular term.
263 **********************************************************************/
264 Trigfun inverse(const std::function<real(real)>& fp,
265 int* countn, int* countb,
266 int nmax, real tol, real scale) const;
267 public:
268 /**
269 * Default constructor specifying with the function \e f(\e x) = 0.
270 **********************************************************************/
272 : _m(1)
273 , _n(0)
274 , _odd(false)
275 , _sym(false)
276 , _coeff(1, 0)
277 , _h(Math::pi())
278 , _q(_h/2)
279 , _max(-1)
280 {}
281 /**
282 * Construct a Trigfun with a given number of samples a function.
283 *
284 * @param[in] n the number of samples.
285 * @param[in] f the function.
286 * @param[in] odd is the function odd? If it's not odd, then it is even.
287 * @param[in] sym is the function symmetric about the quarter period
288 * point (so it contains only odd Fourier harmonics)?
289 * @param[in] halfp the half period.
290 * @param[in] centerp whether to sample on a centered grid (default false).
291 *
292 * For \e sym = false, \e n is the number of samples in a half period, and
293 * spacing between the samples is \e halfp/\e n. (If \e centerp = false
294 * and \e oddp = false, the function is, in fact sampled \e n + 1 times.)
295 * The number of points given to the FFT routine is 2\e n.
296 *
297 * For \e sym = true, \e n is the number of samples in a quarter period, and
298 * spacing between the samples is \e halfp/(2\e n). The number of points
299 * given to the FFT routine is 4\e n.
300 *
301 * \note In order for the FFT method to operate efficiently, \e n should be
302 * the product of a small factors (typically a power of 2).
303 *
304 * \warning \e f must be a periodic function and it must be either even or
305 * odd. With \e odd = true and \e sym = false, the secular term can be
306 * set with setsecular().
307 **********************************************************************/
308 Trigfun(int n, const std::function<real(real)>& f,
309 bool odd, bool sym, real halfp, bool centerp = false);
310 /**
311 * Construct a Trigfun from a function of one argument.
312 *
313 * @param[in] f the function.
314 * @param[in] odd is the function odd? If it's not odd, then it is even.
315 * @param[in] sym is the function symmetric about the quarter period
316 * point (so it contains only odd Fourier harmonics)?
317 * @param[in] halfp the half period.
318 * @param[in] nmax the maximum number of points in a half/quarter period
319 * (default 2^16 = 65536).
320 * @param[in] tol the tolerance, the default value 0 means use the machine
321 * epsilon.
322 * @param[in] scale; if \e scale is negative (the default), \e tol sets the
323 * error relative to the largest Fourier coeffient. Otherwise, the error
324 * is relative to the maximum of the largest Fourier coefficient and \e
325 * scale.
326 *
327 * The constructor successively doubles the number of sample points and
328 * updating the Fourier coefficients accordingly until the high order
329 * coefficients become sufficiently small. At that point Fourier series is
330 * truncated discarding some of the trailing coefficients. This mimics the
331 * method used by Chebfun. In particular, the method used to truncate the
332 * series is taken from Aurentz and L. N. Trefethen,
333 * <a href="https://doi.org/10.1145/2998442"> Chopping a Chebyshev
334 * series</a> (2017); <a href="https://arxiv.org/abs/1512.01803">
335 * preprint</a>.
336 *
337 * \warning \e f must be a periodic function and it must be either even or
338 * odd. With \e odd = true and \e sym = false, the secular term can be
339 * set with setsecular().
340 **********************************************************************/
341 Trigfun(const std::function<real(real)>& f, bool odd, bool sym,
342 real halfp, int nmax = 1 << 16,
343 real tol = 0,
344 real scale = -1);
345 /**
346 * Construct a Trigfun from a function of two arguments.
347 *
348 * @param[in] f the function.
349 * @param[in] odd is the function odd? If it's not odd, then it is even.
350 * @param[in] sym is the function symmetric about the quarter period
351 * point (so it contains only odd Fourier harmonics)?
352 * @param[in] halfp the half period.
353 * @param[in] nmax the maximum number of points in a half/quarter period
354 * (default 2^16 = 65536).
355 * @param[in] tol the tolerance, the default value 0 means use the machine
356 * epsilon.
357 * @param[in] scale; if \e scale is negative (the default), \e tol sets the
358 * error relative to the largest Fourier coeffient. Otherwise, the error
359 * is relative to the maximum of the largest Fourier coefficient and \e
360 * scale.
361 *
362 * This accommodates the situation where the inverse of a Trigfun \e g is
363 * being computed using inverse(). In this case \e f(\e x, \e y0) returns
364 * the value \e y such that \e g(\e y) = \e x. This is typically found
365 * using Newton's method which requires a starting guess \e y0. In the
366 * implementation of inverse(), the Fourier representation is successively
367 * refined by doubling the number samples. At each stage, a good estimate
368 * of the function values at the new points is found by using the current
369 * Fourier representation.
370 *
371 * \warning \e f must be a periodic function and it amust be either even or
372 * odd. With \e odd = true and \e sym = false, the secular term can be
373 * set with setsecular().
374 **********************************************************************/
375 Trigfun(const std::function<real(real, real)>& f, bool odd, bool sym,
376 real halfp, int nmax = 1 << 16,
377 real tol = 0,
378 real scale = -1);
379 /**
380 * Set the coefficient of the secular term
381 *
382 * @param[in] f0 the value of \e f(\e halfp).
383 *
384 * \warning This throws an error unless \e odd = true and \e sym = false.
385 **********************************************************************/
386 void setsecular(real f0);
387 /**
388 * Evaluate the Trigfun.
389 *
390 * @param[in] x the function argument.
391 * @return the function value \e f(\e x).
392 **********************************************************************/
393 real operator()(real x) const;
394 // For support of Angle
395 // real eval(Angle phi) const;
396
397 /**
398 * The integral of a Trigfun.
399 *
400 * @return the integral.
401 *
402 * \warning The secular term (only present with \e odd = true and \e sym =
403 * false) is ignored when taking the integral.
404 **********************************************************************/
405 Trigfun integral() const;
406 /**
407 * Produce a Trigfun for the inverse of \e f.
408 *
409 * @param[in] fp the derivative of \e f(\e x).
410 * @param[in] nmax the maximum number of points in a quarter period
411 * (default 2^16 = 65536).
412 * @param[in] tol the tolerance using in terminating the root finding. \e
413 * tol = 0 (the defaulat) mean to use the machine epsilon.
414 * @param[in] scale; if \e scale is negative (the default), \e tol sets the
415 * error relative to the largest Fourier coeffient. Otherwise, the error
416 * is relative to the maximum of the largest Fourier coefficient and \e
417 * scale.
418 * @return the Trigfun represention of \e f <sup>&minus;1</sup>(\e z).
419 *
420 * As with the normal constructor this routine successively doubles the
421 * number of sample points, which are computed using Newton's method. A
422 * good starting guess for Newton's method is provided by the previous
423 * Fourier approximation. As a result the average number of Newton
424 * iterations per sample point is about 1 or 2.
425 *
426 * \e scale is used when \e f(\e x) is a correction term added to a larger
427 * contribution; and it would then be the magnitude of the larger
428 * contribution.
429
430 * \note Computing the inverse is only possible with a Trigfun with a
431 * secular term.
432 **********************************************************************/
433 Trigfun inverse(const std::function<real(real)>& fp,
434 int nmax = 1 << 16, real tol = 0, real scale = -1) const {
435 return inverse(fp, nullptr, nullptr, nmax, tol, scale);
436 }
437
438 /**
439 * @return whether the function is odd or not. If it's not odd, then it is
440 * even.
441 **********************************************************************/
442 bool Odd() const { return _odd; }
443 /**
444 * @return whether the function is symmetric about the quarter peroid
445 * point. If it is it, then the Fourier series has only odd terms.
446 **********************************************************************/
447 bool Symmetric() const { return _sym; }
448 /**
449 * @return the half period of the function.
450 **********************************************************************/
451 real HalfPeriod() const { return _h; }
452 /**
453 * @return the number of terms in the Fourier series.
454 **********************************************************************/
455 int NCoeffs() const { return _m; }
456 /**
457 * @return an estimate of the amplitude of the oscillating component of \e
458 * f.
459 *
460 * \note This estimate excludes any constant or secular terms in the
461 * series. The estimate is found by summing the absolute values of the
462 * remaining coefficients (and is thus an overestimate).
463 **********************************************************************/
464 real Max() const;
465 /**
466 * @return the (approximate) half range of the function.
467 *
468 * For a Trigfun containing a secular contribution this is the value of the
469 * function tat the half perioid. Otherwise Max() is returned.
470 **********************************************************************/
471 real HalfRange() const {
472 return _odd && !_sym ? _coeff[0] * Math::pi() : Max();
473 }
474 /**
475 * @return the average slope of the function.
476 *
477 * For a Trigfun containing a secular contribution this is the slope of the
478 * secular component. Otherwise 0 is returned..
479 **********************************************************************/
480 real Slope() const {
481 return _odd && !_sym ? HalfRange() / HalfPeriod() : 0;
482 }
483 };
484
485 /**
486 * \brief A function defined by its derivative and its inverse.
487 *
488 * This is an extension of Trigfun which allows a function to be defined by
489 * its derivative. In this case the derivative must be even, so that its
490 * integral is odd (and taken to be zero at the origin).
491 *
492 * In addition, this class offers a flexible interface to computing the
493 * inverse of the function. If the inverse is only required at a few points
494 *
495 * Example of use:
496 * \include example-TrigfunExt.cpp
497 **********************************************************************/
499 private:
500 /// \cond SKIP
501 friend class Triaxial::GeodesicLine3; // For access internal inv, inv1
502 /// \endcond
503 using real = Math::real;
504 std::function<real(real)> _fp;
505 bool _sym;
506 Trigfun _f, _finv;
507 real _tol;
508 int _nmax;
509 bool _invp;
510 int _countn, _countb;
511
512 // Approximate inverse using _finv
513 real inv0(real z) const {
514 if (!_invp) return Math::NaN();
515 return _sym ? Math::NaN() : _finv(z);
516 }
517 // Accurate inverse by direct Newton (not using _finv)
518 real inv1(real z, int* countn, int* countb) const {
519 return _sym ? Math::NaN() : _f.root(Trigfun::INV1, z, _fp, Math::NaN(),
520 countn, countb, 0);
521 }
522 // Accurate inverse correcting result from _finv
523 real inv2(real z, int* countn, int* countb) const {
524 if (!_invp) return Math::NaN();
525 return _sym ? Math::NaN() :
526 _f.root(Trigfun::INV2, z, _fp, _finv(z), countn, countb, 0);
527 }
528 real inv(real z, int* countn, int* countb) const {
529 return _invp ? inv2(z, countn, countb) : inv1(z, countn, countb);
530 }
531 public:
533 /**
534 * Constructor specifying the derivative, an even periodic function
535 *
536 * @param[in] fp the derivative function, \e fp(\e x) = \e f'(\e x).
537 * @param[in] halfp the half period.
538 * @param[in] sym is \e fp symmetric about the quarter period point (so it
539 * contains only odd Fourier harmonics)?
540 * @param[in] scale; this is passed to the Trigfun constructor when finding
541 * the Fourier series for \e fp.
542 *
543 * \warning \e fp must be an even periodic function. In addition \e fp
544 * must be non-negative for the inverse of \e f to be computed (in this
545 * case, \e f is a monotonically increasing function). The inverse is
546 * undefined for \e sym = true.
547 **********************************************************************/
548 TrigfunExt(const std::function<real(real)>& fp, real halfp,
549 bool sym = false, real scale = -1);
550 /**
551 * Evaluate the TrigfunExt.
552 *
553 * @param[in] x the function argument.
554 * @return the function value \e f(\e x).
555 **********************************************************************/
556 real operator()(real x) const { return _f(x); }
557 /**
558 * Evaluate the derivative for TrigfunExt.
559 *
560 * @param[in] x the function argument.
561 * @return the value of the derivate \e fp(\e x). This uses the function
562 * object passed to the constructor.
563 **********************************************************************/
564 real deriv(real x) const { return _fp(x); }
565 /**
566 * Evaluate the inverse of \e f
567 *
568 * @param[in] z the vaule of \e f(\e x)
569 * @return the value of \e x = \e f <sup>&minus;1</sup>(\e z).
570 *
571 * This compute the inverse using Newton's method with the derivate
572 * function \e fp supplied on construction. Initially, the starting guess
573 * is based on just the secular component of \e f(\e x). However, if
574 * ComputeInverse() is called, a rough Trigfun approximation to the inverse
575 * is found and this is used as the starting point for Newton's method.
576 **********************************************************************/
577 real inv(real z) const {
578 return _invp ? inv2(z, nullptr, nullptr) : inv1(z, nullptr, nullptr);
579 }
580 /**
581 * Compute a coarse Fourier series approximation of the inverse.
582 *
583 * This is used to provide a better starting guess for Newton's method in
584 * inv(). Because ComputeInverse() is fairly expensive, this only makes
585 * sense if inv() will be called many times. In order to limit the expense
586 * in computing this approximate inverse, the number of Fourier componensts
587 * in the Trigfun for the inverse is limited to 3/2 of the number of
588 * components for \e f and the tolerance is set to the square root of the
589 * machine epsilon.
590 **********************************************************************/
592 if (!_invp && !_sym) {
593 _countn = _countb = 0;
594 _finv = _f.inverse(_fp, &_countn, &_countb, _nmax, _tol, -1);
595 _invp = true;
596 }
597 }
598 /**
599 * @return whether the function is symmetric about the quarter peroid
600 * point. If it is it, then the Fourier series has only odd harmonics.
601 **********************************************************************/
602 bool Symmetric() const { return _sym; }
603 /**
604 * @return the number of terms in the Fourier series for \e f.
605 **********************************************************************/
606 int NCoeffs() const { return _f.NCoeffs(); }
607 /**
608 * @return the number of terms in the Fourier series for
609 * \e f<sup>&minus;1</sup>.
610 **********************************************************************/
611 int NCoeffsInv() const {
612 if (!_invp) return -1;
613 return _finv.NCoeffs(); }
614 /**
615 * @return Max() for the underlying Trigfun.
616 **********************************************************************/
617 real Max() const { return _f.Max(); }
618 /**
619 * @return HalfPeriod() for the underlying Trigfun.
620 **********************************************************************/
621 real HalfPeriod() const { return _f.HalfPeriod(); }
622 /**
623 * @return HalfRange() for the underlying Trigfun.
624 **********************************************************************/
625 real HalfRange() const { return _f.HalfRange(); }
626 /**
627 * @return Slope() for the underlying Trigfun.
628 **********************************************************************/
629 real Slope() const { return _f.Slope(); }
630 };
631
632} // namespace GeographicLib
633
634#if defined(_MSC_VER)
635# pragma warning (pop)
636#endif
637
638#endif // GEOGRAPHICLIB_TRIGFUN_HPP
Header for GeographicLib::Constants class.
#define GEOGRAPHICLIB_EXPORT
Definition Constants.hpp:59
GeographicLib::Math::real real
Mathematical functions needed by GeographicLib.
Definition Math.hpp:82
static T pi()
Definition Math.hpp:187
static T NaN()
Definition Math.cpp:301
Jacobi's conformal projection of a triaxial ellipsoid.
The direct geodesic problem for a triaxial ellipsoid.
A function defined by its derivative and its inverse.
Definition Trigfun.hpp:498
TrigfunExt(const std::function< real(real)> &fp, real halfp, bool sym=false, real scale=-1)
real operator()(real x) const
Definition Trigfun.hpp:556
real deriv(real x) const
Definition Trigfun.hpp:564
real inv(real z) const
Definition Trigfun.hpp:577
Representing a function by a Fourier series.
Definition Trigfun.hpp:65
Trigfun(const std::function< real(real)> &f, bool odd, bool sym, real halfp, int nmax=1<< 16, real tol=0, real scale=-1)
Trigfun(int n, const std::function< real(real)> &f, bool odd, bool sym, real halfp, bool centerp=false)
bool Symmetric() const
Definition Trigfun.hpp:447
real HalfRange() const
Definition Trigfun.hpp:471
real HalfPeriod() const
Definition Trigfun.hpp:451
real operator()(real x) const
Trigfun inverse(const std::function< real(real)> &fp, int nmax=1<< 16, real tol=0, real scale=-1) const
Definition Trigfun.hpp:433
Trigfun(const std::function< real(real, real)> &f, bool odd, bool sym, real halfp, int nmax=1<< 16, real tol=0, real scale=-1)
Trigfun integral() const
void setsecular(real f0)
Namespace for operations on triaxial ellipsoids.
Namespace for GeographicLib.