Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/math/special_functions/fpclassify.hpp @ 16:2665513ce2d3
Add boost headers
author | Chris Cannam |
---|---|
date | Tue, 05 Aug 2014 11:11:38 +0100 |
parents | |
children | c530137014c0 |
comparison
equal
deleted
inserted
replaced
15:663ca0da4350 | 16:2665513ce2d3 |
---|---|
1 // Copyright John Maddock 2005-2008. | |
2 // Copyright (c) 2006-2008 Johan Rade | |
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_FPCLASSIFY_HPP | |
8 #define BOOST_MATH_FPCLASSIFY_HPP | |
9 | |
10 #ifdef _MSC_VER | |
11 #pragma once | |
12 #endif | |
13 | |
14 #include <math.h> | |
15 #include <boost/config/no_tr1/cmath.hpp> | |
16 #include <boost/limits.hpp> | |
17 #include <boost/math/tools/real_cast.hpp> | |
18 #include <boost/type_traits/is_floating_point.hpp> | |
19 #include <boost/math/special_functions/math_fwd.hpp> | |
20 #include <boost/math/special_functions/detail/fp_traits.hpp> | |
21 /*! | |
22 \file fpclassify.hpp | |
23 \brief Classify floating-point value as normal, subnormal, zero, infinite, or NaN. | |
24 \version 1.0 | |
25 \author John Maddock | |
26 */ | |
27 | |
28 /* | |
29 | |
30 1. If the platform is C99 compliant, then the native floating point | |
31 classification functions are used. However, note that we must only | |
32 define the functions which call std::fpclassify etc if that function | |
33 really does exist: otherwise a compiler may reject the code even though | |
34 the template is never instantiated. | |
35 | |
36 2. If the platform is not C99 compliant, and the binary format for | |
37 a floating point type (float, double or long double) can be determined | |
38 at compile time, then the following algorithm is used: | |
39 | |
40 If all exponent bits, the flag bit (if there is one), | |
41 and all significand bits are 0, then the number is zero. | |
42 | |
43 If all exponent bits and the flag bit (if there is one) are 0, | |
44 and at least one significand bit is 1, then the number is subnormal. | |
45 | |
46 If all exponent bits are 1 and all significand bits are 0, | |
47 then the number is infinity. | |
48 | |
49 If all exponent bits are 1 and at least one significand bit is 1, | |
50 then the number is a not-a-number. | |
51 | |
52 Otherwise the number is normal. | |
53 | |
54 This algorithm works for the IEEE 754 representation, | |
55 and also for several non IEEE 754 formats. | |
56 | |
57 Most formats have the structure | |
58 sign bit + exponent bits + significand bits. | |
59 | |
60 A few have the structure | |
61 sign bit + exponent bits + flag bit + significand bits. | |
62 The flag bit is 0 for zero and subnormal numbers, | |
63 and 1 for normal numbers and NaN. | |
64 It is 0 (Motorola 68K) or 1 (Intel) for infinity. | |
65 | |
66 To get the bits, the four or eight most significant bytes are copied | |
67 into an uint32_t or uint64_t and bit masks are applied. | |
68 This covers all the exponent bits and the flag bit (if there is one), | |
69 but not always all the significand bits. | |
70 Some of the functions below have two implementations, | |
71 depending on whether all the significand bits are copied or not. | |
72 | |
73 3. If the platform is not C99 compliant, and the binary format for | |
74 a floating point type (float, double or long double) can not be determined | |
75 at compile time, then comparison with std::numeric_limits values | |
76 is used. | |
77 | |
78 */ | |
79 | |
80 #if defined(_MSC_VER) || defined(__BORLANDC__) | |
81 #include <float.h> | |
82 #endif | |
83 | |
84 #ifdef BOOST_NO_STDC_NAMESPACE | |
85 namespace std{ using ::abs; using ::fabs; } | |
86 #endif | |
87 | |
88 namespace boost{ | |
89 | |
90 // | |
91 // This must not be located in any namespace under boost::math | |
92 // otherwise we can get into an infinite loop if isnan is | |
93 // a #define for "isnan" ! | |
94 // | |
95 namespace math_detail{ | |
96 | |
97 #ifdef BOOST_MSVC | |
98 #pragma warning(push) | |
99 #pragma warning(disable:4800) | |
100 #endif | |
101 | |
102 template <class T> | |
103 inline bool is_nan_helper(T t, const boost::true_type&) | |
104 { | |
105 #ifdef isnan | |
106 return isnan(t); | |
107 #elif defined(BOOST_MATH_DISABLE_STD_FPCLASSIFY) || !defined(BOOST_HAS_FPCLASSIFY) | |
108 (void)t; | |
109 return false; | |
110 #else // BOOST_HAS_FPCLASSIFY | |
111 return (BOOST_FPCLASSIFY_PREFIX fpclassify(t) == (int)FP_NAN); | |
112 #endif | |
113 } | |
114 | |
115 #ifdef BOOST_MSVC | |
116 #pragma warning(pop) | |
117 #endif | |
118 | |
119 template <class T> | |
120 inline bool is_nan_helper(T, const boost::false_type&) | |
121 { | |
122 return false; | |
123 } | |
124 | |
125 } | |
126 | |
127 namespace math{ | |
128 | |
129 namespace detail{ | |
130 | |
131 #ifdef BOOST_MATH_USE_STD_FPCLASSIFY | |
132 template <class T> | |
133 inline int fpclassify_imp BOOST_NO_MACRO_EXPAND(T t, const native_tag&) | |
134 { | |
135 return (std::fpclassify)(t); | |
136 } | |
137 #endif | |
138 | |
139 template <class T> | |
140 inline int fpclassify_imp BOOST_NO_MACRO_EXPAND(T t, const generic_tag<true>&) | |
141 { | |
142 BOOST_MATH_INSTRUMENT_VARIABLE(t); | |
143 | |
144 // whenever possible check for Nan's first: | |
145 #if defined(BOOST_HAS_FPCLASSIFY) && !defined(BOOST_MATH_DISABLE_STD_FPCLASSIFY) | |
146 if(::boost::math_detail::is_nan_helper(t, ::boost::is_floating_point<T>())) | |
147 return FP_NAN; | |
148 #elif defined(isnan) | |
149 if(boost::math_detail::is_nan_helper(t, ::boost::is_floating_point<T>())) | |
150 return FP_NAN; | |
151 #elif defined(_MSC_VER) || defined(__BORLANDC__) | |
152 if(::_isnan(boost::math::tools::real_cast<double>(t))) | |
153 return FP_NAN; | |
154 #endif | |
155 // std::fabs broken on a few systems especially for long long!!!! | |
156 T at = (t < T(0)) ? -t : t; | |
157 | |
158 // Use a process of exclusion to figure out | |
159 // what kind of type we have, this relies on | |
160 // IEEE conforming reals that will treat | |
161 // Nan's as unordered. Some compilers | |
162 // don't do this once optimisations are | |
163 // turned on, hence the check for nan's above. | |
164 if(at <= (std::numeric_limits<T>::max)()) | |
165 { | |
166 if(at >= (std::numeric_limits<T>::min)()) | |
167 return FP_NORMAL; | |
168 return (at != 0) ? FP_SUBNORMAL : FP_ZERO; | |
169 } | |
170 else if(at > (std::numeric_limits<T>::max)()) | |
171 return FP_INFINITE; | |
172 return FP_NAN; | |
173 } | |
174 | |
175 template <class T> | |
176 inline int fpclassify_imp BOOST_NO_MACRO_EXPAND(T t, const generic_tag<false>&) | |
177 { | |
178 #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS | |
179 if(std::numeric_limits<T>::is_specialized) | |
180 return fpclassify_imp(t, generic_tag<true>()); | |
181 #endif | |
182 // | |
183 // An unknown type with no numeric_limits support, | |
184 // so what are we supposed to do we do here? | |
185 // | |
186 BOOST_MATH_INSTRUMENT_VARIABLE(t); | |
187 | |
188 return t == 0 ? FP_ZERO : FP_NORMAL; | |
189 } | |
190 | |
191 template<class T> | |
192 int fpclassify_imp BOOST_NO_MACRO_EXPAND(T x, ieee_copy_all_bits_tag) | |
193 { | |
194 typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits; | |
195 | |
196 BOOST_MATH_INSTRUMENT_VARIABLE(x); | |
197 | |
198 BOOST_DEDUCED_TYPENAME traits::bits a; | |
199 traits::get_bits(x,a); | |
200 BOOST_MATH_INSTRUMENT_VARIABLE(a); | |
201 a &= traits::exponent | traits::flag | traits::significand; | |
202 BOOST_MATH_INSTRUMENT_VARIABLE((traits::exponent | traits::flag | traits::significand)); | |
203 BOOST_MATH_INSTRUMENT_VARIABLE(a); | |
204 | |
205 if(a <= traits::significand) { | |
206 if(a == 0) | |
207 return FP_ZERO; | |
208 else | |
209 return FP_SUBNORMAL; | |
210 } | |
211 | |
212 if(a < traits::exponent) return FP_NORMAL; | |
213 | |
214 a &= traits::significand; | |
215 if(a == 0) return FP_INFINITE; | |
216 | |
217 return FP_NAN; | |
218 } | |
219 | |
220 template<class T> | |
221 int fpclassify_imp BOOST_NO_MACRO_EXPAND(T x, ieee_copy_leading_bits_tag) | |
222 { | |
223 typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits; | |
224 | |
225 BOOST_MATH_INSTRUMENT_VARIABLE(x); | |
226 | |
227 BOOST_DEDUCED_TYPENAME traits::bits a; | |
228 traits::get_bits(x,a); | |
229 a &= traits::exponent | traits::flag | traits::significand; | |
230 | |
231 if(a <= traits::significand) { | |
232 if(x == 0) | |
233 return FP_ZERO; | |
234 else | |
235 return FP_SUBNORMAL; | |
236 } | |
237 | |
238 if(a < traits::exponent) return FP_NORMAL; | |
239 | |
240 a &= traits::significand; | |
241 traits::set_bits(x,a); | |
242 if(x == 0) return FP_INFINITE; | |
243 | |
244 return FP_NAN; | |
245 } | |
246 | |
247 #if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && (defined(BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY) || defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS)) | |
248 inline int fpclassify_imp BOOST_NO_MACRO_EXPAND(long double t, const native_tag&) | |
249 { | |
250 return boost::math::detail::fpclassify_imp(t, generic_tag<true>()); | |
251 } | |
252 #endif | |
253 | |
254 } // namespace detail | |
255 | |
256 template <class T> | |
257 inline int fpclassify BOOST_NO_MACRO_EXPAND(T t) | |
258 { | |
259 typedef typename detail::fp_traits<T>::type traits; | |
260 typedef typename traits::method method; | |
261 typedef typename tools::promote_args_permissive<T>::type value_type; | |
262 #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS | |
263 if(std::numeric_limits<T>::is_specialized && detail::is_generic_tag_false(static_cast<method*>(0))) | |
264 return detail::fpclassify_imp(static_cast<value_type>(t), detail::generic_tag<true>()); | |
265 return detail::fpclassify_imp(static_cast<value_type>(t), method()); | |
266 #else | |
267 return detail::fpclassify_imp(static_cast<value_type>(t), method()); | |
268 #endif | |
269 } | |
270 | |
271 #ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS | |
272 template <> | |
273 inline int fpclassify<long double> BOOST_NO_MACRO_EXPAND(long double t) | |
274 { | |
275 typedef detail::fp_traits<long double>::type traits; | |
276 typedef traits::method method; | |
277 typedef long double value_type; | |
278 #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS | |
279 if(std::numeric_limits<long double>::is_specialized && detail::is_generic_tag_false(static_cast<method*>(0))) | |
280 return detail::fpclassify_imp(static_cast<value_type>(t), detail::generic_tag<true>()); | |
281 return detail::fpclassify_imp(static_cast<value_type>(t), method()); | |
282 #else | |
283 return detail::fpclassify_imp(static_cast<value_type>(t), method()); | |
284 #endif | |
285 } | |
286 #endif | |
287 | |
288 namespace detail { | |
289 | |
290 #ifdef BOOST_MATH_USE_STD_FPCLASSIFY | |
291 template<class T> | |
292 inline bool isfinite_impl(T x, native_tag const&) | |
293 { | |
294 return (std::isfinite)(x); | |
295 } | |
296 #endif | |
297 | |
298 template<class T> | |
299 inline bool isfinite_impl(T x, generic_tag<true> const&) | |
300 { | |
301 return x >= -(std::numeric_limits<T>::max)() | |
302 && x <= (std::numeric_limits<T>::max)(); | |
303 } | |
304 | |
305 template<class T> | |
306 inline bool isfinite_impl(T x, generic_tag<false> const&) | |
307 { | |
308 #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS | |
309 if(std::numeric_limits<T>::is_specialized) | |
310 return isfinite_impl(x, generic_tag<true>()); | |
311 #endif | |
312 (void)x; // warning supression. | |
313 return true; | |
314 } | |
315 | |
316 template<class T> | |
317 inline bool isfinite_impl(T x, ieee_tag const&) | |
318 { | |
319 typedef BOOST_DEDUCED_TYPENAME detail::fp_traits<T>::type traits; | |
320 BOOST_DEDUCED_TYPENAME traits::bits a; | |
321 traits::get_bits(x,a); | |
322 a &= traits::exponent; | |
323 return a != traits::exponent; | |
324 } | |
325 | |
326 #if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && defined(BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY) | |
327 inline bool isfinite_impl BOOST_NO_MACRO_EXPAND(long double t, const native_tag&) | |
328 { | |
329 return boost::math::detail::isfinite_impl(t, generic_tag<true>()); | |
330 } | |
331 #endif | |
332 | |
333 } | |
334 | |
335 template<class T> | |
336 inline bool (isfinite)(T x) | |
337 { //!< \brief return true if floating-point type t is finite. | |
338 typedef typename detail::fp_traits<T>::type traits; | |
339 typedef typename traits::method method; | |
340 // typedef typename boost::is_floating_point<T>::type fp_tag; | |
341 typedef typename tools::promote_args_permissive<T>::type value_type; | |
342 return detail::isfinite_impl(static_cast<value_type>(x), method()); | |
343 } | |
344 | |
345 #ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS | |
346 template<> | |
347 inline bool (isfinite)(long double x) | |
348 { //!< \brief return true if floating-point type t is finite. | |
349 typedef detail::fp_traits<long double>::type traits; | |
350 typedef traits::method method; | |
351 typedef boost::is_floating_point<long double>::type fp_tag; | |
352 typedef long double value_type; | |
353 return detail::isfinite_impl(static_cast<value_type>(x), method()); | |
354 } | |
355 #endif | |
356 | |
357 //------------------------------------------------------------------------------ | |
358 | |
359 namespace detail { | |
360 | |
361 #ifdef BOOST_MATH_USE_STD_FPCLASSIFY | |
362 template<class T> | |
363 inline bool isnormal_impl(T x, native_tag const&) | |
364 { | |
365 return (std::isnormal)(x); | |
366 } | |
367 #endif | |
368 | |
369 template<class T> | |
370 inline bool isnormal_impl(T x, generic_tag<true> const&) | |
371 { | |
372 if(x < 0) x = -x; | |
373 return x >= (std::numeric_limits<T>::min)() | |
374 && x <= (std::numeric_limits<T>::max)(); | |
375 } | |
376 | |
377 template<class T> | |
378 inline bool isnormal_impl(T x, generic_tag<false> const&) | |
379 { | |
380 #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS | |
381 if(std::numeric_limits<T>::is_specialized) | |
382 return isnormal_impl(x, generic_tag<true>()); | |
383 #endif | |
384 return !(x == 0); | |
385 } | |
386 | |
387 template<class T> | |
388 inline bool isnormal_impl(T x, ieee_tag const&) | |
389 { | |
390 typedef BOOST_DEDUCED_TYPENAME detail::fp_traits<T>::type traits; | |
391 BOOST_DEDUCED_TYPENAME traits::bits a; | |
392 traits::get_bits(x,a); | |
393 a &= traits::exponent | traits::flag; | |
394 return (a != 0) && (a < traits::exponent); | |
395 } | |
396 | |
397 #if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && defined(BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY) | |
398 inline bool isnormal_impl BOOST_NO_MACRO_EXPAND(long double t, const native_tag&) | |
399 { | |
400 return boost::math::detail::isnormal_impl(t, generic_tag<true>()); | |
401 } | |
402 #endif | |
403 | |
404 } | |
405 | |
406 template<class T> | |
407 inline bool (isnormal)(T x) | |
408 { | |
409 typedef typename detail::fp_traits<T>::type traits; | |
410 typedef typename traits::method method; | |
411 //typedef typename boost::is_floating_point<T>::type fp_tag; | |
412 typedef typename tools::promote_args_permissive<T>::type value_type; | |
413 return detail::isnormal_impl(static_cast<value_type>(x), method()); | |
414 } | |
415 | |
416 #ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS | |
417 template<> | |
418 inline bool (isnormal)(long double x) | |
419 { | |
420 typedef detail::fp_traits<long double>::type traits; | |
421 typedef traits::method method; | |
422 typedef boost::is_floating_point<long double>::type fp_tag; | |
423 typedef long double value_type; | |
424 return detail::isnormal_impl(static_cast<value_type>(x), method()); | |
425 } | |
426 #endif | |
427 | |
428 //------------------------------------------------------------------------------ | |
429 | |
430 namespace detail { | |
431 | |
432 #ifdef BOOST_MATH_USE_STD_FPCLASSIFY | |
433 template<class T> | |
434 inline bool isinf_impl(T x, native_tag const&) | |
435 { | |
436 return (std::isinf)(x); | |
437 } | |
438 #endif | |
439 | |
440 template<class T> | |
441 inline bool isinf_impl(T x, generic_tag<true> const&) | |
442 { | |
443 (void)x; // in case the compiler thinks that x is unused because std::numeric_limits<T>::has_infinity is false | |
444 return std::numeric_limits<T>::has_infinity | |
445 && ( x == std::numeric_limits<T>::infinity() | |
446 || x == -std::numeric_limits<T>::infinity()); | |
447 } | |
448 | |
449 template<class T> | |
450 inline bool isinf_impl(T x, generic_tag<false> const&) | |
451 { | |
452 #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS | |
453 if(std::numeric_limits<T>::is_specialized) | |
454 return isinf_impl(x, generic_tag<true>()); | |
455 #endif | |
456 (void)x; // warning supression. | |
457 return false; | |
458 } | |
459 | |
460 template<class T> | |
461 inline bool isinf_impl(T x, ieee_copy_all_bits_tag const&) | |
462 { | |
463 typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits; | |
464 | |
465 BOOST_DEDUCED_TYPENAME traits::bits a; | |
466 traits::get_bits(x,a); | |
467 a &= traits::exponent | traits::significand; | |
468 return a == traits::exponent; | |
469 } | |
470 | |
471 template<class T> | |
472 inline bool isinf_impl(T x, ieee_copy_leading_bits_tag const&) | |
473 { | |
474 typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits; | |
475 | |
476 BOOST_DEDUCED_TYPENAME traits::bits a; | |
477 traits::get_bits(x,a); | |
478 a &= traits::exponent | traits::significand; | |
479 if(a != traits::exponent) | |
480 return false; | |
481 | |
482 traits::set_bits(x,0); | |
483 return x == 0; | |
484 } | |
485 | |
486 #if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && defined(BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY) | |
487 inline bool isinf_impl BOOST_NO_MACRO_EXPAND(long double t, const native_tag&) | |
488 { | |
489 return boost::math::detail::isinf_impl(t, generic_tag<true>()); | |
490 } | |
491 #endif | |
492 | |
493 } // namespace detail | |
494 | |
495 template<class T> | |
496 inline bool (isinf)(T x) | |
497 { | |
498 typedef typename detail::fp_traits<T>::type traits; | |
499 typedef typename traits::method method; | |
500 // typedef typename boost::is_floating_point<T>::type fp_tag; | |
501 typedef typename tools::promote_args_permissive<T>::type value_type; | |
502 return detail::isinf_impl(static_cast<value_type>(x), method()); | |
503 } | |
504 | |
505 #ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS | |
506 template<> | |
507 inline bool (isinf)(long double x) | |
508 { | |
509 typedef detail::fp_traits<long double>::type traits; | |
510 typedef traits::method method; | |
511 typedef boost::is_floating_point<long double>::type fp_tag; | |
512 typedef long double value_type; | |
513 return detail::isinf_impl(static_cast<value_type>(x), method()); | |
514 } | |
515 #endif | |
516 | |
517 //------------------------------------------------------------------------------ | |
518 | |
519 namespace detail { | |
520 | |
521 #ifdef BOOST_MATH_USE_STD_FPCLASSIFY | |
522 template<class T> | |
523 inline bool isnan_impl(T x, native_tag const&) | |
524 { | |
525 return (std::isnan)(x); | |
526 } | |
527 #endif | |
528 | |
529 template<class T> | |
530 inline bool isnan_impl(T x, generic_tag<true> const&) | |
531 { | |
532 return std::numeric_limits<T>::has_infinity | |
533 ? !(x <= std::numeric_limits<T>::infinity()) | |
534 : x != x; | |
535 } | |
536 | |
537 template<class T> | |
538 inline bool isnan_impl(T x, generic_tag<false> const&) | |
539 { | |
540 #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS | |
541 if(std::numeric_limits<T>::is_specialized) | |
542 return isnan_impl(x, generic_tag<true>()); | |
543 #endif | |
544 (void)x; // warning supression | |
545 return false; | |
546 } | |
547 | |
548 template<class T> | |
549 inline bool isnan_impl(T x, ieee_copy_all_bits_tag const&) | |
550 { | |
551 typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits; | |
552 | |
553 BOOST_DEDUCED_TYPENAME traits::bits a; | |
554 traits::get_bits(x,a); | |
555 a &= traits::exponent | traits::significand; | |
556 return a > traits::exponent; | |
557 } | |
558 | |
559 template<class T> | |
560 inline bool isnan_impl(T x, ieee_copy_leading_bits_tag const&) | |
561 { | |
562 typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits; | |
563 | |
564 BOOST_DEDUCED_TYPENAME traits::bits a; | |
565 traits::get_bits(x,a); | |
566 | |
567 a &= traits::exponent | traits::significand; | |
568 if(a < traits::exponent) | |
569 return false; | |
570 | |
571 a &= traits::significand; | |
572 traits::set_bits(x,a); | |
573 return x != 0; | |
574 } | |
575 | |
576 } // namespace detail | |
577 | |
578 template<class T> | |
579 inline bool (isnan)(T x) | |
580 { //!< \brief return true if floating-point type t is NaN (Not A Number). | |
581 typedef typename detail::fp_traits<T>::type traits; | |
582 typedef typename traits::method method; | |
583 // typedef typename boost::is_floating_point<T>::type fp_tag; | |
584 return detail::isnan_impl(x, method()); | |
585 } | |
586 | |
587 #ifdef isnan | |
588 template <> inline bool isnan BOOST_NO_MACRO_EXPAND<float>(float t){ return ::boost::math_detail::is_nan_helper(t, boost::true_type()); } | |
589 template <> inline bool isnan BOOST_NO_MACRO_EXPAND<double>(double t){ return ::boost::math_detail::is_nan_helper(t, boost::true_type()); } | |
590 template <> inline bool isnan BOOST_NO_MACRO_EXPAND<long double>(long double t){ return ::boost::math_detail::is_nan_helper(t, boost::true_type()); } | |
591 #elif defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS) | |
592 template<> | |
593 inline bool (isnan)(long double x) | |
594 { //!< \brief return true if floating-point type t is NaN (Not A Number). | |
595 typedef detail::fp_traits<long double>::type traits; | |
596 typedef traits::method method; | |
597 typedef boost::is_floating_point<long double>::type fp_tag; | |
598 return detail::isnan_impl(x, method()); | |
599 } | |
600 #endif | |
601 | |
602 } // namespace math | |
603 } // namespace boost | |
604 | |
605 #endif // BOOST_MATH_FPCLASSIFY_HPP | |
606 |