@@ -41,10 +41,12 @@ template <typename T, typename Policy>
41
41
T ellint_k_imp (T k, const Policy& pol, std::integral_constant<int , 1 > const &);
42
42
template <typename T, typename Policy>
43
43
T ellint_k_imp (T k, const Policy& pol, std::integral_constant<int , 2 > const &);
44
+ template <typename T, typename Policy>
45
+ T ellint_k_imp (T k, const Policy& pol, T one_minus_k2);
44
46
45
47
// Elliptic integral (Legendre form) of the first kind
46
48
template <typename T, typename Policy>
47
- T ellint_f_imp (T phi, T k, const Policy& pol)
49
+ T ellint_f_imp (T phi, T k, const Policy& pol, T one_minus_k2 )
48
50
{
49
51
BOOST_MATH_STD_USING
50
52
using namespace boost ::math::tools;
@@ -75,12 +77,7 @@ T ellint_f_imp(T phi, T k, const Policy& pol)
75
77
{
76
78
// Phi is so large that phi%pi is necessarily zero (or garbage),
77
79
// just return the second part of the duplication formula:
78
- typedef std::integral_constant<int ,
79
- std::is_floating_point<T>::value&& std::numeric_limits<T>::digits && (std::numeric_limits<T>::digits <= 54 ) ? 0 :
80
- std::is_floating_point<T>::value && std::numeric_limits<T>::digits && (std::numeric_limits<T>::digits <= 64 ) ? 1 : 2
81
- > precision_tag_type;
82
-
83
- result = 2 * phi * ellint_k_imp (k, pol, precision_tag_type ()) / constants::pi <T>();
80
+ result = 2 * phi * ellint_k_imp (k, pol, one_minus_k2) / constants::pi <T>();
84
81
BOOST_MATH_INSTRUMENT_VARIABLE (result);
85
82
}
86
83
else
@@ -121,31 +118,40 @@ T ellint_f_imp(T phi, T k, const Policy& pol)
121
118
BOOST_MATH_ASSERT (rphi != 0 ); // precondition, can't be true if sin(rphi) != 0.
122
119
//
123
120
// Use http://dlmf.nist.gov/19.25#E5, note that
124
- // c-1 simplifies to cot^2(rphi) which avoid cancellation:
121
+ // c-1 simplifies to cot^2(rphi) which avoids cancellation.
122
+ // Likewise c - k^2 is the same as (c - 1) + (1 - k^2).
125
123
//
126
124
T c = 1 / sinp;
127
- result = static_cast <T>(s * ellint_rf_imp (T (cosp / sinp), T (c - k * k), c, pol));
125
+ T c_minus_one = cosp / sinp;
126
+ T cross = fabs (c / (k * k));
127
+ T arg2;
128
+ if ((cross > 0 .9f ) && (cross < 1 .1f ))
129
+ arg2 = c_minus_one + one_minus_k2;
130
+ else
131
+ arg2 = c - k * k;
132
+ result = static_cast <T>(s * ellint_rf_imp (c_minus_one, arg2, c, pol));
128
133
}
129
134
else
130
135
result = s * sin (rphi);
131
136
BOOST_MATH_INSTRUMENT_VARIABLE (result);
132
137
if (m != 0 )
133
138
{
134
- typedef std::integral_constant<int ,
135
- std::is_floating_point<T>::value&& std::numeric_limits<T>::digits && (std::numeric_limits<T>::digits <= 54 ) ? 0 :
136
- std::is_floating_point<T>::value && std::numeric_limits<T>::digits && (std::numeric_limits<T>::digits <= 64 ) ? 1 : 2
137
- > precision_tag_type;
138
-
139
- result += m * ellint_k_imp (k, pol, precision_tag_type ());
139
+ result += m * ellint_k_imp (k, pol, one_minus_k2);
140
140
BOOST_MATH_INSTRUMENT_VARIABLE (result);
141
141
}
142
142
}
143
143
return invert ? T (-result) : result;
144
144
}
145
145
146
+ template <typename T, typename Policy>
147
+ inline T ellint_f_imp (T phi, T k, const Policy& pol)
148
+ {
149
+ return ellint_f_imp (phi, k, pol, T (1 - k * k));
150
+ }
151
+
146
152
// Complete elliptic integral (Legendre form) of the first kind
147
153
template <typename T, typename Policy>
148
- T ellint_k_imp (T k, const Policy& pol, std::integral_constant< int , 2 > const & )
154
+ T ellint_k_imp (T k, const Policy& pol, T one_minus_k2 )
149
155
{
150
156
BOOST_MATH_STD_USING
151
157
using namespace boost ::math::tools;
@@ -162,12 +168,16 @@ T ellint_k_imp(T k, const Policy& pol, std::integral_constant<int, 2> const&)
162
168
}
163
169
164
170
T x = 0 ;
165
- T y = 1 - k * k;
166
171
T z = 1 ;
167
- T value = ellint_rf_imp (x, y , z, pol);
172
+ T value = ellint_rf_imp (x, one_minus_k2 , z, pol);
168
173
169
174
return value;
170
175
}
176
+ template <typename T, typename Policy>
177
+ inline T ellint_k_imp (T k, const Policy& pol, std::integral_constant<int , 2 > const &)
178
+ {
179
+ return ellint_k_imp (k, pol, T (1 - k * k));
180
+ }
171
181
172
182
//
173
183
// Special versions for double and 80-bit long double precision,
0 commit comments