/**
         * Constructor for a ellipsoid with
         *
         * @param[in] a equatorial radius (meters).
         * @param[in] f flattening of ellipsoid.  Setting \e f = 0 gives a sphere.
         *   Negative \e f gives a prolate ellipsoid.
         * @param[in] k0 central scale factor.
         * @exception GeographicErr if \e a, (1 − \e f) \e a, or \e k0 is
         *   not positive.
         **********************************************************************/
        public TransverseMercator(double a, double f, double k0)
        {
            _a   = a;
            _f   = f;
            _k0  = k0;
            _e2  = _f * (2 - _f);
            _es  = (f < 0 ? -1 : 1) * Math.Sqrt(Math.Abs(_e2));
            _e2m = 1 - _e2;
            // _c = Math.Sqrt( pow(1 + _e, 1 + _e) * pow(1 - _e, 1 - _e) ) )
            // See, for example, Lee (1976), p 100.
            _c = Math.Sqrt(_e2m) * Math.Exp(GeoMath.Eatanhe(1, _es));
            _n = _f / (2 - _f);


            if (!(GeoMath.IsFinite(_a) && _a > 0))
            {
                throw new GeographicException("Equatorial radius is not positive");
            }
            if (!(GeoMath.IsFinite(_f) && _f < 1))
            {
                throw new GeographicException("Polar semi-axis is not positive");
            }
            if (!(GeoMath.IsFinite(_k0) && _k0 > 0))
            {
                throw new GeographicException("Scale is not positive");
            }

            double[] b1coeff =
            {
                // b1*(n+1), polynomial in n2 of order 3
                1, 4, 64, 256, 256,
            };

            double[] alpcoeff =
            {
                // alp[1]/n^1, polynomial in n of order 5
                31564,        -66675,   34440,    47250, -100800,   75600, 151200,
                // alp[2]/n^2, polynomial in n of order 4
                -1983433,     863232,  748608, -1161216,  524160, 1935360,
                // alp[3]/n^3, polynomial in n of order 3
                670412,       406647, -533952,   184464,  725760,
                // alp[4]/n^4, polynomial in n of order 2
                6601661,    -7732800, 2230245,  7257600,
                // alp[5]/n^5, polynomial in n of order 1
                -13675556,   3438171, 7983360,
                // alp[6]/n^6, polynomial in n of order 0
                212378941, 319334400,
            };  // count = 27

            double[] betcoeff =
            {
                // bet[1]/n^1, polynomial in n of order 5
                384796,     -382725,    -6720,  932400, -1612800, 1209600, 2419200,
                // bet[2]/n^2, polynomial in n of order 4
                -1118711,   1695744, -1174656,  258048,    80640, 3870720,
                // bet[3]/n^3, polynomial in n of order 3
                22276,       -16929,   -15984,   12852,   362880,
                // bet[4]/n^4, polynomial in n of order 2
                -830251,    -158400,   197865, 7257600,
                // bet[5]/n^5, polynomial in n of order 1
                -435388,     453717, 15966720,
                // bet[6]/n^6, polynomial in n of order 0
                20648693, 638668800,
            };  // count = 27

            int m = maxpow_ / 2;

            _b1 = GeoMath.PolyVal(m, b1coeff, 0, GeoMath.Square(_n)) / (b1coeff[m + 1] * (1 + _n));
            // _a1 is the equivalent radius for computing the circumference of
            // ellipse.
            _a1 = _b1 * _a;
            int    o = 0;
            double d = _n;

            for (int l = 1; l <= maxpow_; ++l)
            {
                m       = maxpow_ - l;
                _alp[l] = d * GeoMath.PolyVal(m, alpcoeff, o, _n) / alpcoeff[o + m + 1];
                _bet[l] = d * GeoMath.PolyVal(m, betcoeff, o, _n) / betcoeff[o + m + 1];
                o      += m + 2;
                d      *= _n;
            }
            // Post condition: o == sizeof(alpcoeff) / sizeof(double) &&
            // o == sizeof(betcoeff) / sizeof(double)
        }