~tsarev/boostdc/cmake

« back to all changes in this revision

Viewing changes to boost/boost/math/special_functions/fpclassify.hpp

  • Committer: bigmuscle
  • Date: 2010-05-08 08:47:15 UTC
  • Revision ID: svn-v4:5fb55d53-692c-0410-a46a-e90ab66e00ee:trunk:497
removed old boost version

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
#if defined(BOOST_HAS_FPCLASSIFY) || defined(isnan)
91
 
//
92
 
// This must not be located in any namespace under boost::math
93
 
// otherwise we can get into an infinite loop if isnan is
94
 
// a #define for "isnan" !
95
 
//
96
 
namespace math_detail{
97
 
 
98
 
template <class T>
99
 
inline bool is_nan_helper(T t, const boost::true_type&)
100
 
{
101
 
#ifdef isnan
102
 
   return isnan(t);
103
 
#else // BOOST_HAS_FPCLASSIFY
104
 
   return (BOOST_FPCLASSIFY_PREFIX fpclassify(t) == (int)FP_NAN);
105
 
#endif
106
 
}
107
 
 
108
 
template <class T>
109
 
inline bool is_nan_helper(T t, const boost::false_type&)
110
 
{
111
 
   return false;
112
 
}
113
 
 
114
 
}
115
 
 
116
 
#endif // defined(BOOST_HAS_FPCLASSIFY) || defined(isnan)
117
 
 
118
 
namespace math{
119
 
 
120
 
namespace detail{
121
 
 
122
 
#ifdef BOOST_MATH_USE_STD_FPCLASSIFY
123
 
template <class T>
124
 
inline int fpclassify_imp BOOST_NO_MACRO_EXPAND(T t, const native_tag&)
125
 
{
126
 
   return (std::fpclassify)(t);
127
 
}
128
 
#endif
129
 
 
130
 
template <class T>
131
 
inline int fpclassify_imp BOOST_NO_MACRO_EXPAND(T t, const generic_tag<true>&)
132
 
{
133
 
   BOOST_MATH_INSTRUMENT_VARIABLE(t);
134
 
 
135
 
   // whenever possible check for Nan's first:
136
 
#ifdef BOOST_HAS_FPCLASSIFY
137
 
   if(::boost::math_detail::is_nan_helper(t, ::boost::is_floating_point<T>()))
138
 
      return FP_NAN;
139
 
#elif defined(isnan)
140
 
   if(boost::math_detail::is_nan_helper(t, ::boost::is_floating_point<T>()))
141
 
      return FP_NAN;
142
 
#elif defined(_MSC_VER) || defined(__BORLANDC__)
143
 
   if(::_isnan(boost::math::tools::real_cast<double>(t)))
144
 
      return FP_NAN;
145
 
#endif
146
 
   // std::fabs broken on a few systems especially for long long!!!!
147
 
   T at = (t < T(0)) ? -t : t;
148
 
 
149
 
   // Use a process of exclusion to figure out
150
 
   // what kind of type we have, this relies on
151
 
   // IEEE conforming reals that will treat
152
 
   // Nan's as unordered.  Some compilers
153
 
   // don't do this once optimisations are
154
 
   // turned on, hence the check for nan's above.
155
 
   if(at <= (std::numeric_limits<T>::max)())
156
 
   {
157
 
      if(at >= (std::numeric_limits<T>::min)())
158
 
         return FP_NORMAL;
159
 
      return (at != 0) ? FP_SUBNORMAL : FP_ZERO;
160
 
   }
161
 
   else if(at > (std::numeric_limits<T>::max)())
162
 
      return FP_INFINITE;
163
 
   return FP_NAN;
164
 
}
165
 
 
166
 
template <class T>
167
 
inline int fpclassify_imp BOOST_NO_MACRO_EXPAND(T t, const generic_tag<false>&)
168
 
{
169
 
#ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
170
 
   if(std::numeric_limits<T>::is_specialized)
171
 
      return fp_classify_imp(t, mpl::true_());
172
 
#endif
173
 
   // 
174
 
   // An unknown type with no numeric_limits support,
175
 
   // so what are we supposed to do we do here?
176
 
   //
177
 
   BOOST_MATH_INSTRUMENT_VARIABLE(t);
178
 
 
179
 
   return t == 0 ? FP_ZERO : FP_NORMAL;
180
 
}
181
 
 
182
 
template<class T> 
183
 
int fpclassify_imp BOOST_NO_MACRO_EXPAND(T x, ieee_copy_all_bits_tag)
184
 
{
185
 
   typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
186
 
 
187
 
   BOOST_MATH_INSTRUMENT_VARIABLE(x);
188
 
 
189
 
   BOOST_DEDUCED_TYPENAME traits::bits a;
190
 
   traits::get_bits(x,a);
191
 
   BOOST_MATH_INSTRUMENT_VARIABLE(a);
192
 
   a &= traits::exponent | traits::flag | traits::significand;
193
 
   BOOST_MATH_INSTRUMENT_VARIABLE((traits::exponent | traits::flag | traits::significand));
194
 
   BOOST_MATH_INSTRUMENT_VARIABLE(a);
195
 
 
196
 
   if(a <= traits::significand) {
197
 
      if(a == 0)
198
 
         return FP_ZERO;
199
 
      else
200
 
         return FP_SUBNORMAL;
201
 
   }
202
 
 
203
 
   if(a < traits::exponent) return FP_NORMAL;
204
 
 
205
 
   a &= traits::significand;
206
 
   if(a == 0) return FP_INFINITE;
207
 
 
208
 
   return FP_NAN;
209
 
}
210
 
 
211
 
template<class T> 
212
 
int fpclassify_imp BOOST_NO_MACRO_EXPAND(T x, ieee_copy_leading_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
 
   a &= traits::exponent | traits::flag | traits::significand;
221
 
 
222
 
   if(a <= traits::significand) {
223
 
      if(x == 0)
224
 
         return FP_ZERO;
225
 
      else
226
 
         return FP_SUBNORMAL;
227
 
   }
228
 
 
229
 
   if(a < traits::exponent) return FP_NORMAL;
230
 
 
231
 
   a &= traits::significand;
232
 
   traits::set_bits(x,a);
233
 
   if(x == 0) return FP_INFINITE;
234
 
 
235
 
   return FP_NAN;
236
 
}
237
 
 
238
 
#if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && defined(BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY)
239
 
template <>
240
 
inline int fpclassify_imp<long double> BOOST_NO_MACRO_EXPAND(long double t, const native_tag&)
241
 
{
242
 
   return boost::math::detail::fpclassify_imp(t, generic_tag<true>());
243
 
}
244
 
#endif
245
 
 
246
 
}  // namespace detail
247
 
 
248
 
template <class T>
249
 
inline int fpclassify BOOST_NO_MACRO_EXPAND(T t)
250
 
{
251
 
   typedef typename detail::fp_traits<T>::type traits;
252
 
   typedef typename traits::method method;
253
 
#ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
254
 
   if(std::numeric_limits<T>::is_specialized && detail::is_generic_tag_false(method()))
255
 
      return detail::fpclassify_imp(t, detail::generic_tag<true>());
256
 
   return detail::fpclassify_imp(t, method());
257
 
#else
258
 
   return detail::fpclassify_imp(t, method());
259
 
#endif
260
 
}
261
 
 
262
 
namespace detail {
263
 
 
264
 
#ifdef BOOST_MATH_USE_STD_FPCLASSIFY
265
 
    template<class T> 
266
 
    inline bool isfinite_impl(T x, native_tag const&)
267
 
    {
268
 
        return (std::isfinite)(x);
269
 
    }
270
 
#endif
271
 
 
272
 
    template<class T> 
273
 
    inline bool isfinite_impl(T x, generic_tag<true> const&)
274
 
    {
275
 
        return x >= -(std::numeric_limits<T>::max)()
276
 
            && x <= (std::numeric_limits<T>::max)();
277
 
    }
278
 
 
279
 
    template<class T> 
280
 
    inline bool isfinite_impl(T x, generic_tag<false> const&)
281
 
    {
282
 
#ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
283
 
      if(std::numeric_limits<T>::is_specialized)
284
 
         return isfinite_impl(x, mpl::true_());
285
 
#endif
286
 
       (void)x; // warning supression.
287
 
       return true;
288
 
    }
289
 
 
290
 
    template<class T> 
291
 
    inline bool isfinite_impl(T x, ieee_tag const&)
292
 
    {
293
 
        typedef BOOST_DEDUCED_TYPENAME detail::fp_traits<T>::type traits;
294
 
        BOOST_DEDUCED_TYPENAME traits::bits a;
295
 
        traits::get_bits(x,a);
296
 
        a &= traits::exponent;
297
 
        return a != traits::exponent;
298
 
    }
299
 
 
300
 
#if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && defined(BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY)
301
 
template <>
302
 
inline bool isfinite_impl<long double> BOOST_NO_MACRO_EXPAND(long double t, const native_tag&)
303
 
{
304
 
   return boost::math::detail::isfinite_impl(t, generic_tag<true>());
305
 
}
306
 
#endif
307
 
 
308
 
}
309
 
 
310
 
template<class T> 
311
 
inline bool (isfinite)(T x)
312
 
{ //!< \brief return true if floating-point type t is finite.
313
 
   typedef typename detail::fp_traits<T>::type traits;
314
 
   typedef typename traits::method method;
315
 
   typedef typename boost::is_floating_point<T>::type fp_tag;
316
 
   return detail::isfinite_impl(x, method());
317
 
}
318
 
 
319
 
//------------------------------------------------------------------------------
320
 
 
321
 
namespace detail {
322
 
 
323
 
#ifdef BOOST_MATH_USE_STD_FPCLASSIFY
324
 
    template<class T> 
325
 
    inline bool isnormal_impl(T x, native_tag const&)
326
 
    {
327
 
        return (std::isnormal)(x);
328
 
    }
329
 
#endif
330
 
 
331
 
    template<class T> 
332
 
    inline bool isnormal_impl(T x, generic_tag<true> const&)
333
 
    {
334
 
        if(x < 0) x = -x;
335
 
        return x >= (std::numeric_limits<T>::min)()
336
 
            && x <= (std::numeric_limits<T>::max)();
337
 
    }
338
 
 
339
 
    template<class T> 
340
 
    inline bool isnormal_impl(T x, generic_tag<false> const&)
341
 
    {
342
 
#ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
343
 
      if(std::numeric_limits<T>::is_specialized)
344
 
         return isnormal_impl(x, mpl::true_());
345
 
#endif
346
 
       return !(x == 0);
347
 
    }
348
 
 
349
 
    template<class T> 
350
 
    inline bool isnormal_impl(T x, ieee_tag const&)
351
 
    {
352
 
        typedef BOOST_DEDUCED_TYPENAME detail::fp_traits<T>::type traits;
353
 
        BOOST_DEDUCED_TYPENAME traits::bits a;
354
 
        traits::get_bits(x,a);
355
 
        a &= traits::exponent | traits::flag;
356
 
        return (a != 0) && (a < traits::exponent);
357
 
    }
358
 
 
359
 
#if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && defined(BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY)
360
 
template <>
361
 
inline bool isnormal_impl<long double> BOOST_NO_MACRO_EXPAND(long double t, const native_tag&)
362
 
{
363
 
   return boost::math::detail::isnormal_impl(t, generic_tag<true>());
364
 
}
365
 
#endif
366
 
 
367
 
}
368
 
 
369
 
template<class T> 
370
 
inline bool (isnormal)(T x)
371
 
{
372
 
   typedef typename detail::fp_traits<T>::type traits;
373
 
   typedef typename traits::method method;
374
 
   typedef typename boost::is_floating_point<T>::type fp_tag;
375
 
   return detail::isnormal_impl(x, method());
376
 
}
377
 
 
378
 
//------------------------------------------------------------------------------
379
 
 
380
 
namespace detail {
381
 
 
382
 
#ifdef BOOST_MATH_USE_STD_FPCLASSIFY
383
 
    template<class T> 
384
 
    inline bool isinf_impl(T x, native_tag const&)
385
 
    {
386
 
        return (std::isinf)(x);
387
 
    }
388
 
#endif
389
 
 
390
 
    template<class T> 
391
 
    inline bool isinf_impl(T x, generic_tag<true> const&)
392
 
    {
393
 
        return std::numeric_limits<T>::has_infinity 
394
 
            && ( x == std::numeric_limits<T>::infinity()
395
 
                 || x == -std::numeric_limits<T>::infinity());
396
 
    }
397
 
 
398
 
    template<class T> 
399
 
    inline bool isinf_impl(T x, generic_tag<false> const&)
400
 
    {
401
 
#ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
402
 
      if(std::numeric_limits<T>::is_specialized)
403
 
         return isinf_impl(x, mpl::true_());
404
 
#endif
405
 
        (void)x; // warning supression.
406
 
        return false;
407
 
    }
408
 
 
409
 
    template<class T> 
410
 
    inline bool isinf_impl(T x, ieee_copy_all_bits_tag const&)
411
 
    {
412
 
        typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
413
 
 
414
 
        BOOST_DEDUCED_TYPENAME traits::bits a;
415
 
        traits::get_bits(x,a);
416
 
        a &= traits::exponent | traits::significand;
417
 
        return a == traits::exponent;
418
 
    }
419
 
 
420
 
    template<class T> 
421
 
    inline bool isinf_impl(T x, ieee_copy_leading_bits_tag const&)
422
 
    {
423
 
        typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
424
 
 
425
 
        BOOST_DEDUCED_TYPENAME traits::bits a;
426
 
        traits::get_bits(x,a);
427
 
        a &= traits::exponent | traits::significand;
428
 
        if(a != traits::exponent)
429
 
            return false;
430
 
 
431
 
        traits::set_bits(x,0);
432
 
        return x == 0;
433
 
    }
434
 
 
435
 
#if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && defined(BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY)
436
 
template <>
437
 
inline bool isinf_impl<long double> BOOST_NO_MACRO_EXPAND(long double t, const native_tag&)
438
 
{
439
 
   return boost::math::detail::isinf_impl(t, generic_tag<true>());
440
 
}
441
 
#endif
442
 
 
443
 
}   // namespace detail
444
 
 
445
 
template<class T> 
446
 
inline bool (isinf)(T x)
447
 
{
448
 
   typedef typename detail::fp_traits<T>::type traits;
449
 
   typedef typename traits::method method;
450
 
   typedef typename boost::is_floating_point<T>::type fp_tag;
451
 
   return detail::isinf_impl(x, method());
452
 
}
453
 
 
454
 
//------------------------------------------------------------------------------
455
 
 
456
 
namespace detail {
457
 
 
458
 
#ifdef BOOST_MATH_USE_STD_FPCLASSIFY
459
 
    template<class T> 
460
 
    inline bool isnan_impl(T x, native_tag const&)
461
 
    {
462
 
        return (std::isnan)(x);
463
 
    }
464
 
#endif
465
 
 
466
 
    template<class T> 
467
 
    inline bool isnan_impl(T x, generic_tag<true> const&)
468
 
    {
469
 
        return std::numeric_limits<T>::has_infinity
470
 
            ? !(x <= std::numeric_limits<T>::infinity())
471
 
            : x != x;
472
 
    }
473
 
 
474
 
    template<class T> 
475
 
    inline bool isnan_impl(T x, generic_tag<false> const&)
476
 
    {
477
 
#ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
478
 
      if(std::numeric_limits<T>::is_specialized)
479
 
         return isnan_impl(x, mpl::true_());
480
 
#endif
481
 
        (void)x; // warning supression
482
 
        return false;
483
 
    }
484
 
 
485
 
    template<class T> 
486
 
    inline bool isnan_impl(T x, ieee_copy_all_bits_tag const&)
487
 
    {
488
 
        typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
489
 
 
490
 
        BOOST_DEDUCED_TYPENAME traits::bits a;
491
 
        traits::get_bits(x,a);
492
 
        a &= traits::exponent | traits::significand;
493
 
        return a > traits::exponent;
494
 
    }
495
 
 
496
 
    template<class T> 
497
 
    inline bool isnan_impl(T x, ieee_copy_leading_bits_tag const&)
498
 
    {
499
 
        typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
500
 
 
501
 
        BOOST_DEDUCED_TYPENAME traits::bits a;
502
 
        traits::get_bits(x,a);
503
 
 
504
 
        a &= traits::exponent | traits::significand;
505
 
        if(a < traits::exponent)
506
 
            return false;
507
 
 
508
 
        a &= traits::significand;
509
 
        traits::set_bits(x,a);
510
 
        return x != 0;
511
 
    }
512
 
 
513
 
}   // namespace detail
514
 
 
515
 
template<class T> bool (isnan)(T x)
516
 
{ //!< \brief return true if floating-point type t is NaN (Not A Number).
517
 
   typedef typename detail::fp_traits<T>::type traits;
518
 
   typedef typename traits::method method;
519
 
   typedef typename boost::is_floating_point<T>::type fp_tag;
520
 
   return detail::isnan_impl(x, method());
521
 
}
522
 
 
523
 
#ifdef isnan
524
 
template <> inline bool isnan BOOST_NO_MACRO_EXPAND<float>(float t){ return ::boost::math_detail::is_nan_helper(t, boost::true_type()); }
525
 
template <> inline bool isnan BOOST_NO_MACRO_EXPAND<double>(double t){ return ::boost::math_detail::is_nan_helper(t, boost::true_type()); }
526
 
template <> inline bool isnan BOOST_NO_MACRO_EXPAND<long double>(long double t){ return ::boost::math_detail::is_nan_helper(t, boost::true_type()); }
527
 
#endif
528
 
 
529
 
} // namespace math
530
 
} // namespace boost
531
 
 
532
 
#endif // BOOST_MATH_FPCLASSIFY_HPP
533