blob: 7b4b1933aae4b52bf1aeaf48df1ab1aa7643ed72 [file] [log] [blame]
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001// 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
Jeff Thompson3d613fd2013-10-15 15:39:04 -07007#ifndef NDNBOOST_MATH_FPCLASSIFY_HPP
8#define NDNBOOST_MATH_FPCLASSIFY_HPP
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07009
10#ifdef _MSC_VER
11#pragma once
12#endif
13
14#include <math.h>
15#include <ndnboost/config/no_tr1/cmath.hpp>
16#include <ndnboost/limits.hpp>
17#include <ndnboost/math/tools/real_cast.hpp>
18#include <ndnboost/type_traits/is_floating_point.hpp>
19#include <ndnboost/math/special_functions/math_fwd.hpp>
20#include <ndnboost/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
301. If the platform is C99 compliant, then the native floating point
31classification functions are used. However, note that we must only
32define the functions which call std::fpclassify etc if that function
33really does exist: otherwise a compiler may reject the code even though
34the template is never instantiated.
35
362. If the platform is not C99 compliant, and the binary format for
37a floating point type (float, double or long double) can be determined
38at 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
733. If the platform is not C99 compliant, and the binary format for
74a floating point type (float, double or long double) can not be determined
75at compile time, then comparison with std::numeric_limits values
76is used.
77
78*/
79
80#if defined(_MSC_VER) || defined(__BORLANDC__)
81#include <float.h>
82#endif
83
Jeff Thompson3d613fd2013-10-15 15:39:04 -070084#ifdef NDNBOOST_NO_STDC_NAMESPACE
Jeff Thompsonef2d5a42013-08-22 19:09:24 -070085 namespace std{ using ::abs; using ::fabs; }
86#endif
87
88namespace ndnboost{
89
90//
91// This must not be located in any namespace under ndnboost::math
92// otherwise we can get into an infinite loop if isnan is
93// a #define for "isnan" !
94//
95namespace math_detail{
96
Jeff Thompson3d613fd2013-10-15 15:39:04 -070097#ifdef NDNBOOST_MSVC
Jeff Thompsonef2d5a42013-08-22 19:09:24 -070098#pragma warning(push)
99#pragma warning(disable:4800)
100#endif
101
102template <class T>
103inline bool is_nan_helper(T t, const ndnboost::true_type&)
104{
105#ifdef isnan
106 return isnan(t);
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700107#elif defined(NDNBOOST_MATH_DISABLE_STD_FPCLASSIFY) || !defined(NDNBOOST_HAS_FPCLASSIFY)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700108 (void)t;
109 return false;
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700110#else // NDNBOOST_HAS_FPCLASSIFY
111 return (NDNBOOST_FPCLASSIFY_PREFIX fpclassify(t) == (int)FP_NAN);
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700112#endif
113}
114
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700115#ifdef NDNBOOST_MSVC
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700116#pragma warning(pop)
117#endif
118
119template <class T>
120inline bool is_nan_helper(T, const ndnboost::false_type&)
121{
122 return false;
123}
124
125}
126
127namespace math{
128
129namespace detail{
130
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700131#ifdef NDNBOOST_MATH_USE_STD_FPCLASSIFY
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700132template <class T>
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700133inline int fpclassify_imp NDNBOOST_NO_MACRO_EXPAND(T t, const native_tag&)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700134{
135 return (std::fpclassify)(t);
136}
137#endif
138
139template <class T>
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700140inline int fpclassify_imp NDNBOOST_NO_MACRO_EXPAND(T t, const generic_tag<true>&)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700141{
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700142 NDNBOOST_MATH_INSTRUMENT_VARIABLE(t);
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700143
144 // whenever possible check for Nan's first:
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700145#if defined(NDNBOOST_HAS_FPCLASSIFY) && !defined(NDNBOOST_MATH_DISABLE_STD_FPCLASSIFY)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700146 if(::ndnboost::math_detail::is_nan_helper(t, ::ndnboost::is_floating_point<T>()))
147 return FP_NAN;
148#elif defined(isnan)
149 if(ndnboost::math_detail::is_nan_helper(t, ::ndnboost::is_floating_point<T>()))
150 return FP_NAN;
151#elif defined(_MSC_VER) || defined(__BORLANDC__)
152 if(::_isnan(ndnboost::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
175template <class T>
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700176inline int fpclassify_imp NDNBOOST_NO_MACRO_EXPAND(T t, const generic_tag<false>&)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700177{
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700178#ifdef NDNBOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700179 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 //
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700186 NDNBOOST_MATH_INSTRUMENT_VARIABLE(t);
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700187
188 return t == 0 ? FP_ZERO : FP_NORMAL;
189}
190
191template<class T>
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700192int fpclassify_imp NDNBOOST_NO_MACRO_EXPAND(T x, ieee_copy_all_bits_tag)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700193{
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700194 typedef NDNBOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700195
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700196 NDNBOOST_MATH_INSTRUMENT_VARIABLE(x);
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700197
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700198 NDNBOOST_DEDUCED_TYPENAME traits::bits a;
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700199 traits::get_bits(x,a);
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700200 NDNBOOST_MATH_INSTRUMENT_VARIABLE(a);
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700201 a &= traits::exponent | traits::flag | traits::significand;
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700202 NDNBOOST_MATH_INSTRUMENT_VARIABLE((traits::exponent | traits::flag | traits::significand));
203 NDNBOOST_MATH_INSTRUMENT_VARIABLE(a);
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700204
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
220template<class T>
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700221int fpclassify_imp NDNBOOST_NO_MACRO_EXPAND(T x, ieee_copy_leading_bits_tag)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700222{
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700223 typedef NDNBOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700224
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700225 NDNBOOST_MATH_INSTRUMENT_VARIABLE(x);
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700226
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700227 NDNBOOST_DEDUCED_TYPENAME traits::bits a;
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700228 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
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700247#if defined(NDNBOOST_MATH_USE_STD_FPCLASSIFY) && (defined(NDNBOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY) || defined(NDNBOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS))
248inline int fpclassify_imp NDNBOOST_NO_MACRO_EXPAND(long double t, const native_tag&)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700249{
250 return ndnboost::math::detail::fpclassify_imp(t, generic_tag<true>());
251}
252#endif
253
254} // namespace detail
255
256template <class T>
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700257inline int fpclassify NDNBOOST_NO_MACRO_EXPAND(T t)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700258{
259 typedef typename detail::fp_traits<T>::type traits;
260 typedef typename traits::method method;
261 typedef typename tools::promote_args<T>::type value_type;
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700262#ifdef NDNBOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700263 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
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700271#ifdef NDNBOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700272template <>
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700273inline int fpclassify<long double> NDNBOOST_NO_MACRO_EXPAND(long double t)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700274{
275 typedef detail::fp_traits<long double>::type traits;
276 typedef traits::method method;
277 typedef long double value_type;
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700278#ifdef NDNBOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700279 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
288namespace detail {
289
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700290#ifdef NDNBOOST_MATH_USE_STD_FPCLASSIFY
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700291 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 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700308#ifdef NDNBOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700309 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 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700319 typedef NDNBOOST_DEDUCED_TYPENAME detail::fp_traits<T>::type traits;
320 NDNBOOST_DEDUCED_TYPENAME traits::bits a;
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700321 traits::get_bits(x,a);
322 a &= traits::exponent;
323 return a != traits::exponent;
324 }
325
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700326#if defined(NDNBOOST_MATH_USE_STD_FPCLASSIFY) && defined(NDNBOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY)
327inline bool isfinite_impl NDNBOOST_NO_MACRO_EXPAND(long double t, const native_tag&)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700328{
329 return ndnboost::math::detail::isfinite_impl(t, generic_tag<true>());
330}
331#endif
332
333}
334
335template<class T>
336inline 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 ndnboost::is_floating_point<T>::type fp_tag;
341 typedef typename tools::promote_args<T>::type value_type;
342 return detail::isfinite_impl(static_cast<value_type>(x), method());
343}
344
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700345#ifdef NDNBOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700346template<>
347inline 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 ndnboost::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
359namespace detail {
360
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700361#ifdef NDNBOOST_MATH_USE_STD_FPCLASSIFY
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700362 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 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700380#ifdef NDNBOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700381 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 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700390 typedef NDNBOOST_DEDUCED_TYPENAME detail::fp_traits<T>::type traits;
391 NDNBOOST_DEDUCED_TYPENAME traits::bits a;
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700392 traits::get_bits(x,a);
393 a &= traits::exponent | traits::flag;
394 return (a != 0) && (a < traits::exponent);
395 }
396
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700397#if defined(NDNBOOST_MATH_USE_STD_FPCLASSIFY) && defined(NDNBOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY)
398inline bool isnormal_impl NDNBOOST_NO_MACRO_EXPAND(long double t, const native_tag&)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700399{
400 return ndnboost::math::detail::isnormal_impl(t, generic_tag<true>());
401}
402#endif
403
404}
405
406template<class T>
407inline bool (isnormal)(T x)
408{
409 typedef typename detail::fp_traits<T>::type traits;
410 typedef typename traits::method method;
411 //typedef typename ndnboost::is_floating_point<T>::type fp_tag;
412 typedef typename tools::promote_args<T>::type value_type;
413 return detail::isnormal_impl(static_cast<value_type>(x), method());
414}
415
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700416#ifdef NDNBOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700417template<>
418inline bool (isnormal)(long double x)
419{
420 typedef detail::fp_traits<long double>::type traits;
421 typedef traits::method method;
422 typedef ndnboost::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
430namespace detail {
431
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700432#ifdef NDNBOOST_MATH_USE_STD_FPCLASSIFY
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700433 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 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700452#ifdef NDNBOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700453 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 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700463 typedef NDNBOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700464
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700465 NDNBOOST_DEDUCED_TYPENAME traits::bits a;
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700466 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 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700474 typedef NDNBOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700475
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700476 NDNBOOST_DEDUCED_TYPENAME traits::bits a;
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700477 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
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700486#if defined(NDNBOOST_MATH_USE_STD_FPCLASSIFY) && defined(NDNBOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY)
487inline bool isinf_impl NDNBOOST_NO_MACRO_EXPAND(long double t, const native_tag&)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700488{
489 return ndnboost::math::detail::isinf_impl(t, generic_tag<true>());
490}
491#endif
492
493} // namespace detail
494
495template<class T>
496inline bool (isinf)(T x)
497{
498 typedef typename detail::fp_traits<T>::type traits;
499 typedef typename traits::method method;
500 // typedef typename ndnboost::is_floating_point<T>::type fp_tag;
501 typedef typename tools::promote_args<T>::type value_type;
502 return detail::isinf_impl(static_cast<value_type>(x), method());
503}
504
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700505#ifdef NDNBOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700506template<>
507inline bool (isinf)(long double x)
508{
509 typedef detail::fp_traits<long double>::type traits;
510 typedef traits::method method;
511 typedef ndnboost::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
519namespace detail {
520
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700521#ifdef NDNBOOST_MATH_USE_STD_FPCLASSIFY
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700522 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 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700540#ifdef NDNBOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700541 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 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700551 typedef NDNBOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700552
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700553 NDNBOOST_DEDUCED_TYPENAME traits::bits a;
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700554 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 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700562 typedef NDNBOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700563
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700564 NDNBOOST_DEDUCED_TYPENAME traits::bits a;
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700565 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
578template<class T>
579inline 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 ndnboost::is_floating_point<T>::type fp_tag;
584 return detail::isnan_impl(x, method());
585}
586
587#ifdef isnan
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700588template <> inline bool isnan NDNBOOST_NO_MACRO_EXPAND<float>(float t){ return ::ndnboost::math_detail::is_nan_helper(t, ndnboost::true_type()); }
589template <> inline bool isnan NDNBOOST_NO_MACRO_EXPAND<double>(double t){ return ::ndnboost::math_detail::is_nan_helper(t, ndnboost::true_type()); }
590template <> inline bool isnan NDNBOOST_NO_MACRO_EXPAND<long double>(long double t){ return ::ndnboost::math_detail::is_nan_helper(t, ndnboost::true_type()); }
591#elif defined(NDNBOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700592template<>
593inline 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 ndnboost::is_floating_point<long double>::type fp_tag;
598 return detail::isnan_impl(x, method());
599}
600#endif
601
602} // namespace math
603} // namespace ndnboost
604
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700605#endif // NDNBOOST_MATH_FPCLASSIFY_HPP
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700606