comparison DEPENDENCIES/generic/include/boost/math/special_functions/next.hpp @ 101:c530137014c0

Update Boost headers (1.58.0)
author Chris Cannam
date Mon, 07 Sep 2015 11:12:49 +0100
parents 2665513ce2d3
children
comparison
equal deleted inserted replaced
100:793467b5e61c 101:c530137014c0
8 8
9 #ifdef _MSC_VER 9 #ifdef _MSC_VER
10 #pragma once 10 #pragma once
11 #endif 11 #endif
12 12
13 #include <boost/math/special_functions/math_fwd.hpp>
13 #include <boost/math/policies/error_handling.hpp> 14 #include <boost/math/policies/error_handling.hpp>
14 #include <boost/math/special_functions/fpclassify.hpp> 15 #include <boost/math/special_functions/fpclassify.hpp>
15 #include <boost/math/special_functions/sign.hpp> 16 #include <boost/math/special_functions/sign.hpp>
16 #include <boost/math/special_functions/trunc.hpp> 17 #include <boost/math/special_functions/trunc.hpp>
17 18
18 #ifdef BOOST_MSVC
19 #include <float.h> 19 #include <float.h>
20
21 #if !defined(_CRAYC) && !defined(__CUDACC__) && (!defined(__GNUC__) || (__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ > 3)))
22 #if (defined(_M_IX86_FP) && (_M_IX86_FP >= 2)) || defined(__SSE2__)
23 #include "xmmintrin.h"
24 #define BOOST_MATH_CHECK_SSE2
25 #endif
20 #endif 26 #endif
21 27
22 namespace boost{ namespace math{ 28 namespace boost{ namespace math{
23 29
24 namespace detail{ 30 namespace detail{
30 // numeric_limits lies about denorms being present - particularly 36 // numeric_limits lies about denorms being present - particularly
31 // when this can be turned on or off at runtime, as is the case 37 // when this can be turned on or off at runtime, as is the case
32 // when using the SSE2 registers in DAZ or FTZ mode. 38 // when using the SSE2 registers in DAZ or FTZ mode.
33 // 39 //
34 static const T m = std::numeric_limits<T>::denorm_min(); 40 static const T m = std::numeric_limits<T>::denorm_min();
35 return ((tools::min_value<T>() - m) == tools::min_value<T>()) ? tools::min_value<T>() : m; 41 #ifdef BOOST_MATH_CHECK_SSE2
42 return (_mm_getcsr() & (_MM_FLUSH_ZERO_ON | 0x40)) ? tools::min_value<T>() : m;;
43 #else
44 return ((tools::min_value<T>() / 2) == 0) ? tools::min_value<T>() : m;
45 #endif
36 } 46 }
37 47
38 template <class T> 48 template <class T>
39 inline T get_smallest_value(mpl::false_ const&) 49 inline T get_smallest_value(mpl::false_ const&)
40 { 50 {
101 int expon; 111 int expon;
102 static const char* function = "float_next<%1%>(%1%)"; 112 static const char* function = "float_next<%1%>(%1%)";
103 113
104 int fpclass = (boost::math::fpclassify)(val); 114 int fpclass = (boost::math::fpclassify)(val);
105 115
106 if((fpclass == FP_NAN) || (fpclass == FP_INFINITE)) 116 if((fpclass == (int)FP_NAN) || (fpclass == (int)FP_INFINITE))
107 { 117 {
108 if(val < 0) 118 if(val < 0)
109 return -tools::max_value<T>(); 119 return -tools::max_value<T>();
110 return policies::raise_domain_error<T>( 120 return policies::raise_domain_error<T>(
111 function, 121 function,
116 return policies::raise_overflow_error<T>(function, 0, pol); 126 return policies::raise_overflow_error<T>(function, 0, pol);
117 127
118 if(val == 0) 128 if(val == 0)
119 return detail::get_smallest_value<T>(); 129 return detail::get_smallest_value<T>();
120 130
121 if((fpclass != FP_SUBNORMAL) && (fpclass != FP_ZERO) && (fabs(val) < detail::get_min_shift_value<T>()) && (val != -tools::min_value<T>())) 131 if((fpclass != (int)FP_SUBNORMAL) && (fpclass != (int)FP_ZERO) && (fabs(val) < detail::get_min_shift_value<T>()) && (val != -tools::min_value<T>()))
122 { 132 {
123 // 133 //
124 // Special case: if the value of the least significant bit is a denorm, and the result 134 // Special case: if the value of the least significant bit is a denorm, and the result
125 // would not be a denorm, then shift the input, increment, and shift back. 135 // would not be a denorm, then shift the input, increment, and shift back.
126 // This avoids issues with the Intel SSE2 registers when the FTZ or DAZ flags are set. 136 // This avoids issues with the Intel SSE2 registers when the FTZ or DAZ flags are set.
183 int expon; 193 int expon;
184 static const char* function = "float_prior<%1%>(%1%)"; 194 static const char* function = "float_prior<%1%>(%1%)";
185 195
186 int fpclass = (boost::math::fpclassify)(val); 196 int fpclass = (boost::math::fpclassify)(val);
187 197
188 if((fpclass == FP_NAN) || (fpclass == FP_INFINITE)) 198 if((fpclass == (int)FP_NAN) || (fpclass == (int)FP_INFINITE))
189 { 199 {
190 if(val > 0) 200 if(val > 0)
191 return tools::max_value<T>(); 201 return tools::max_value<T>();
192 return policies::raise_domain_error<T>( 202 return policies::raise_domain_error<T>(
193 function, 203 function,
198 return -policies::raise_overflow_error<T>(function, 0, pol); 208 return -policies::raise_overflow_error<T>(function, 0, pol);
199 209
200 if(val == 0) 210 if(val == 0)
201 return -detail::get_smallest_value<T>(); 211 return -detail::get_smallest_value<T>();
202 212
203 if((fpclass != FP_SUBNORMAL) && (fpclass != FP_ZERO) && (fabs(val) < detail::get_min_shift_value<T>()) && (val != tools::min_value<T>())) 213 if((fpclass != (int)FP_SUBNORMAL) && (fpclass != (int)FP_ZERO) && (fabs(val) < detail::get_min_shift_value<T>()) && (val != tools::min_value<T>()))
204 { 214 {
205 // 215 //
206 // Special case: if the value of the least significant bit is a denorm, and the result 216 // Special case: if the value of the least significant bit is a denorm, and the result
207 // would not be a denorm, then shift the input, increment, and shift back. 217 // would not be a denorm, then shift the input, increment, and shift back.
208 // This avoids issues with the Intel SSE2 registers when the FTZ or DAZ flags are set. 218 // This avoids issues with the Intel SSE2 registers when the FTZ or DAZ flags are set.
316 // 326 //
317 // Note that if a is a denorm then the usual formula fails 327 // Note that if a is a denorm then the usual formula fails
318 // because we actually have fewer than tools::digits<T>() 328 // because we actually have fewer than tools::digits<T>()
319 // significant bits in the representation: 329 // significant bits in the representation:
320 // 330 //
321 frexp(((boost::math::fpclassify)(a) == FP_SUBNORMAL) ? tools::min_value<T>() : a, &expon); 331 frexp(((boost::math::fpclassify)(a) == (int)FP_SUBNORMAL) ? tools::min_value<T>() : a, &expon);
322 T upper = ldexp(T(1), expon); 332 T upper = ldexp(T(1), expon);
323 T result = 0; 333 T result = 0;
324 expon = tools::digits<T>() - expon; 334 expon = tools::digits<T>() - expon;
325 // 335 //
326 // If b is greater than upper, then we *must* split the calculation 336 // If b is greater than upper, then we *must* split the calculation
333 // 343 //
334 // Use compensated double-double addition to avoid rounding 344 // Use compensated double-double addition to avoid rounding
335 // errors in the subtraction: 345 // errors in the subtraction:
336 // 346 //
337 T mb, x, y, z; 347 T mb, x, y, z;
338 if(((boost::math::fpclassify)(a) == FP_SUBNORMAL) || (b - a < tools::min_value<T>())) 348 if(((boost::math::fpclassify)(a) == (int)FP_SUBNORMAL) || (b - a < tools::min_value<T>()))
339 { 349 {
340 // 350 //
341 // Special case - either one end of the range is a denormal, or else the difference is. 351 // Special case - either one end of the range is a denormal, or else the difference is.
342 // The regular code will fail if we're using the SSE2 registers on Intel and either 352 // The regular code will fail if we're using the SSE2 registers on Intel and either
343 // the FTZ or DAZ flags are set. 353 // the FTZ or DAZ flags are set.
397 // 407 //
398 static const char* function = "float_advance<%1%>(%1%, int)"; 408 static const char* function = "float_advance<%1%>(%1%, int)";
399 409
400 int fpclass = (boost::math::fpclassify)(val); 410 int fpclass = (boost::math::fpclassify)(val);
401 411
402 if((fpclass == FP_NAN) || (fpclass == FP_INFINITE)) 412 if((fpclass == (int)FP_NAN) || (fpclass == (int)FP_INFINITE))
403 return policies::raise_domain_error<T>( 413 return policies::raise_domain_error<T>(
404 function, 414 function,
405 "Argument val must be finite, but got %1%", val, pol); 415 "Argument val must be finite, but got %1%", val, pol);
406 416
407 if(val < 0) 417 if(val < 0)
454 expon++; 464 expon++;
455 } 465 }
456 limit_distance = float_distance(val, limit); 466 limit_distance = float_distance(val, limit);
457 if(distance && (limit_distance == 0)) 467 if(distance && (limit_distance == 0))
458 { 468 {
459 policies::raise_evaluation_error<T>(function, "Internal logic failed while trying to increment floating point value %1%: most likely your FPU is in non-IEEE conforming mode.", val, pol); 469 return policies::raise_evaluation_error<T>(function, "Internal logic failed while trying to increment floating point value %1%: most likely your FPU is in non-IEEE conforming mode.", val, pol);
460 } 470 }
461 } 471 }
462 if((0.5f == frexp(val, &expon)) && (distance < 0)) 472 if((0.5f == frexp(val, &expon)) && (distance < 0))
463 --expon; 473 --expon;
464 T diff = 0; 474 T diff = 0;