Line data Source code
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 : #ifdef BOOST_MATH_USE_FLOAT128
84 : #ifdef __has_include
85 : #if __has_include("quadmath.h")
86 : #include "quadmath.h"
87 : #define BOOST_MATH_HAS_QUADMATH_H
88 : #endif
89 : #endif
90 : #endif
91 :
92 : #ifdef BOOST_NO_STDC_NAMESPACE
93 : namespace std{ using ::abs; using ::fabs; }
94 : #endif
95 :
96 : namespace boost{
97 :
98 : //
99 : // This must not be located in any namespace under boost::math
100 : // otherwise we can get into an infinite loop if isnan is
101 : // a #define for "isnan" !
102 : //
103 : namespace math_detail{
104 :
105 : #ifdef BOOST_MSVC
106 : #pragma warning(push)
107 : #pragma warning(disable:4800)
108 : #endif
109 :
110 : template <class T>
111 : inline bool is_nan_helper(T t, const boost::true_type&)
112 : {
113 : #ifdef isnan
114 : return isnan(t);
115 : #elif defined(BOOST_MATH_DISABLE_STD_FPCLASSIFY) || !defined(BOOST_HAS_FPCLASSIFY)
116 : (void)t;
117 : return false;
118 : #else // BOOST_HAS_FPCLASSIFY
119 : return (BOOST_FPCLASSIFY_PREFIX fpclassify(t) == (int)FP_NAN);
120 : #endif
121 : }
122 :
123 : #ifdef BOOST_MSVC
124 : #pragma warning(pop)
125 : #endif
126 :
127 : template <class T>
128 : inline bool is_nan_helper(T, const boost::false_type&)
129 : {
130 : return false;
131 : }
132 : #if defined(BOOST_MATH_USE_FLOAT128)
133 : #if defined(BOOST_MATH_HAS_QUADMATH_H)
134 : inline bool is_nan_helper(__float128 f, const boost::true_type&) { return ::isnanq(f); }
135 : inline bool is_nan_helper(__float128 f, const boost::false_type&) { return ::isnanq(f); }
136 : #elif defined(BOOST_GNU_STDLIB) && BOOST_GNU_STDLIB && \
137 : _GLIBCXX_USE_C99_MATH && !_GLIBCXX_USE_C99_FP_MACROS_DYNAMIC
138 : inline bool is_nan_helper(__float128 f, const boost::true_type&) { return std::isnan(static_cast<double>(f)); }
139 : inline bool is_nan_helper(__float128 f, const boost::false_type&) { return std::isnan(static_cast<double>(f)); }
140 : #else
141 : inline bool is_nan_helper(__float128 f, const boost::true_type&) { return ::isnan(static_cast<double>(f)); }
142 : inline bool is_nan_helper(__float128 f, const boost::false_type&) { return ::isnan(static_cast<double>(f)); }
143 : #endif
144 : #endif
145 : }
146 :
147 : namespace math{
148 :
149 : namespace detail{
150 :
151 : #ifdef BOOST_MATH_USE_STD_FPCLASSIFY
152 : template <class T>
153 : inline int fpclassify_imp BOOST_NO_MACRO_EXPAND(T t, const native_tag&)
154 : {
155 : return (std::fpclassify)(t);
156 : }
157 : #endif
158 :
159 : template <class T>
160 : inline int fpclassify_imp BOOST_NO_MACRO_EXPAND(T t, const generic_tag<true>&)
161 : {
162 : BOOST_MATH_INSTRUMENT_VARIABLE(t);
163 :
164 : // whenever possible check for Nan's first:
165 : #if defined(BOOST_HAS_FPCLASSIFY) && !defined(BOOST_MATH_DISABLE_STD_FPCLASSIFY)
166 : if(::boost::math_detail::is_nan_helper(t, ::boost::is_floating_point<T>()))
167 : return FP_NAN;
168 : #elif defined(isnan)
169 : if(boost::math_detail::is_nan_helper(t, ::boost::is_floating_point<T>()))
170 : return FP_NAN;
171 : #elif defined(_MSC_VER) || defined(__BORLANDC__)
172 : if(::_isnan(boost::math::tools::real_cast<double>(t)))
173 : return FP_NAN;
174 : #endif
175 : // std::fabs broken on a few systems especially for long long!!!!
176 : T at = (t < T(0)) ? -t : t;
177 :
178 : // Use a process of exclusion to figure out
179 : // what kind of type we have, this relies on
180 : // IEEE conforming reals that will treat
181 : // Nan's as unordered. Some compilers
182 : // don't do this once optimisations are
183 : // turned on, hence the check for nan's above.
184 : if(at <= (std::numeric_limits<T>::max)())
185 : {
186 : if(at >= (std::numeric_limits<T>::min)())
187 : return FP_NORMAL;
188 : return (at != 0) ? FP_SUBNORMAL : FP_ZERO;
189 : }
190 : else if(at > (std::numeric_limits<T>::max)())
191 : return FP_INFINITE;
192 : return FP_NAN;
193 : }
194 :
195 : template <class T>
196 : inline int fpclassify_imp BOOST_NO_MACRO_EXPAND(T t, const generic_tag<false>&)
197 : {
198 : #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
199 : if(std::numeric_limits<T>::is_specialized)
200 : return fpclassify_imp(t, generic_tag<true>());
201 : #endif
202 : //
203 : // An unknown type with no numeric_limits support,
204 : // so what are we supposed to do we do here?
205 : //
206 : BOOST_MATH_INSTRUMENT_VARIABLE(t);
207 :
208 : return t == 0 ? FP_ZERO : FP_NORMAL;
209 : }
210 :
211 : template<class T>
212 : int fpclassify_imp BOOST_NO_MACRO_EXPAND(T x, ieee_copy_all_bits_tag)
213 : {
214 : typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
215 :
216 : BOOST_MATH_INSTRUMENT_VARIABLE(x);
217 :
218 : BOOST_DEDUCED_TYPENAME traits::bits a;
219 : traits::get_bits(x,a);
220 : BOOST_MATH_INSTRUMENT_VARIABLE(a);
221 : a &= traits::exponent | traits::flag | traits::significand;
222 : BOOST_MATH_INSTRUMENT_VARIABLE((traits::exponent | traits::flag | traits::significand));
223 : BOOST_MATH_INSTRUMENT_VARIABLE(a);
224 :
225 : if(a <= traits::significand) {
226 : if(a == 0)
227 : return FP_ZERO;
228 : else
229 : return FP_SUBNORMAL;
230 : }
231 :
232 : if(a < traits::exponent) return FP_NORMAL;
233 :
234 : a &= traits::significand;
235 : if(a == 0) return FP_INFINITE;
236 :
237 : return FP_NAN;
238 : }
239 :
240 : template<class T>
241 : int fpclassify_imp BOOST_NO_MACRO_EXPAND(T x, ieee_copy_leading_bits_tag)
242 : {
243 : typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
244 :
245 : BOOST_MATH_INSTRUMENT_VARIABLE(x);
246 :
247 : BOOST_DEDUCED_TYPENAME traits::bits a;
248 : traits::get_bits(x,a);
249 : a &= traits::exponent | traits::flag | traits::significand;
250 :
251 : if(a <= traits::significand) {
252 : if(x == 0)
253 : return FP_ZERO;
254 : else
255 : return FP_SUBNORMAL;
256 : }
257 :
258 : if(a < traits::exponent) return FP_NORMAL;
259 :
260 : a &= traits::significand;
261 : traits::set_bits(x,a);
262 : if(x == 0) return FP_INFINITE;
263 :
264 : return FP_NAN;
265 : }
266 :
267 : #if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && (defined(BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY) || defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS))
268 : inline int fpclassify_imp BOOST_NO_MACRO_EXPAND(long double t, const native_tag&)
269 : {
270 : return boost::math::detail::fpclassify_imp(t, generic_tag<true>());
271 : }
272 : #endif
273 :
274 : } // namespace detail
275 :
276 : template <class T>
277 : inline int fpclassify BOOST_NO_MACRO_EXPAND(T t)
278 : {
279 : typedef typename detail::fp_traits<T>::type traits;
280 : typedef typename traits::method method;
281 : typedef typename tools::promote_args_permissive<T>::type value_type;
282 : #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
283 : if(std::numeric_limits<T>::is_specialized && detail::is_generic_tag_false(static_cast<method*>(0)))
284 : return detail::fpclassify_imp(static_cast<value_type>(t), detail::generic_tag<true>());
285 : return detail::fpclassify_imp(static_cast<value_type>(t), method());
286 : #else
287 : return detail::fpclassify_imp(static_cast<value_type>(t), method());
288 : #endif
289 : }
290 :
291 : #ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
292 : template <>
293 : inline int fpclassify<long double> BOOST_NO_MACRO_EXPAND(long double t)
294 : {
295 : typedef detail::fp_traits<long double>::type traits;
296 : typedef traits::method method;
297 : typedef long double value_type;
298 : #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
299 : if(std::numeric_limits<long double>::is_specialized && detail::is_generic_tag_false(static_cast<method*>(0)))
300 : return detail::fpclassify_imp(static_cast<value_type>(t), detail::generic_tag<true>());
301 : return detail::fpclassify_imp(static_cast<value_type>(t), method());
302 : #else
303 : return detail::fpclassify_imp(static_cast<value_type>(t), method());
304 : #endif
305 : }
306 : #endif
307 :
308 : namespace detail {
309 :
310 : #ifdef BOOST_MATH_USE_STD_FPCLASSIFY
311 : template<class T>
312 : inline bool isfinite_impl(T x, native_tag const&)
313 : {
314 : return (std::isfinite)(x);
315 : }
316 : #endif
317 :
318 : template<class T>
319 : inline bool isfinite_impl(T x, generic_tag<true> const&)
320 : {
321 : return x >= -(std::numeric_limits<T>::max)()
322 : && x <= (std::numeric_limits<T>::max)();
323 : }
324 :
325 : template<class T>
326 : inline bool isfinite_impl(T x, generic_tag<false> const&)
327 : {
328 : #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
329 : if(std::numeric_limits<T>::is_specialized)
330 : return isfinite_impl(x, generic_tag<true>());
331 : #endif
332 : (void)x; // warning suppression.
333 : return true;
334 : }
335 :
336 : template<class T>
337 : inline bool isfinite_impl(T x, ieee_tag const&)
338 : {
339 : typedef BOOST_DEDUCED_TYPENAME detail::fp_traits<T>::type traits;
340 : BOOST_DEDUCED_TYPENAME traits::bits a;
341 : traits::get_bits(x,a);
342 : a &= traits::exponent;
343 : return a != traits::exponent;
344 : }
345 :
346 : #if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && defined(BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY)
347 : inline bool isfinite_impl BOOST_NO_MACRO_EXPAND(long double t, const native_tag&)
348 : {
349 : return boost::math::detail::isfinite_impl(t, generic_tag<true>());
350 : }
351 : #endif
352 :
353 : }
354 :
355 : template<class T>
356 : inline bool (isfinite)(T x)
357 : { //!< \brief return true if floating-point type t is finite.
358 : typedef typename detail::fp_traits<T>::type traits;
359 : typedef typename traits::method method;
360 : // typedef typename boost::is_floating_point<T>::type fp_tag;
361 : typedef typename tools::promote_args_permissive<T>::type value_type;
362 : return detail::isfinite_impl(static_cast<value_type>(x), method());
363 : }
364 :
365 : #ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
366 : template<>
367 : inline bool (isfinite)(long double x)
368 : { //!< \brief return true if floating-point type t is finite.
369 : typedef detail::fp_traits<long double>::type traits;
370 : typedef traits::method method;
371 : //typedef boost::is_floating_point<long double>::type fp_tag;
372 : typedef long double value_type;
373 : return detail::isfinite_impl(static_cast<value_type>(x), method());
374 : }
375 : #endif
376 :
377 : //------------------------------------------------------------------------------
378 :
379 : namespace detail {
380 :
381 : #ifdef BOOST_MATH_USE_STD_FPCLASSIFY
382 : template<class T>
383 : inline bool isnormal_impl(T x, native_tag const&)
384 : {
385 : return (std::isnormal)(x);
386 : }
387 : #endif
388 :
389 : template<class T>
390 : inline bool isnormal_impl(T x, generic_tag<true> const&)
391 : {
392 : if(x < 0) x = -x;
393 : return x >= (std::numeric_limits<T>::min)()
394 : && x <= (std::numeric_limits<T>::max)();
395 : }
396 :
397 : template<class T>
398 : inline bool isnormal_impl(T x, generic_tag<false> const&)
399 : {
400 : #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
401 : if(std::numeric_limits<T>::is_specialized)
402 : return isnormal_impl(x, generic_tag<true>());
403 : #endif
404 : return !(x == 0);
405 : }
406 :
407 : template<class T>
408 : inline bool isnormal_impl(T x, ieee_tag const&)
409 : {
410 : typedef BOOST_DEDUCED_TYPENAME detail::fp_traits<T>::type traits;
411 : BOOST_DEDUCED_TYPENAME traits::bits a;
412 : traits::get_bits(x,a);
413 : a &= traits::exponent | traits::flag;
414 : return (a != 0) && (a < traits::exponent);
415 : }
416 :
417 : #if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && defined(BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY)
418 : inline bool isnormal_impl BOOST_NO_MACRO_EXPAND(long double t, const native_tag&)
419 : {
420 : return boost::math::detail::isnormal_impl(t, generic_tag<true>());
421 : }
422 : #endif
423 :
424 : }
425 :
426 : template<class T>
427 : inline bool (isnormal)(T x)
428 : {
429 : typedef typename detail::fp_traits<T>::type traits;
430 : typedef typename traits::method method;
431 : //typedef typename boost::is_floating_point<T>::type fp_tag;
432 : typedef typename tools::promote_args_permissive<T>::type value_type;
433 : return detail::isnormal_impl(static_cast<value_type>(x), method());
434 : }
435 :
436 : #ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
437 : template<>
438 : inline bool (isnormal)(long double x)
439 : {
440 : typedef detail::fp_traits<long double>::type traits;
441 : typedef traits::method method;
442 : //typedef boost::is_floating_point<long double>::type fp_tag;
443 : typedef long double value_type;
444 : return detail::isnormal_impl(static_cast<value_type>(x), method());
445 : }
446 : #endif
447 :
448 : //------------------------------------------------------------------------------
449 :
450 : namespace detail {
451 :
452 : #ifdef BOOST_MATH_USE_STD_FPCLASSIFY
453 : template<class T>
454 0 : inline bool isinf_impl(T x, native_tag const&)
455 : {
456 0 : return (std::isinf)(x);
457 : }
458 : #endif
459 :
460 : template<class T>
461 : inline bool isinf_impl(T x, generic_tag<true> const&)
462 : {
463 : (void)x; // in case the compiler thinks that x is unused because std::numeric_limits<T>::has_infinity is false
464 : return std::numeric_limits<T>::has_infinity
465 : && ( x == std::numeric_limits<T>::infinity()
466 : || x == -std::numeric_limits<T>::infinity());
467 : }
468 :
469 : template<class T>
470 : inline bool isinf_impl(T x, generic_tag<false> const&)
471 : {
472 : #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
473 : if(std::numeric_limits<T>::is_specialized)
474 : return isinf_impl(x, generic_tag<true>());
475 : #endif
476 : (void)x; // warning suppression.
477 : return false;
478 : }
479 :
480 : template<class T>
481 : inline bool isinf_impl(T x, ieee_copy_all_bits_tag const&)
482 : {
483 : typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
484 :
485 : BOOST_DEDUCED_TYPENAME traits::bits a;
486 : traits::get_bits(x,a);
487 : a &= traits::exponent | traits::significand;
488 : return a == traits::exponent;
489 : }
490 :
491 : template<class T>
492 : inline bool isinf_impl(T x, ieee_copy_leading_bits_tag const&)
493 : {
494 : typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
495 :
496 : BOOST_DEDUCED_TYPENAME traits::bits a;
497 : traits::get_bits(x,a);
498 : a &= traits::exponent | traits::significand;
499 : if(a != traits::exponent)
500 : return false;
501 :
502 : traits::set_bits(x,0);
503 : return x == 0;
504 : }
505 :
506 : #if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && defined(BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY)
507 : inline bool isinf_impl BOOST_NO_MACRO_EXPAND(long double t, const native_tag&)
508 : {
509 : return boost::math::detail::isinf_impl(t, generic_tag<true>());
510 : }
511 : #endif
512 :
513 : } // namespace detail
514 :
515 : template<class T>
516 0 : inline bool (isinf)(T x)
517 : {
518 : typedef typename detail::fp_traits<T>::type traits;
519 : typedef typename traits::method method;
520 : // typedef typename boost::is_floating_point<T>::type fp_tag;
521 : typedef typename tools::promote_args_permissive<T>::type value_type;
522 0 : return detail::isinf_impl(static_cast<value_type>(x), method());
523 : }
524 :
525 : #ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
526 : template<>
527 : inline bool (isinf)(long double x)
528 : {
529 : typedef detail::fp_traits<long double>::type traits;
530 : typedef traits::method method;
531 : //typedef boost::is_floating_point<long double>::type fp_tag;
532 : typedef long double value_type;
533 : return detail::isinf_impl(static_cast<value_type>(x), method());
534 : }
535 : #endif
536 : #if defined(BOOST_MATH_USE_FLOAT128) && defined(BOOST_MATH_HAS_QUADMATH_H)
537 : template<>
538 : inline bool (isinf)(__float128 x)
539 : {
540 : return ::isinfq(x);
541 : }
542 : #endif
543 :
544 : //------------------------------------------------------------------------------
545 :
546 : namespace detail {
547 :
548 : #ifdef BOOST_MATH_USE_STD_FPCLASSIFY
549 : template<class T>
550 0 : inline bool isnan_impl(T x, native_tag const&)
551 : {
552 0 : return (std::isnan)(x);
553 : }
554 : #endif
555 :
556 : template<class T>
557 : inline bool isnan_impl(T x, generic_tag<true> const&)
558 : {
559 : return std::numeric_limits<T>::has_infinity
560 : ? !(x <= std::numeric_limits<T>::infinity())
561 : : x != x;
562 : }
563 :
564 : template<class T>
565 : inline bool isnan_impl(T x, generic_tag<false> const&)
566 : {
567 : #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
568 : if(std::numeric_limits<T>::is_specialized)
569 : return isnan_impl(x, generic_tag<true>());
570 : #endif
571 : (void)x; // warning suppression
572 : return false;
573 : }
574 :
575 : template<class T>
576 : inline bool isnan_impl(T x, ieee_copy_all_bits_tag const&)
577 : {
578 : typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
579 :
580 : BOOST_DEDUCED_TYPENAME traits::bits a;
581 : traits::get_bits(x,a);
582 : a &= traits::exponent | traits::significand;
583 : return a > traits::exponent;
584 : }
585 :
586 : template<class T>
587 : inline bool isnan_impl(T x, ieee_copy_leading_bits_tag const&)
588 : {
589 : typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
590 :
591 : BOOST_DEDUCED_TYPENAME traits::bits a;
592 : traits::get_bits(x,a);
593 :
594 : a &= traits::exponent | traits::significand;
595 : if(a < traits::exponent)
596 : return false;
597 :
598 : a &= traits::significand;
599 : traits::set_bits(x,a);
600 : return x != 0;
601 : }
602 :
603 : } // namespace detail
604 :
605 : template<class T>
606 0 : inline bool (isnan)(T x)
607 : { //!< \brief return true if floating-point type t is NaN (Not A Number).
608 : typedef typename detail::fp_traits<T>::type traits;
609 : typedef typename traits::method method;
610 : // typedef typename boost::is_floating_point<T>::type fp_tag;
611 0 : return detail::isnan_impl(x, method());
612 : }
613 :
614 : #ifdef isnan
615 : template <> inline bool isnan BOOST_NO_MACRO_EXPAND<float>(float t){ return ::boost::math_detail::is_nan_helper(t, boost::true_type()); }
616 : template <> inline bool isnan BOOST_NO_MACRO_EXPAND<double>(double t){ return ::boost::math_detail::is_nan_helper(t, boost::true_type()); }
617 : template <> inline bool isnan BOOST_NO_MACRO_EXPAND<long double>(long double t){ return ::boost::math_detail::is_nan_helper(t, boost::true_type()); }
618 : #elif defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS)
619 : template<>
620 : inline bool (isnan)(long double x)
621 : { //!< \brief return true if floating-point type t is NaN (Not A Number).
622 : typedef detail::fp_traits<long double>::type traits;
623 : typedef traits::method method;
624 : //typedef boost::is_floating_point<long double>::type fp_tag;
625 : return detail::isnan_impl(x, method());
626 : }
627 : #endif
628 : #if defined(BOOST_MATH_USE_FLOAT128) && defined(BOOST_MATH_HAS_QUADMATH_H)
629 : template<>
630 : inline bool (isnan)(__float128 x)
631 : {
632 : return ::isnanq(x);
633 : }
634 : #endif
635 :
636 : } // namespace math
637 : } // namespace boost
638 :
639 : #endif // BOOST_MATH_FPCLASSIFY_HPP
640 :
|