GeographicLib  2.6
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 
24 namespace 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  **********************************************************************/
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  **********************************************************************/
591  void ComputeInverse() {
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
A function defined by its derivative and its inverse.
Definition: Trigfun.hpp:498
Representing a function by a Fourier series.
Definition: Trigfun.hpp:65
static T pi()
Definition: Math.hpp:187
#define GEOGRAPHICLIB_EXPORT
Definition: Constants.hpp:59
real HalfRange() const
Definition: Trigfun.hpp:625
real inv(real z) const
Definition: Trigfun.hpp:577
Trigfun inverse(const std::function< real(real)> &fp, int nmax=1<< 16, real tol=0, real scale=-1) const
Definition: Trigfun.hpp:433
real HalfPeriod() const
Definition: Trigfun.hpp:621
real deriv(real x) const
Definition: Trigfun.hpp:564
bool Symmetric() const
Definition: Trigfun.hpp:602
Mathematical functions needed by GeographicLib.
Definition: Math.hpp:82
bool Odd() const
Definition: Trigfun.hpp:442
int NCoeffs() const
Definition: Trigfun.hpp:455
Jacobi&#39;s conformal projection of a triaxial ellipsoid.
Definition: Conformal3.hpp:67
The direct geodesic problem for a triaxial ellipsoid.
real HalfPeriod() const
Definition: Trigfun.hpp:451
real operator()(real x) const
Definition: Trigfun.hpp:556
Namespace for GeographicLib.
Definition: Accumulator.cpp:12
static T NaN()
Definition: Math.cpp:301
GeographicLib::Math::real real
Definition: Geod3Solve.cpp:25
real HalfRange() const
Definition: Trigfun.hpp:471
Header for GeographicLib::Constants class.
bool Symmetric() const
Definition: Trigfun.hpp:447
real Slope() const
Definition: Trigfun.hpp:480