v0.15.5
Loading...
Searching...
No Matches
lambert_w_tools.hpp
Go to the documentation of this file.
1
2// Copyright Balazs Cziraki 2016.
3// Use, modification and distribution are subject to the
4// Boost Software License, Version 1.0. (See accompanying file
5// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6
7#ifndef BOOST_MATH_LAMBERT_W_TOOLS_HPP_INCLUDED
8#define BOOST_MATH_LAMBERT_W_TOOLS_HPP_INCLUDED
9
10#include <cmath>
11#include <complex>
12#include <limits>
13#include <algorithm>
14#include <boost/math/constants/constants.hpp>
15#include <boost/type_traits/is_complex.hpp>
16//#include <boost/typeof/typeof.hpp>
17#include <boost/array.hpp>
18
19namespace boost
20{
21namespace math
22{
23namespace lambw
24{
25 //Function overloads returning the imaginary unit for complex types, NaN otherwise.
26 template<class ArgumentType>
27 inline const ArgumentType& _imaginary_unit(const ArgumentType &z)
28 {
29 static const ArgumentType i = std::numeric_limits<ArgumentType>::quiet_NaN();
30
31 return i;
32 }
33
34 template<class ArgumentType>
35 inline const std::complex<ArgumentType>& _imaginary_unit(const std::complex<ArgumentType> &z)
36 {
37 static const std::complex<ArgumentType> i((ArgumentType)0.,(ArgumentType)1.);
38
39 return i;
40 }
41
42 //Function returning exp(-1)
43 template<class CoeffType>
44 inline const CoeffType& rec_e()
45 {
46 using std::exp;
47
48 static const CoeffType ans = exp((CoeffType)(-1.));
49
50 return ans;
51 }
52
53 //Function overloads to return the real part of any number
54 template<class CoeffType>
55 inline CoeffType _complex_real(const CoeffType &z)
56 {
57 return z;
58 }
59
60 template<class CoeffType>
61 inline CoeffType _complex_real(const std::complex<CoeffType> &z)
62 {
63 return z.real();
64 }
65
66 //Function overloads to return the imaginary part of any number
67 template<class CoeffType>
68 inline CoeffType _complex_imag(const CoeffType &z)
69 {
70 static const CoeffType zero = (CoeffType)0.;
71 return zero;
72 }
73
74 template<class CoeffType>
75 inline CoeffType _complex_imag(const std::complex<CoeffType> &z)
76 {
77 return z.imag();
78 }
79
80 //Function overloads to return 1. For some reason when using boost::multiprecision types _series_sum does not compile for sum = (ArgumentType)1.
81 template<class CoeffType>
82 inline const CoeffType& _complex_one(const CoeffType &z)
83 {
84 static const CoeffType ans = (CoeffType)1.;
85 return ans;
86 }
87
88 template<class CoeffType>
89 inline const std::complex<CoeffType>& _complex_one(const std::complex<CoeffType> &z)
90 {
91 static const std::complex<CoeffType> ans((CoeffType)1.,(CoeffType)0.);
92 return ans;
93 }
94
95 //Evaluates a power series, but it requires the coefficients to be processed as follows: c'_k = c_{k+1}/c_k
96 template<class ArgumentType, class CoeffType, std::size_t L>
97 ArgumentType _series_sum(const ArgumentType &z, const boost::array<CoeffType,L> &c)
98 {
99 ArgumentType sum = _complex_one(z);
100
101 for(std::size_t k = 0; k < L; ++k)
102 {
103 sum = _complex_one(z)+c[L-k-1]*z*sum;
104 }
105
106 return sum;
107 }
108
109 //Creates an array of the coefficients defined by the function argument coeffs.
110 template<class CoeffType, std::size_t L>
111 boost::array<CoeffType,L> _coeff_array(CoeffType (&coeffs)(std::size_t) )
112 {
113 boost::array<CoeffType,L> ans;
114 for(std::size_t k = 0; k < L; ++k)
115 {
116 ans[k] = coeffs(k);
117 }
118 return ans;
119 }
120
121 //constexpr-s in these require C++14. BOOST_CONSTEXPR inserts constexpr-s from C++11, without checking for C++14 compatibility.
122 //Cuts up the complex plane on the imaginary axis in 2pi intervals, effectively repeating z-2pi*k for each integer k
123 template<class ArgumentType, class Policy>
124 /*BOOST_CONSTEXPR*/ ArgumentType _linstrips(const ArgumentType &z, const Policy &pol)
125 {
126 return z;
127 }
128
129 template<class ArgumentType, class Policy>
130 /*BOOST_CONSTEXPR*/ std::complex<ArgumentType> _linstrips(const std::complex<ArgumentType> &z, const Policy &pol)
131 {
132 return z-boost::math::constants::two_pi<ArgumentType>()
133 *_imaginary_unit(z)*boost::math::round(_complex_imag(z)/boost::math::constants::two_pi<ArgumentType>(),pol);
134 }
135
136 //Tests if w satisfies w*exp(w)=z. In order to avoid overflows it
137 //actually checks the equivalent, but numerically less precise log(w)+w=log(z), which is the logarithm of the previous.
138 //The relative errors (x1-x2)/x1 and (x1-x2)/x2 can be expressed as 1-x2/x1 and x1/x2-1, which in turn using logarithms:
139 //1-exp(log(x2)-log(x1)) and exp(log(x1)-log(x2))-1, or -expm1(log(x2)-log(x1)) and expm1(log(x1)-log(x2)).
140 //Since expm1(x) ~ x for small arguments both can equivalently be approximated with log(x1)-log(x2).
141 //On that basis this function tests for relative errors.
142 template<class ArgumentType, class Policy>
143 ArgumentType _test_s(const ArgumentType &z, const ArgumentType &w, const Policy &pol)
144 {
145 using std::log;
146 using std::abs;
147
148 if(_complex_real(z) < 0.)
149 {
150 return _linstrips(log(-w)+w-log(-z),pol);
151 }
152 else
153 {
154 return _linstrips(log(w)+w-log(z),pol);
155 }
156 }
157
158 template<class ArgumentType, class Policy>
159 ArgumentType _test(const ArgumentType &z, const ArgumentType &w, const Policy &pol)
160 {
161 using std::exp;
162 using std::abs;
163
164 ArgumentType t = w*exp(w);
165
166 return std::max(abs((z-t)/z),abs((z-t)/t));
167 }
168
169 template<class ArgumentType, class Policy>
170 ArgumentType _test(const std::complex<ArgumentType> &z, const std::complex<ArgumentType> &w, const Policy &pol)
171 {
172 using std::exp;
173 using std::abs;
174
175 std::complex<ArgumentType> t = w*exp(w);
176
177 return std::max(abs((z-t)/z),abs((z-t)/t));
178 }
179
180 //Abandoned exact evaluation of relative error, using expm1.
181 //expm1 is not defined for complex arguments, which is why this was abandoned.
182 /*
183 template<class ArgumentType>
184 ArgumentType _test(const ArgumentType &z, const ArgumentType &w)
185 {
186 return expm1(_test_s(z,w));
187 }
188 */
189 //Abandoned scoring system
190 /*
191 template<class ArgumentType, class CoeffType>
192 CoeffType _test_score(const ArgumentType &z, const ArgumentType &w)
193 {
194 using std::abs;
195 using std::log10;
196
197 return -log10(abs(_test_s(z,w)));
198 }
199 */
200
201 //Returns the k-th branch of the complex logarithm: log(z)+i*2pi*k
202 template<class ArgumentType, class IndexType>
203 ArgumentType _log_k(const ArgumentType &z, const IndexType& k)
204 {
205 using std::log;
206
207 return (k==0)?(log(z)):(std::numeric_limits<ArgumentType>::quiet_NaN());
208 }
209
210 template<class ArgumentType, class IndexType>
211 std::complex<ArgumentType> _log_k(const std::complex<ArgumentType> &z, const IndexType& k)
212 {
213 using std::log;
214
215 return log(z) + (boost::math::constants::two_pi<ArgumentType>()*k)*_imaginary_unit(z);
216 }
217} //namespace lambw
218} //namespace math
219} //namespace boost
220
221#endif // BOOST_MATH_LAMBERT_W_TOOLS_HPP_INCLUDED
FTensor::Index< 'i', SPACE_DIM > i
const double c
speed of light (cm/ns)
FTensor::Index< 'k', 3 > k
const CoeffType & _complex_one(const CoeffType &z)
const CoeffType & rec_e()
ArgumentType _test(const ArgumentType &z, const ArgumentType &w, const Policy &pol)
const ArgumentType & _imaginary_unit(const ArgumentType &z)
ArgumentType _log_k(const ArgumentType &z, const IndexType &k)
ArgumentType _test_s(const ArgumentType &z, const ArgumentType &w, const Policy &pol)
boost::array< CoeffType, L > _coeff_array(CoeffType(&coeffs)(std::size_t))
CoeffType _complex_imag(const CoeffType &z)
ArgumentType _series_sum(const ArgumentType &z, const boost::array< CoeffType, L > &c)
CoeffType _complex_real(const CoeffType &z)
ArgumentType _linstrips(const ArgumentType &z, const Policy &pol)
constexpr double t
plate stiffness
Definition plate.cpp:58