00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef EIGEN_MATHFUNCTIONS_H
00026 #define EIGEN_MATHFUNCTIONS_H
00027
00028 template<typename T> inline typename NumTraits<T>::Real precision();
00029 template<typename T> inline typename NumTraits<T>::Real machine_epsilon();
00030 template<typename T> inline T ei_random(T a, T b);
00031 template<typename T> inline T ei_random();
00032 template<typename T> inline T ei_random_amplitude()
00033 {
00034 if(NumTraits<T>::HasFloatingPoint) return static_cast<T>(1);
00035 else return static_cast<T>(10);
00036 }
00037
00038
00039
00040
00041
00042 template<> inline int precision<int>() { return 0; }
00043 template<> inline int machine_epsilon<int>() { return 0; }
00044 inline int ei_real(int x) { return x; }
00045 inline int ei_imag(int) { return 0; }
00046 inline int ei_conj(int x) { return x; }
00047 inline int ei_abs(int x) { return std::abs(x); }
00048 inline int ei_abs2(int x) { return x*x; }
00049 inline int ei_sqrt(int) { ei_assert(false); return 0; }
00050 inline int ei_exp(int) { ei_assert(false); return 0; }
00051 inline int ei_log(int) { ei_assert(false); return 0; }
00052 inline int ei_sin(int) { ei_assert(false); return 0; }
00053 inline int ei_cos(int) { ei_assert(false); return 0; }
00054 inline int ei_atan2(int, int) { ei_assert(false); return 0; }
00055 inline int ei_pow(int x, int y) { return int(std::pow(double(x), y)); }
00056
00057 template<> inline int ei_random(int a, int b)
00058 {
00059
00060 return a + static_cast<int>((b-a+1) * (std::rand() / (RAND_MAX + 1.0)));
00061 }
00062 template<> inline int ei_random()
00063 {
00064 return ei_random<int>(-ei_random_amplitude<int>(), ei_random_amplitude<int>());
00065 }
00066 inline bool ei_isMuchSmallerThan(int a, int, int = precision<int>())
00067 {
00068 return a == 0;
00069 }
00070 inline bool ei_isApprox(int a, int b, int = precision<int>())
00071 {
00072 return a == b;
00073 }
00074 inline bool ei_isApproxOrLessThan(int a, int b, int = precision<int>())
00075 {
00076 return a <= b;
00077 }
00078
00079
00080
00081
00082
00083 template<> inline float precision<float>() { return 1e-5f; }
00084 template<> inline float machine_epsilon<float>() { return 1.192e-07f; }
00085 inline float ei_real(float x) { return x; }
00086 inline float ei_imag(float) { return 0.f; }
00087 inline float ei_conj(float x) { return x; }
00088 inline float ei_abs(float x) { return std::abs(x); }
00089 inline float ei_abs2(float x) { return x*x; }
00090 inline float ei_sqrt(float x) { return std::sqrt(x); }
00091 inline float ei_exp(float x) { return std::exp(x); }
00092 inline float ei_log(float x) { return std::log(x); }
00093 inline float ei_sin(float x) { return std::sin(x); }
00094 inline float ei_cos(float x) { return std::cos(x); }
00095 inline float ei_atan2(float y, float x) { return std::atan2(y,x); }
00096 inline float ei_pow(float x, float y) { return std::pow(x, y); }
00097
00098 template<> inline float ei_random(float a, float b)
00099 {
00100 #ifdef EIGEN_NICE_RANDOM
00101 int i;
00102 do { i = ei_random<int>(256*int(a),256*int(b));
00103 } while(i==0);
00104 return float(i)/256.f;
00105 #else
00106 return a + (b-a) * float(std::rand()) / float(RAND_MAX);
00107 #endif
00108 }
00109 template<> inline float ei_random()
00110 {
00111 return ei_random<float>(-ei_random_amplitude<float>(), ei_random_amplitude<float>());
00112 }
00113 inline bool ei_isMuchSmallerThan(float a, float b, float prec = precision<float>())
00114 {
00115 return ei_abs(a) <= ei_abs(b) * prec;
00116 }
00117 inline bool ei_isApprox(float a, float b, float prec = precision<float>())
00118 {
00119 return ei_abs(a - b) <= std::min(ei_abs(a), ei_abs(b)) * prec;
00120 }
00121 inline bool ei_isApproxOrLessThan(float a, float b, float prec = precision<float>())
00122 {
00123 return a <= b || ei_isApprox(a, b, prec);
00124 }
00125
00126
00127
00128
00129
00130 template<> inline double precision<double>() { return 1e-11; }
00131 template<> inline double machine_epsilon<double>() { return 2.220e-16; }
00132
00133 inline double ei_real(double x) { return x; }
00134 inline double ei_imag(double) { return 0.; }
00135 inline double ei_conj(double x) { return x; }
00136 inline double ei_abs(double x) { return std::abs(x); }
00137 inline double ei_abs2(double x) { return x*x; }
00138 inline double ei_sqrt(double x) { return std::sqrt(x); }
00139 inline double ei_exp(double x) { return std::exp(x); }
00140 inline double ei_log(double x) { return std::log(x); }
00141 inline double ei_sin(double x) { return std::sin(x); }
00142 inline double ei_cos(double x) { return std::cos(x); }
00143 inline double ei_atan2(double y, double x) { return std::atan2(y,x); }
00144 inline double ei_pow(double x, double y) { return std::pow(x, y); }
00145
00146 template<> inline double ei_random(double a, double b)
00147 {
00148 #ifdef EIGEN_NICE_RANDOM
00149 int i;
00150 do { i= ei_random<int>(256*int(a),256*int(b));
00151 } while(i==0);
00152 return i/256.;
00153 #else
00154 return a + (b-a) * std::rand() / RAND_MAX;
00155 #endif
00156 }
00157 template<> inline double ei_random()
00158 {
00159 return ei_random<double>(-ei_random_amplitude<double>(), ei_random_amplitude<double>());
00160 }
00161 inline bool ei_isMuchSmallerThan(double a, double b, double prec = precision<double>())
00162 {
00163 return ei_abs(a) <= ei_abs(b) * prec;
00164 }
00165 inline bool ei_isApprox(double a, double b, double prec = precision<double>())
00166 {
00167 return ei_abs(a - b) <= std::min(ei_abs(a), ei_abs(b)) * prec;
00168 }
00169 inline bool ei_isApproxOrLessThan(double a, double b, double prec = precision<double>())
00170 {
00171 return a <= b || ei_isApprox(a, b, prec);
00172 }
00173
00174
00175
00176
00177
00178 template<> inline float precision<std::complex<float> >() { return precision<float>(); }
00179 template<> inline float machine_epsilon<std::complex<float> >() { return machine_epsilon<float>(); }
00180 inline float ei_real(const std::complex<float>& x) { return std::real(x); }
00181 inline float ei_imag(const std::complex<float>& x) { return std::imag(x); }
00182 inline std::complex<float> ei_conj(const std::complex<float>& x) { return std::conj(x); }
00183 inline float ei_abs(const std::complex<float>& x) { return std::abs(x); }
00184 inline float ei_abs2(const std::complex<float>& x) { return std::norm(x); }
00185 inline std::complex<float> ei_exp(std::complex<float> x) { return std::exp(x); }
00186 inline std::complex<float> ei_sin(std::complex<float> x) { return std::sin(x); }
00187 inline std::complex<float> ei_cos(std::complex<float> x) { return std::cos(x); }
00188 inline std::complex<float> ei_atan2(std::complex<float>, std::complex<float> ) { ei_assert(false); return 0; }
00189
00190 template<> inline std::complex<float> ei_random()
00191 {
00192 return std::complex<float>(ei_random<float>(), ei_random<float>());
00193 }
00194 inline bool ei_isMuchSmallerThan(const std::complex<float>& a, const std::complex<float>& b, float prec = precision<float>())
00195 {
00196 return ei_abs2(a) <= ei_abs2(b) * prec * prec;
00197 }
00198 inline bool ei_isMuchSmallerThan(const std::complex<float>& a, float b, float prec = precision<float>())
00199 {
00200 return ei_abs2(a) <= ei_abs2(b) * prec * prec;
00201 }
00202 inline bool ei_isApprox(const std::complex<float>& a, const std::complex<float>& b, float prec = precision<float>())
00203 {
00204 return ei_isApprox(ei_real(a), ei_real(b), prec)
00205 && ei_isApprox(ei_imag(a), ei_imag(b), prec);
00206 }
00207
00208
00209
00210
00211
00212
00213 template<> inline double precision<std::complex<double> >() { return precision<double>(); }
00214 template<> inline double machine_epsilon<std::complex<double> >() { return machine_epsilon<double>(); }
00215 inline double ei_real(const std::complex<double>& x) { return std::real(x); }
00216 inline double ei_imag(const std::complex<double>& x) { return std::imag(x); }
00217 inline std::complex<double> ei_conj(const std::complex<double>& x) { return std::conj(x); }
00218 inline double ei_abs(const std::complex<double>& x) { return std::abs(x); }
00219 inline double ei_abs2(const std::complex<double>& x) { return std::norm(x); }
00220 inline std::complex<double> ei_exp(std::complex<double> x) { return std::exp(x); }
00221 inline std::complex<double> ei_sin(std::complex<double> x) { return std::sin(x); }
00222 inline std::complex<double> ei_cos(std::complex<double> x) { return std::cos(x); }
00223 inline std::complex<double> ei_atan2(std::complex<double>, std::complex<double>) { ei_assert(false); return 0; }
00224
00225 template<> inline std::complex<double> ei_random()
00226 {
00227 return std::complex<double>(ei_random<double>(), ei_random<double>());
00228 }
00229 inline bool ei_isMuchSmallerThan(const std::complex<double>& a, const std::complex<double>& b, double prec = precision<double>())
00230 {
00231 return ei_abs2(a) <= ei_abs2(b) * prec * prec;
00232 }
00233 inline bool ei_isMuchSmallerThan(const std::complex<double>& a, double b, double prec = precision<double>())
00234 {
00235 return ei_abs2(a) <= ei_abs2(b) * prec * prec;
00236 }
00237 inline bool ei_isApprox(const std::complex<double>& a, const std::complex<double>& b, double prec = precision<double>())
00238 {
00239 return ei_isApprox(ei_real(a), ei_real(b), prec)
00240 && ei_isApprox(ei_imag(a), ei_imag(b), prec);
00241 }
00242
00243
00244
00245
00246
00247
00248
00249 template<> inline long double precision<long double>() { return precision<double>(); }
00250 template<> inline long double machine_epsilon<long double>() { return 1.084e-19l; }
00251 inline long double ei_real(long double x) { return x; }
00252 inline long double ei_imag(long double) { return 0.; }
00253 inline long double ei_conj(long double x) { return x; }
00254 inline long double ei_abs(long double x) { return std::abs(x); }
00255 inline long double ei_abs2(long double x) { return x*x; }
00256 inline long double ei_sqrt(long double x) { return std::sqrt(x); }
00257 inline long double ei_exp(long double x) { return std::exp(x); }
00258 inline long double ei_log(long double x) { return std::log(x); }
00259 inline long double ei_sin(long double x) { return std::sin(x); }
00260 inline long double ei_cos(long double x) { return std::cos(x); }
00261 inline long double ei_atan2(long double y, long double x) { return std::atan2(y,x); }
00262 inline long double ei_pow(long double x, long double y) { return std::pow(x, y); }
00263
00264 template<> inline long double ei_random(long double a, long double b)
00265 {
00266 return ei_random<double>(static_cast<double>(a),static_cast<double>(b));
00267 }
00268 template<> inline long double ei_random()
00269 {
00270 return ei_random<double>(-ei_random_amplitude<double>(), ei_random_amplitude<double>());
00271 }
00272 inline bool ei_isMuchSmallerThan(long double a, long double b, long double prec = precision<long double>())
00273 {
00274 return ei_abs(a) <= ei_abs(b) * prec;
00275 }
00276 inline bool ei_isApprox(long double a, long double b, long double prec = precision<long double>())
00277 {
00278 return ei_abs(a - b) <= std::min(ei_abs(a), ei_abs(b)) * prec;
00279 }
00280 inline bool ei_isApproxOrLessThan(long double a, long double b, long double prec = precision<long double>())
00281 {
00282 return a <= b || ei_isApprox(a, b, prec);
00283 }
00284
00285 template<typename T> inline T ei_hypot(T x, T y)
00286 {
00287 T _x = ei_abs(x);
00288 T _y = ei_abs(y);
00289 T p = std::max(_x, _y);
00290 T q = std::min(_x, _y);
00291 T qp = q/p;
00292 return p * ei_sqrt(T(1) + qp*qp);
00293 }
00294
00295 #endif // EIGEN_MATHFUNCTIONS_H