GeographicLib
2.7
Toggle main menu visibility
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
13
#include <
GeographicLib/Constants.hpp
>
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 original 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 ≈ \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 default) mean to use the machine epsilon.
179
* @return the root \e x = \e f <sup>−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 ≅ \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 ±1 depending on whether \e f is an increasing or
206
* decreasing 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 default) mean to use the machine epsilon.
214
* @return the root \e x = \e f <sup>−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 routine 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 default) 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 coefficient. Otherwise, the error
251
* is relative to the maximum of the largest Fourier coefficient and \e
252
* scale.
253
* @return the Trigfun representation of \e f <sup>−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
**********************************************************************/
271
Trigfun
()
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 coefficient. 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 coefficient. 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 must 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 default) 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 coefficient. Otherwise, the error
416
* is relative to the maximum of the largest Fourier coefficient and \e
417
* scale.
418
* @return the Trigfun representation of \e f <sup>−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 period
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 at 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
**********************************************************************/
498
class
GEOGRAPHICLIB_EXPORT
TrigfunExt
{
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
:
532
TrigfunExt
() {}
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 nonnegative 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 derivative \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 value of \e f(\e x)
569
* @return the value of \e x = \e f <sup>−1</sup>(\e z).
570
*
571
* This compute the inverse using Newton's method with the derivative
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 components
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 period
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>−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
Constants.hpp
Header for GeographicLib::Constants class.
GEOGRAPHICLIB_EXPORT
#define GEOGRAPHICLIB_EXPORT
Definition
Constants.hpp:59
real
GeographicLib::Math::real real
Definition
Geod3Solve.cpp:25
GeographicLib::Math
Mathematical functions needed by GeographicLib.
Definition
Math.hpp:82
GeographicLib::Math::pi
static T pi()
Definition
Math.hpp:187
GeographicLib::Math::NaN
static T NaN()
Definition
Math.cpp:301
GeographicLib::Math::real
double real
Definition
Math.hpp:115
GeographicLib::Triaxial::Conformal3
Jacobi's conformal projection of a triaxial ellipsoid.
Definition
Conformal3.hpp:67
GeographicLib::Triaxial::GeodesicLine3
The direct geodesic problem for a triaxial ellipsoid.
Definition
GeodesicLine3.hpp:54
GeographicLib::TrigfunExt
A function defined by its derivative and its inverse.
Definition
Trigfun.hpp:498
GeographicLib::TrigfunExt::TrigfunExt
TrigfunExt(const std::function< real(real)> &fp, real halfp, bool sym=false, real scale=-1)
GeographicLib::TrigfunExt::HalfPeriod
real HalfPeriod() const
Definition
Trigfun.hpp:621
GeographicLib::TrigfunExt::Max
real Max() const
Definition
Trigfun.hpp:617
GeographicLib::TrigfunExt::NCoeffs
int NCoeffs() const
Definition
Trigfun.hpp:606
GeographicLib::TrigfunExt::operator()
real operator()(real x) const
Definition
Trigfun.hpp:556
GeographicLib::TrigfunExt::NCoeffsInv
int NCoeffsInv() const
Definition
Trigfun.hpp:611
GeographicLib::TrigfunExt::deriv
real deriv(real x) const
Definition
Trigfun.hpp:564
GeographicLib::TrigfunExt::inv
real inv(real z) const
Definition
Trigfun.hpp:577
GeographicLib::TrigfunExt::HalfRange
real HalfRange() const
Definition
Trigfun.hpp:625
GeographicLib::TrigfunExt::TrigfunExt
TrigfunExt()
Definition
Trigfun.hpp:532
GeographicLib::TrigfunExt::Slope
real Slope() const
Definition
Trigfun.hpp:629
GeographicLib::TrigfunExt::ComputeInverse
void ComputeInverse()
Definition
Trigfun.hpp:591
GeographicLib::TrigfunExt::Symmetric
bool Symmetric() const
Definition
Trigfun.hpp:602
GeographicLib::Trigfun
Representing a function by a Fourier series.
Definition
Trigfun.hpp:65
GeographicLib::Trigfun::Trigfun
Trigfun()
Definition
Trigfun.hpp:271
GeographicLib::Trigfun::Slope
real Slope() const
Definition
Trigfun.hpp:480
GeographicLib::Trigfun::Max
real Max() const
GeographicLib::Trigfun::NCoeffs
int NCoeffs() const
Definition
Trigfun.hpp:455
GeographicLib::Trigfun::Trigfun
Trigfun(const std::function< real(real)> &f, bool odd, bool sym, real halfp, int nmax=1<< 16, real tol=0, real scale=-1)
GeographicLib::Trigfun::Trigfun
Trigfun(int n, const std::function< real(real)> &f, bool odd, bool sym, real halfp, bool centerp=false)
GeographicLib::Trigfun::Symmetric
bool Symmetric() const
Definition
Trigfun.hpp:447
GeographicLib::Trigfun::HalfRange
real HalfRange() const
Definition
Trigfun.hpp:471
GeographicLib::Trigfun::HalfPeriod
real HalfPeriod() const
Definition
Trigfun.hpp:451
GeographicLib::Trigfun::operator()
real operator()(real x) const
GeographicLib::Trigfun::inverse
Trigfun inverse(const std::function< real(real)> &fp, int nmax=1<< 16, real tol=0, real scale=-1) const
Definition
Trigfun.hpp:433
GeographicLib::Trigfun::Trigfun
Trigfun(const std::function< real(real, real)> &f, bool odd, bool sym, real halfp, int nmax=1<< 16, real tol=0, real scale=-1)
GeographicLib::Trigfun::integral
Trigfun integral() const
GeographicLib::Trigfun::Odd
bool Odd() const
Definition
Trigfun.hpp:442
GeographicLib::Trigfun::setsecular
void setsecular(real f0)
GeographicLib::Triaxial
Namespace for operations on triaxial ellipsoids.
Definition
Cartesian3.cpp:13
GeographicLib
Namespace for GeographicLib.
Definition
Accumulator.cpp:12
include
GeographicLib
Trigfun.hpp
Generated by
1.17.0