~ubuntu-branches/ubuntu/saucy/merkaartor/saucy

« back to all changes in this revision

Viewing changes to include/builtin-boost/boost/math/special_functions/fpclassify.hpp

Tags: upstream-0.15.3+svn20934
ImportĀ upstreamĀ versionĀ 0.15.3+svn20934

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