This file is indexed.

/usr/include/GeographicLib/SphericalEngine.hpp is in libgeographiclib-dev 1.21-1ubuntu1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
/**
 * \file SphericalEngine.hpp
 * \brief Header for GeographicLib::SphericalEngine class
 *
 * Copyright (c) Charles Karney (2011, 2012) <charles@karney.com> and licensed
 * under the MIT/X11 License.  For more information, see
 * http://geographiclib.sourceforge.net/
 **********************************************************************/

#if !defined(GEOGRAPHICLIB_SPHERICALENGINE_HPP)
#define GEOGRAPHICLIB_SPHERICALENGINE_HPP \
  "$Id: f48320a694ecf901d997b23d32ea625e589f9534 $"

#include <vector>
#include <istream>
#include <GeographicLib/Constants.hpp>

#if defined(_MSC_VER)
// Squelch warnings about dll vs vector
#pragma warning (push)
#pragma warning (disable: 4251)
#endif

namespace GeographicLib {

  class CircularEngine;

  /**
   * \brief The evaluation engine for SphericalHarmonic
   *
   * This serves as the backend to SphericalHarmonic, SphericalHarmonic1, and
   * SphericalHarmonic2.  Typically end-users will not have to access this
   * class directly.
   *
   * See SphericalEngine.cpp for more information on the implementation.
   *
   * Example of use:
   * \include example-SphericalEngine.cpp
   **********************************************************************/

  class GEOGRAPHIC_EXPORT SphericalEngine {
  private:
    typedef Math::real real;
    // A table of the square roots of integers
    static std::vector<real> root_;
    friend class CircularEngine; // CircularEngine needs access to root_, scale_
    // An internal scaling of the coefficients to avoid overflow in
    // intermediate calculations.
    static const real scale_;
    // Move latitudes near the pole off the axis by this amount.
    static const real eps_;
    static const std::vector<real> Z_;
    SphericalEngine();          // Disable constructor
  public:
    /**
     * Supported normalizations for associated Legendre polynomials.
     **********************************************************************/
    enum normalization {
      /**
       * Fully normalized associated Legendre polynomials.  See
       * SphericalHarmonic::FULL for documentation.
       *
       * @hideinitializer
       **********************************************************************/
      FULL = 0,
      /**
       * Schmidt semi-normalized associated Legendre polynomials.  See
       * SphericalHarmonic::SCHMIDT for documentation.
       *
       * @hideinitializer
       **********************************************************************/
      SCHMIDT = 1,
      /// \cond SKIP
      // These are deprecated...
      full = FULL,
      schmidt = SCHMIDT,
      /// \endcond
    };

    /**
     * \brief Package up coefficients for SphericalEngine
     *
     * This packages up the \e C, \e S coefficients and information about how
     * the coefficients are stored into a single structure.  This allows a
     * vector of type SphericalEngine::coeff to be passed to
     * SphericalEngine::Value.  This class also includes functions to aid
     * indexing into \e C and \e S.
     *
     * The storage layout of the coefficients is documented in
     * SphericalHarmonic and SphericalHarmonic::SphericalHarmonic.
     **********************************************************************/
    class GEOGRAPHIC_EXPORT coeff {
    private:
      int _N, _nmx, _mmx;
      std::vector<real>::const_iterator _Cnm;
      std::vector<real>::const_iterator _Snm;
    public:
      /**
       * A default constructor
       **********************************************************************/
      coeff()
        : _N(-1)
        , _nmx(-1)
        , _mmx(-1)
        , _Cnm(Z_.begin())
        , _Snm(Z_.begin()) {}
      /**
       * The general constructor.
       *
       * @param[in] C a vector of coefficients for the cosine terms.
       * @param[in] S a vector of coefficients for the sine terms.
       * @param[in] N the degree giving storage layout for \e C and \e S.
       * @param[in] nmx the maximum degree to be used.
       * @param[in] mmx the maximum order to be used.
       *
       * This requires \e N >= \e nmx >= \e mmx >= -1.  \e C and \e S must also
       * be large enough to hold the coefficients.  Otherwise an exception is
       * thrown.
       **********************************************************************/
      coeff(const std::vector<real>& C,
            const std::vector<real>& S,
            int N, int nmx, int mmx)
        : _N(N)
        , _nmx(nmx)
        , _mmx(mmx)
        , _Cnm(C.begin())
        , _Snm(S.begin())
      {
        if (!(_N >= _nmx && _nmx >= _mmx && _mmx >= -1))
          throw GeographicErr("Bad indices for coeff");
        if (!(index(_nmx, _mmx) < int(C.size()) &&
              index(_nmx, _mmx) < int(S.size()) + (_N + 1)))
          throw GeographicErr("Arrays too small in coeff");
        SphericalEngine::RootTable(_nmx);
      }
      /**
       * The constructor for full coefficient vectors.
       *
       * @param[in] C a vector of coefficients for the cosine terms.
       * @param[in] S a vector of coefficients for the sine terms.
       * @param[in] N the maximum degree and order.
       *
       * This requires \e N >= -1.  \e C and \e S must also be large enough to
       * hold the coefficients.  Otherwise an exception is thrown.
       **********************************************************************/
      coeff(const std::vector<real>& C,
            const std::vector<real>& S,
            int N)
        : _N(N)
        , _nmx(N)
        , _mmx(N)
        , _Cnm(C.begin())
        , _Snm(S.begin())
      {
        if (!(_N >= -1))
          throw GeographicErr("Bad indices for coeff");
        if (!(index(_nmx, _mmx) < int(C.size()) &&
              index(_nmx, _mmx) < int(S.size()) + (_N + 1)))
          throw GeographicErr("Arrays too small in coeff");
        SphericalEngine::RootTable(_nmx);
      }
      /**
       * @return \e N the degree giving storage layout for \e C and \e S.
       **********************************************************************/
      inline int N() const throw() { return _N; }
      /**
       * @return \e nmx the maximum degree to be used.
       **********************************************************************/
      inline int nmx() const throw() { return _nmx; }
      /**
       * @return \e mmx the maximum order to be used.
       **********************************************************************/
      inline int mmx() const throw() { return _mmx; }
      /**
       * The one-dimensional index into \e C and \e S.
       *
       * @param[in] n the degree.
       * @param[in] m the order.
       * @return the one-dimensional index.
       **********************************************************************/
      inline int index(int n, int m) const throw()
      { return m * _N - m * (m - 1) / 2 + n; }
      /**
       * An element of \e C.
       *
       * @param[in] k the one-dimensional index.
       * @return the value of the \e C coefficient.
       **********************************************************************/
      inline Math::real Cv(int k) const { return *(_Cnm + k); }
      /**
       * An element of \e S.
       *
       * @param[in] k the one-dimensional index.
       * @return the value of the \e S coefficient.
       **********************************************************************/
      inline Math::real Sv(int k) const { return *(_Snm + (k - (_N + 1))); }
      /**
       * An element of \e C with checking.
       *
       * @param[in] k the one-dimensional index.
       * @param[in] n the requested degree.
       * @param[in] m the requested order.
       * @param[in] f a multiplier.
       * @return the value of the \e C coefficient multiplied by \e f in \e n
       *   and \e m are in range else 0.
       **********************************************************************/
      inline Math::real Cv(int k, int n, int m, real f) const
      { return m > _mmx || n > _nmx ? 0 : *(_Cnm + k) * f; }
      /**
       * An element of \e S with checking.
       *
       * @param[in] k the one-dimensional index.
       * @param[in] n the requested degree.
       * @param[in] m the requested order.
       * @param[in] f a multiplier.
       * @return the value of the \e S coefficient multiplied by \e f in \e n
       *   and \e m are in range else 0.
       **********************************************************************/
      inline Math::real Sv(int k, int n, int m, real f) const
      { return m > _mmx || n > _nmx ? 0 : *(_Snm + (k - (_N + 1))) * f; }

      /**
       * The size of the coefficient vector for the cosine terms.
       *
       * @param[in] N the maximum degree.
       * @param[in] M the maximum order.
       * @return the size of the vector of cosine terms as stored in column
       *   major order.
       **********************************************************************/
      static inline int Csize(int N, int M)
      { return (M + 1) * (2 * N - M + 2) / 2; }

      /**
       * The size of the coefficient vector for the sine terms.
       *
       * @param[in] N the maximum degree.
       * @param[in] M the maximum order.
       * @return the size of the vector of cosine terms as stored in column
       *   major order.
       **********************************************************************/
      static inline int Ssize(int N, int M)
      { return Csize(N, M) - (N + 1); }

      /**
       * Load coefficients from a binary stream.
       *
       * @param[in] stream the input stream.
       * @param[out] N The maximum degree of the coefficients.
       * @param[out] M The maximum order of the coefficients.
       * @param[out] C The vector of cosine coefficients.
       * @param[out] S The vector of sine coefficients.
       *
       * \e N and \e M are read as 4-byte ints.  \e C and \e S are resized to
       * accommodate all the coefficients (with the \e m = 0 coefficients for
       * \e S excluded) and the data for these coefficients read as 8-byte
       * doubles.  The coefficients are stored in column major order.  The
       * bytes in the stream should use little-endian ordering.  IEEE floating
       * point is assumed for the coefficients.
       **********************************************************************/
      static void readcoeffs(std::istream& stream, int& N, int& M,
                             std::vector<real>& C, std::vector<real>& S);
    };

    /**
     * Evaluate a spherical harmonic sum and its gradient.
     *
     * @tparam gradp should the gradient be calculated.
     * @tparam norm the normalization for the associated Legendre polynomials.
     * @tparam L the number of terms in the coefficients.
     * @param[in] c an array of coeff objects.
     * @param[in] f array of coefficient multipliers.  f[0] should be 1.
     * @param[in] x the \e x component of the cartesian position.
     * @param[in] y the \e y component of the cartesian position.
     * @param[in] z the \e z component of the cartesian position.
     * @param[in] a the normalizing radius.
     * @param[out] gradx the \e x component of the gradient.
     * @param[out] grady the \e y component of the gradient.
     * @param[out] gradz the \e z component of the gradient.
     * @result the spherical harmonic sum.
     *
     * See the SphericalHarmonic class for the definition of the sum.
     * The coefficients used by this function are, for example,
     * c[0].Cv + f[1] * c[1].Cv + ... + f[L-1] * c[L-1].Cv.  (Note
     * that f[0] is \e not used.)  The upper limits on the sum are
     * determined by c[0].nmx() and c[0].mmx(); these limits apply to
     * \e all the components of the coefficients.  The parameters \e
     * gradp, \e norm, and \e L are template parameters, to allow more
     * optimization to be done at compile time.
     *
     * Clenshaw summation is used which permits the evaluation of the sum
     * without the need to allocate temporary arrays.  Thus this function never
     * throws an exception.
     **********************************************************************/
    template<bool gradp, normalization norm, int L>
      static Math::real Value(const coeff c[], const real f[],
                              real x, real y, real z, real a,
                              real& gradx, real& grady, real& gradz) throw();

    /**
     * Create a CircularEngine object
     *
     * @tparam gradp should the gradient be calculated.
     * @tparam norm the normalization for the associated Legendre polynomials.
     * @tparam L the number of terms in the coefficients.
     * @param[in] c an array of coeff objects.
     * @param[in] f array of coefficient multipliers.  f[0] should be 1.
     * @param[in] p the radius of the circle = sqrt(<i>x</i><sup>2</sup> + 
     *   <i>y</i><sup>2</sup>).
     * @param[in] z the height of the circle.
     * @param[in] a the normalizing radius.
     * @result the CircularEngine object.
     *
     * If you need to evaluate the spherical harmonic sum for several points
     * with constant \e f, \e p = sqrt(<i>x</i><sup>2</sup> +
     * <i>y</i><sup>2</sup>), \e z, and \e a, it is more efficient to construct
     * call SphericalEngine::Circle to give a CircularEngine object and then
     * call CircularEngine::operator()() with arguments <i>x</i>/\e p and
     * <i>y</i>/\e p.
     **********************************************************************/
    template<bool gradp, normalization norm, int L>
      static CircularEngine Circle(const coeff c[], const real f[],
                                   real p, real z, real a);
    /**
     * Check that the static table of square roots is big enough and enlarge it
     * if necessary.
     *
     * @param[in] N the maximum degree to be used in SphericalEngine.
     *
     * Typically, there's no need for an end-user to call this routine, because
     * the constructors for SphericalEngine::coeff do so.  However, since this
     * updates a static table, there's a possible race condition in a
     * multi-threaded environment.  Because this routine does nothing if the
     * table is already large enough, one way to avoid race conditions is to
     * call this routine at program start up (when it's still single threaded),
     * supplying the largest degree that your program will use.  E.g.,
     \code
  GeographicLib::SphericalEngine::RootTable(2190);
     \endcode
     * suffices to accommodate extant magnetic and gravity models.
     **********************************************************************/
    static void RootTable(int N);

    /**
     * Clear the static table of square roots and release the memory.  Call
     * this only when you are sure you no longer will be using SphericalEngine.
     * Your program will crash if you call SphericalEngine after calling this
     * routine.  <b>It's safest not to call this routine at all.</b> (The space
     * used by the table is modest.)
     **********************************************************************/
    static void ClearRootTable() {
      std::vector<real> temp(0);
      root_.swap(temp);
    }
  };

} // namespace GeographicLib

#if defined(_MSC_VER)
#pragma warning (pop)
#endif

#endif  // GEOGRAPHICLIB_SPHERICALENGINE_HPP