Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

gen-num-limits.cc

Go to the documentation of this file.
00001 // Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
00002 //
00003 // This file is part of the GNU ISO C++ Library.  This library is free
00004 // software; you can redistribute it and/or modify it under the
00005 // terms of the GNU General Public License as published by the
00006 // Free Software Foundation; either version 2, or (at your option)
00007 // any later version.
00008 
00009 // This library is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 // GNU General Public License for more details.
00013 
00014 // You should have received a copy of the GNU General Public License along
00015 // with this library; see the file COPYING.  If not, write to the Free
00016 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
00017 // USA.
00018 
00019 // As a special exception, you may use this file as part of a free software
00020 // library without restriction.  Specifically, if other files instantiate
00021 // templates or use macros or inline functions from this file, or you compile
00022 // this file and link it with other files to produce an executable, this
00023 // file does not by itself cause the resulting executable to be covered by
00024 // the GNU General Public License.  This exception does not however
00025 // invalidate any other reasons why the executable file might be covered by
00026 // the GNU General Public License.
00027 
00028 //
00029 // Written by Gabriel Dos Reis <gdr@gcc.gnu.org>
00030 // 
00031 // Note: This program outputs speciliazations of ISO C++ class template
00032 // numeric_limits<> as described in 18.2.1.
00033 // Do not compile with optimization turned on.
00034 //
00035 
00036 #include <bits/c++config.h>
00037 
00038 #if HAVE_CONFIG_H
00039 # include <config.h>
00040 #endif
00041 
00042 //
00043 // Force Linux <limits.h> to define the *LONG_LONG*
00044 //
00045 #if __linux__ && _GLIBCPP_USE_LONG_LONG
00046 # ifndef __USE_GNU
00047 #  define __USE_GNU 1
00048 # endif
00049 # ifndef _GNU_SOURCE
00050 #  define _GNU_SOURCE 1
00051 # endif
00052 #endif
00053 
00054 #include <limits.h>
00055 #include <float.h>
00056 #include <stdio.h>
00057 #include <signal.h>
00058 #include <setjmp.h>
00059 #include <math.h>
00060 #ifdef _GLIBCPP_USE_WCHAR_T
00061 #include <wchar.h>
00062 #endif
00063 
00064 // mknumeric_limits will first try to compile this file with
00065 // HAVE_SIGSETJMP.  If it fails, then it will try without it.  Some
00066 // systems, such as GNU/Linux/sparc, would remain with the signal
00067 // blocked if the signal handler uses longjmp instead of siglongjmp.
00068 // We assume here setjmp/longjmp will preserve the sigblock mask if
00069 // sigsetjmp is not present.
00070 
00071 #if ! HAVE_SIGSETJMP 
00072 # define sigjmp_buf jmp_buf 
00073 # define sigsetjmp(buf, save) setjmp (buf) 
00074 # define siglongjmp(env, ret) longjmp (env, ret) 
00075 #endif 
00076 
00077 const char tab[] = "    ";
00078 const char tab2[] = "        ";
00079 const char* bool_alpha[] = { "false", "true" };
00080 const double log10_of_two = .30102999566398119;
00081 const int bits_per_byte = CHAR_BIT;
00082 const int integer_base_rep = 2;
00083 
00084 
00085 //
00086 // numeric_limits members are all static (as it is usually the case for
00087 // traits) and of three kinds: predicates, values and functions.
00088 // Actually there is no harm to think of values and functions as being
00089 // of the same kind.  Their main purposes are to denote values.
00090 //
00091 
00092 
00093 //
00094 // Integer types: bool, char, signed char, unsigned char, wchar_t,
00095 // short, unsigned short, int, unsigned, long, unsigned long,
00096 // and possibly long long and unsigned long long
00097 //
00098 // Here ISO 14882 disagrees with LIA-1 in stating bool to be an
00099 // integer type.  Therefore itn't suprising to see ambiguity in the
00100 // interpretation of some members.  Need to keep track of the discusion
00101 // in LWG on this topic.
00102 //
00103 // Integer types are first promoted to int or long before the actual
00104 // arithmetical operations are carried out.  Therefore testing whether
00105 // traps occur amounts -- for integer types -- to test whether traps
00106 // occur for int, unsigned, long, unsigned long. Furthermore
00107 // overflow cannot happen for unsigned integer types.
00108 
00109 sigjmp_buf env;
00110 
00111 /* The prototype of signal() may vary.  Accomodate variations such as
00112    void(*)(int) and void(*)(...).  */
00113 template <typename signal_handler_type, typename signal_number_type>
00114 inline void (*signal_adapter (signal_handler_type
00115                   (*signal_func)(signal_number_type,
00116                          signal_handler_type),
00117                   signal_number_type arg,
00118                   void (*handler)(int)))(int)
00119 {
00120   return (void (*)(int))(*signal_func)(arg, (signal_handler_type)handler);
00121 }
00122 
00123 template <typename signal_handler_type, typename signal_number_type>
00124 inline void (*signal_adapter (signal_handler_type (*signal_func)(...),
00125                   signal_number_type arg,
00126                   void (*handler)(int)))(int)
00127 {
00128   return (void (*)(int))(*signal_func)(arg, (signal_handler_type)handler);
00129 }
00130 
00131 void signal_handler(int sig) 
00132 { 
00133 #ifdef __CYGWIN__
00134   static sigset_t x;
00135   signal_adapter (signal, sig, signal_handler);
00136   sigemptyset (&x);
00137   sigprocmask(SIG_SETMASK, &x, NULL);
00138 #endif /* __CYGWIN__ */
00139   siglongjmp(env, sig); 
00140 }
00141 
00142 template<typename Operation>
00143 bool trapping(const Operation& op)
00144 {
00145     if (sigsetjmp(env, 1) == 0) op();
00146     else return true;
00147     return false;
00148 }
00149 
00150 template<typename T> 
00151   struct division_by_zero 
00152   {
00153     void operator() () const
00154     {
00155       volatile T zero = T();
00156       volatile T one = T(1);
00157       volatile T infinity = one / zero;
00158     }
00159   };
00160 
00161 template<typename T> 
00162   struct overflow 
00163   {
00164     void operator() () const
00165     {
00166       T i = T(1);
00167       T j = T();
00168       while (i>j) {
00169     j = i;
00170     i = i * 2 + 1;
00171       }
00172     }
00173   };
00174 
00175 template<typename T> struct underflow { };
00176 
00177 // traps
00178 template<typename T> void traps()
00179 {
00180   fflush(NULL);
00181   signal_adapter (signal, SIGFPE, signal_handler);
00182   signal_adapter (signal, SIGTRAP, signal_handler);
00183   bool trap_flag = trapping(division_by_zero<T>());
00184   signal_adapter (signal, SIGFPE, signal_handler);
00185   signal_adapter (signal, SIGTRAP, signal_handler);
00186   trap_flag = trap_flag || trapping(overflow<T>());
00187   const char* p = bool_alpha[trap_flag];
00188   printf("%s%s = %s;\n", tab2, "static const bool traps", p);    
00189 }
00190 
00191 #define SPECIALIZE_TRAPPING(T)                                          \
00192 template<> void traps< T >()                                            \
00193 {                                       \
00194   fflush(NULL);                                                         \
00195   signal_adapter (signal, SIGFPE, signal_handler);                      \
00196   signal_adapter (signal, SIGTRAP, signal_handler);                     \
00197   const char* p = bool_alpha[trapping(division_by_zero<T>())];          \
00198   printf("%s%s = %s;\n", tab2, "static const bool traps", p);           \
00199 }
00200 
00201 SPECIALIZE_TRAPPING(unsigned char);
00202 SPECIALIZE_TRAPPING(unsigned short);
00203 SPECIALIZE_TRAPPING(unsigned int);
00204 SPECIALIZE_TRAPPING(unsigned long);
00205 #if _GLIBCPP_USE_LONG_LONG
00206 SPECIALIZE_TRAPPING(unsigned long long);
00207 #endif
00208 
00209 #undef SPECIALIZE_TRAPPING
00210 
00211 template<typename T> 
00212   struct type_name_trait 
00213   {
00214     static const char type_name[];
00215     static const char trait_name[];
00216   };
00217 
00218 #define DEFINED_TYPE_NAME(T)                                            \
00219 const char type_name_trait< T >::type_name[] = #T;                      \
00220 const char type_name_trait< T >::trait_name[] = "numeric_limits<" #T ">";
00221 
00222 DEFINED_TYPE_NAME(bool);
00223 DEFINED_TYPE_NAME(char);
00224 DEFINED_TYPE_NAME(signed char);
00225 DEFINED_TYPE_NAME(unsigned char);
00226 DEFINED_TYPE_NAME(wchar_t);
00227 DEFINED_TYPE_NAME(short);
00228 DEFINED_TYPE_NAME(unsigned short);
00229 DEFINED_TYPE_NAME(int);
00230 DEFINED_TYPE_NAME(unsigned int);
00231 DEFINED_TYPE_NAME(long);
00232 DEFINED_TYPE_NAME(unsigned long);
00233 #ifdef _GLIBCPP_USE_LONG_LONG
00234 DEFINED_TYPE_NAME(long long);
00235 DEFINED_TYPE_NAME(unsigned long long);
00236 #endif
00237 DEFINED_TYPE_NAME(float);
00238 DEFINED_TYPE_NAME(double);
00239 DEFINED_TYPE_NAME(long double);
00240 
00241 #undef DEFINED_TYPE_NAME
00242 
00243 // declarator
00244 template<typename T> 
00245   struct declarator : type_name_trait<T> 
00246   {
00247     typedef type_name_trait<T> base;
00248     static void start()
00249     { 
00250       printf("%s%s %s %s\n", tab, "template<> struct", base::trait_name, "{"); 
00251     }
00252     
00253     static void end()
00254     { printf("%s};\n\n", tab); }
00255   };
00256 
00257 
00258 //
00259 // Predicates
00260 // 
00261 template<typename T> 
00262   struct predicate 
00263   {
00264     static const bool is_signed;
00265     static const bool is_integer;
00266     static const bool is_exact;
00267     
00268     static const bool has_infinity;
00269     static const bool has_quiet_nan;
00270     static const bool has_signaling_nan;
00271     static const bool has_denorm;
00272     static const bool has_denorm_loss;
00273     
00274     static const bool is_iec559;
00275     static const bool is_bounded;
00276     
00277     static const bool traps;
00278   };
00279 
00280 template<typename T>
00281 const bool predicate<T>::is_signed = T(-1) < 0;
00282 
00283 // Non integer types should specialize this
00284 template<typename T>
00285 const bool predicate<T>::is_integer = true;
00286 
00287 // Non exact types should specialize this;
00288 template<typename T>
00289 const bool predicate<T>::is_exact = true;
00290 
00291 #define SPECIALIZE_EXACTNESS(T)                     \
00292 const bool predicate< T >::is_integer = false;              \
00293 const bool predicate< T >::is_exact = false
00294 
00295 SPECIALIZE_EXACTNESS(float);
00296 SPECIALIZE_EXACTNESS(double);
00297 SPECIALIZE_EXACTNESS(long double);
00298 
00299 #undef SPECIALIZE_EXACTNESS
00300 
00301 
00302 template<typename T>
00303 const bool predicate<T>::has_infinity = false;
00304 
00305 template<typename T>
00306 const bool predicate<T>::has_quiet_nan = false;
00307 
00308 template<typename T>
00309 const bool predicate<T>::has_signaling_nan = false;
00310 
00311 template<typename T>
00312 const bool predicate<T>::has_denorm = false;
00313 
00314 template<typename T>
00315 const bool predicate<T>::has_denorm_loss = false;
00316 
00317 
00318 
00319 // Each type conforming to IEC559 specifications should specialize this.
00320 template<typename T>
00321 const bool predicate<T>::is_iec559 = false;
00322 
00323 #define SPECIALIZE_IEC559(T)                        \
00324 const bool predicate< T >::is_iec559 = true
00325 
00326 SPECIALIZE_IEC559(bool);
00327 SPECIALIZE_IEC559(int);
00328 SPECIALIZE_IEC559(unsigned int);
00329 SPECIALIZE_IEC559(long);
00330 SPECIALIZE_IEC559(unsigned long);
00331 #ifdef _GLIBCPP_USE_LONG_LONG
00332 SPECIALIZE_IEC559(long long);
00333 SPECIALIZE_IEC559(unsigned long long);
00334 #endif
00335 
00336 #undef SPECIALIZE_IEC559
00337 
00338 //
00339 // Values
00340 // 
00341 template<typename T> 
00342   struct value 
00343   {
00344     static const char min[];
00345     static const char max[];
00346     
00347     static const int digits;
00348     static const int digits10;
00349     
00350     static const int radix;
00351     static const char epsilon[];
00352     static const char round_error[];
00353     
00354     static const int min_exponent;
00355     static const int min_exponent10;
00356     static const int max_exponent;
00357     static const int max_exponent10;
00358   };
00359 
00360 #define DEFINE_EXTREMA(T, m, M)  DO_DEFINE_EXTREMA(T, m, M)
00361 #define DO_DEFINE_EXTREMA(T, m, M)                  \
00362 const char value< T >::min[] = #m;                  \
00363 const char value< T >::max[] = #M
00364 
00365 DEFINE_EXTREMA(bool, false, true);
00366 DEFINE_EXTREMA(char, CHAR_MIN, CHAR_MAX);
00367 DEFINE_EXTREMA(signed char, SCHAR_MIN, SCHAR_MAX);
00368 DEFINE_EXTREMA(unsigned char, 0, UCHAR_MAX);
00369 #ifdef _GLIBCPP_USE_WCHAR_T
00370 DEFINE_EXTREMA(wchar_t, WCHAR_MIN, WCHAR_MAX);
00371 #endif
00372 DEFINE_EXTREMA(short, SHRT_MIN, SHRT_MAX);
00373 DEFINE_EXTREMA(unsigned short, 0, USHRT_MAX);
00374 DEFINE_EXTREMA(int, INT_MIN, INT_MAX);
00375 DEFINE_EXTREMA(unsigned int, 0, UINT_MAX);
00376 DEFINE_EXTREMA(long, LONG_MIN, LONG_MAX);
00377 DEFINE_EXTREMA(unsigned long, 0, ULONG_MAX);
00378 #ifdef _GLIBCPP_USE_LONG_LONG
00379 DEFINE_EXTREMA(long long, LONG_LONG_MIN, LONG_LONG_MAX);
00380 DEFINE_EXTREMA(unsigned long long, 0, ULONG_LONG_MAX);
00381 #endif
00382 DEFINE_EXTREMA(float, FLT_MIN, FLT_MAX);
00383 DEFINE_EXTREMA(double, DBL_MIN, DBL_MAX);
00384 DEFINE_EXTREMA(long double, LDBL_MIN, LDBL_MAX);
00385 
00386 #undef DEFINE_EXTREMA
00387 #undef DO_DEFINE_EXTREMA
00388 
00389 // Non integer types should specialize this
00390 template<typename T>
00391 const int value<T>::digits =
00392       bits_per_byte * sizeof(T) - int(predicate<T>::is_signed);
00393 
00394 // Non integer types should specialize this.  Always two for
00395 // integer types.
00396 template<typename T>
00397 const int value<T>::radix = 2;
00398 
00399 #define SPECIALIZE_DIGITS(T, D, D10)                    \
00400 const int value< T >::digits = D;                   \
00401 const int value< T >::digits10 = D10
00402 
00403 SPECIALIZE_DIGITS(float, FLT_MANT_DIG, FLT_DIG);
00404 SPECIALIZE_DIGITS(double, DBL_MANT_DIG, DBL_DIG);
00405 SPECIALIZE_DIGITS(long double, LDBL_MANT_DIG, LDBL_DIG);
00406 
00407 #undef SPECIALIZE_DIGITS
00408 
00409 
00410 #define SPECIALIZE_RADIX(T, R) const int value< T >::radix = R
00411 
00412 SPECIALIZE_RADIX(float, FLT_RADIX);
00413 SPECIALIZE_RADIX(double, FLT_RADIX);
00414 SPECIALIZE_RADIX(long double, FLT_RADIX);
00415 
00416 #undef SPECIALIZE_RADIX
00417 
00418 // Non integer types should specialize this.  
00419 // Unfortunately, systems that don't deal with weak linking correctly
00420 // (Ie, hpux and aix), cannot use this sophisticated yet sane method. So,
00421 // explicitly instantiate all the data members here so that they will
00422 // be happy.
00423 
00424 // sophisticated, sane method
00425 #if 0
00426 template<typename T>
00427 const char value<T>::epsilon[] = "0";
00428 #endif
00429 
00430 #define SPECIALIZE_EPSILON(T, E) DO_SPECIALIZE_EPSILON(T, E)
00431 #define DO_SPECIALIZE_EPSILON(T, E) const char value< T >::epsilon[] = #E
00432 
00433 // unsophisticated, gross method
00434 #if 1
00435 SPECIALIZE_EPSILON(bool, 0);
00436 SPECIALIZE_EPSILON(char, 0);
00437 SPECIALIZE_EPSILON(unsigned char, 0);
00438 SPECIALIZE_EPSILON(signed char, 0);
00439 SPECIALIZE_EPSILON(wchar_t, 0);
00440 SPECIALIZE_EPSILON(short, 0);
00441 SPECIALIZE_EPSILON(unsigned short, 0);
00442 SPECIALIZE_EPSILON(int, 0);
00443 SPECIALIZE_EPSILON(unsigned int, 0);
00444 SPECIALIZE_EPSILON(long, 0);
00445 SPECIALIZE_EPSILON(unsigned long, 0);
00446 SPECIALIZE_EPSILON(long long, 0);
00447 SPECIALIZE_EPSILON(unsigned long long, 0);
00448 #endif
00449 
00450 SPECIALIZE_EPSILON(float, FLT_EPSILON);
00451 SPECIALIZE_EPSILON(double, DBL_EPSILON);
00452 SPECIALIZE_EPSILON(long double, LDBL_EPSILON);
00453 
00454 #undef DO_SPECIALIZE_EPSILON
00455 #undef SPECIALIZE_EPSILON
00456 
00457 
00458 // Non integer types should specialize this.  
00459 // Unfortunately, systems that don't deal with weak linking correctly
00460 // (Ie, hpux and aix), cannot use this sophisticated yet sane method. So,
00461 // explicitly instantiate all the data members here so that they will
00462 // be happy.
00463 
00464 // sophisticated, sane method
00465 #if 0
00466 template<typename T>
00467 const char value<T>::round_error[] = "0";
00468 #endif
00469 
00470 #define SPECIALIZE_ROUND_ERROR(T, R) const char value< T >::round_error[] = #R
00471 // unsophisticated, gross method
00472 #if 1
00473 SPECIALIZE_ROUND_ERROR(bool, 0);
00474 SPECIALIZE_ROUND_ERROR(char, 0);
00475 SPECIALIZE_ROUND_ERROR(unsigned char, 0);
00476 SPECIALIZE_ROUND_ERROR(signed char, 0);
00477 SPECIALIZE_ROUND_ERROR(wchar_t, 0);
00478 SPECIALIZE_ROUND_ERROR(short, 0);
00479 SPECIALIZE_ROUND_ERROR(unsigned short, 0);
00480 SPECIALIZE_ROUND_ERROR(int, 0);
00481 SPECIALIZE_ROUND_ERROR(unsigned int, 0);
00482 SPECIALIZE_ROUND_ERROR(long, 0);
00483 SPECIALIZE_ROUND_ERROR(unsigned long, 0);
00484 SPECIALIZE_ROUND_ERROR(long long, 0);
00485 SPECIALIZE_ROUND_ERROR(unsigned long long, 0);
00486 #endif
00487 
00488 SPECIALIZE_ROUND_ERROR(float, 1.0f);
00489 SPECIALIZE_ROUND_ERROR(double, 1.0);
00490 SPECIALIZE_ROUND_ERROR(long double, 1.0L);
00491 
00492 #undef SPECIALIZE_ROUND_ERROR
00493 
00494 
00495 template<typename T>
00496 const int value<T>::min_exponent = 0;
00497 
00498 template<typename T>
00499 const int value<T>::min_exponent10 = 0;
00500 
00501 template<typename T>
00502 const int value<T>::max_exponent = 0;
00503 
00504 template<typename T>
00505 const int value<T>::max_exponent10 = 0;
00506 
00507 #define SPECIALIZE_EXPONENTS(T, m, m10, M, M10)             \
00508 const int value< T >::min_exponent = m;                 \
00509 const int value< T >::min_exponent10 = m10;             \
00510 const int value< T >::max_exponent = M;                 \
00511 const int value< T >::max_exponent10 = M10
00512 
00513 SPECIALIZE_EXPONENTS(float, FLT_MIN_EXP, FLT_MIN_10_EXP,
00514                      FLT_MAX_EXP, FLT_MAX_10_EXP);
00515 SPECIALIZE_EXPONENTS(double, DBL_MIN_EXP, DBL_MIN_10_EXP,
00516                      DBL_MAX_EXP, DBL_MAX_10_EXP);
00517 SPECIALIZE_EXPONENTS(long double, LDBL_MIN_EXP, LDBL_MIN_10_EXP,
00518                      LDBL_MAX_EXP, LDBL_MAX_10_EXP);
00519 
00520 #undef SPECIALIZE_EXPONENTS
00521 
00522 //
00523 // Functions to output predicates and values.
00524 //
00525 
00526 template<typename T> void is_signed()
00527 {
00528   printf("%s%s = %s;\n", tab2, "static const bool is_signed",
00529      bool_alpha[predicate<T>::is_signed]);
00530 }
00531 
00532 // a fundamental type is modulo iff it isn't signed
00533 template<typename T> void is_modulo()
00534 {
00535   printf("%s%s = %s;\n", tab2, "static const bool is_modulo",
00536      bool_alpha[! predicate<T>::is_signed]);
00537 }
00538 
00539 template<typename T>
00540 void min()
00541 {
00542   printf("%s%s%s%s\n%s%s%s%s\n", tab2, "static ", declarator<T>::type_name,
00543      " min() throw()", tab2, "{ return ", value<T>::min, "; }");
00544 }
00545 
00546 template<typename T>
00547 void max()
00548 {
00549   printf("%s%s%s%s\n%s%s%s%s\n", tab2, "static ", declarator<T>::type_name,
00550      " max() throw()", tab2, "{ return ", value<T>::max, "; }");
00551 }
00552 
00553 template<typename T>
00554 void is_integer()
00555 {
00556   printf("%s%s = %s;\n", tab2, "static const bool is_integer",
00557      bool_alpha[predicate<T>::is_integer]);        
00558 }
00559 
00560 template<typename T>
00561 void is_exact()
00562 {
00563   printf("%s%s = %s;\n", tab2, "static const bool is_exact",
00564      bool_alpha[predicate<T>::is_exact]);    
00565 }
00566 
00567 template<typename T>
00568 void digits()
00569 {
00570   printf("%s%s = %d;\n", tab2, "static const int digits",
00571      value<T>::digits);
00572 }
00573 
00574 template<typename T>
00575 void digits10()
00576 {
00577   printf("%s%s = %d;\n", tab2, "static const int digits10",
00578      int(log10_of_two * value<T>::digits));
00579 }
00580 
00581 template<typename T>
00582 void radix()
00583 {
00584   printf("%s%s = %d;\n", tab2, "static const int radix",
00585      value<T>::radix);
00586 }
00587 
00588 template<typename T>
00589 void epsilon()
00590 {
00591   printf("%s%s %s %s\n%s%s %s%s\n", tab2, "static",
00592      declarator<T>::type_name, "epsilon() throw()",
00593      tab2, "{ return", value<T>::epsilon, "; }");
00594 }
00595 
00596 template<typename T>
00597 void round_error()
00598 {
00599   printf("%s%s %s %s\n%s%s %s%s\n", tab2, "static",
00600      declarator<T>::type_name, "round_error() throw()",
00601      tab2, "{ return", value<T>::round_error, "; }");
00602 }
00603 
00604 template<typename T>
00605 void min_exponent()
00606 {
00607   printf("%s%s = %d;\n", tab2, "static const int min_exponent",
00608      value<T>::min_exponent);    
00609 }
00610 
00611 template<typename T>
00612 void min_exponent10()
00613 {
00614   printf("%s%s = %d;\n", tab2, "static const int min_exponent10",
00615      value<T>::min_exponent10);    
00616 }
00617 
00618 template<typename T>
00619 void max_exponent()
00620 {
00621   printf("%s%s = %d;\n", tab2, "static const int max_exponent",
00622      value<T>::max_exponent);    
00623 }
00624 
00625 template<typename T>
00626 void max_exponent10()
00627 {
00628   printf("%s%s = %d;\n", tab2, "static const int max_exponent10",
00629      value<T>::max_exponent10);    
00630 }
00631 
00632 template<typename T>
00633 void has_infinity()
00634 {
00635   printf("%s%s = %s;\n", tab2, "static const bool has_infinity",
00636      bool_alpha[predicate<T>::has_infinity]);
00637 }
00638 
00639 template<typename T>
00640 void has_quiet_nan()
00641 {
00642   printf("%s%s = %s;\n", tab2, "static const bool has_quiet_NaN",
00643      bool_alpha[predicate<T>::has_quiet_nan]);
00644 }
00645 
00646 template<typename T>
00647 void has_signaling_nan()
00648 {
00649   printf("%s%s = %s;\n", tab2, "static const bool has_signaling_NaN",
00650      bool_alpha[predicate<T>::has_signaling_nan]);
00651 }
00652 
00653 template<typename T>
00654 void has_denorm_loss()
00655 {
00656   printf("%s%s = %s;\n", tab2, "static const bool has_denorm_loss",
00657      bool_alpha[predicate<T>::has_denorm_loss]);
00658 }
00659 
00660 template<typename T> 
00661   struct infinity_trait 
00662   {
00663     static void has_denorm()
00664     {
00665       printf("%s%s;\n", tab2, "static const float_denorm_style "
00666          "has_denorm = denorm_absent");
00667     }
00668     
00669     static void infinity()
00670     {
00671       printf("%s%s %s %s\n%s%s%s%s\n", tab2, "static",
00672          declarator<T>::type_name, "infinity() throw()", tab2, 
00673          "{ return static_cast<", declarator<T>::type_name, ">(0); }");
00674     }
00675 
00676     static void quiet_NaN()
00677     {
00678       printf("%s%s %s %s\n%s%s%s%s\n", tab2, "static",
00679          declarator<T>::type_name, "quiet_NaN() throw()",
00680          tab2, "{ return static_cast<", declarator<T>::type_name, 
00681          ">(0); }");
00682     }
00683     
00684     static void signaling_NaN()
00685     {
00686       printf("%s%s %s %s\n%s%s%s%s\n", tab2, "static",
00687          declarator<T>::type_name, "signaling_NaN() throw()",
00688          tab2, "{ return static_cast<", declarator<T>::type_name, 
00689          ">(0); }");
00690     }
00691 
00692     static void denorm_min()
00693     {
00694       printf("%s%s %s %s\n%s%s%s%s\n", tab2, "static",
00695          declarator<T>::type_name, "denorm_min() throw()",
00696          tab2, "{ return static_cast<", declarator<T>::type_name, 
00697          ">(0); }");
00698     }
00699   };
00700 
00701 
00702 template<typename T>
00703 void is_iec559()
00704 {
00705   printf("%s%s = %s;\n", tab2, "static const bool is_iec559",
00706      bool_alpha[predicate<T>::is_iec559]);
00707 }
00708 
00709 // tinyness_before
00710 template<typename T>
00711 void tinyness_before()
00712 {
00713   printf("%s%s;\n", tab2, "static const bool tinyness_before = false");
00714 }
00715 
00716 // round style
00717 template<typename T>
00718 void round_style()
00719 {
00720   printf("%s%s;\n", tab2, "static const float_round_style "
00721      "round_style = round_toward_zero");    
00722 }
00723 
00724 
00725 
00726 // type traits
00727 template<typename T> 
00728   struct type_trait 
00729   {
00730     type_trait()
00731     {
00732       declarator<T>::start();
00733       printf("%s%s;\n\n", tab2, "static const bool is_specialized = true");
00734       min<T>();
00735       max<T>();
00736       printf("\n");
00737       digits<T>();
00738       digits10<T>();
00739       is_signed<T>();
00740       is_integer<T>();
00741       is_exact<T>();
00742       radix<T>();
00743       epsilon<T>();
00744       round_error<T>();
00745       printf("\n");
00746       min_exponent<T>();
00747       min_exponent10<T>();
00748       max_exponent<T>();
00749       max_exponent10<T>();
00750       printf("\n");
00751       has_infinity<T>();
00752       has_quiet_nan<T>();
00753       has_signaling_nan<T>();
00754       infinity_trait<T>::has_denorm();
00755       has_denorm_loss<T>();
00756       printf("\n");
00757       infinity_trait<T>::infinity();
00758       infinity_trait<T>::quiet_NaN();
00759       infinity_trait<T>::signaling_NaN();
00760       infinity_trait<T>::denorm_min();
00761       printf("\n");
00762       is_iec559<T>();
00763       printf("%s%s;\n", tab2, "static const bool is_bounded = true");
00764       is_modulo<T>();
00765       printf("\n");
00766       traps<T>();
00767       tinyness_before<T>();
00768       round_style<T>();
00769       declarator<T>::end();
00770     }
00771   };
00772 
00773 int main()
00774 {
00775   type_trait<bool>();
00776   
00777   type_trait<char>();
00778   type_trait<signed char>();
00779   type_trait<unsigned char>();
00780 #if defined( _GLIBCPP_USE_WCHAR_T) 
00781   type_trait<wchar_t>();
00782 #endif
00783   
00784   type_trait<short>();
00785   type_trait<unsigned short>();
00786   
00787   type_trait<int>();
00788   type_trait<unsigned int>();
00789   
00790   type_trait<long>();
00791   type_trait<unsigned long>();
00792   
00793 #ifdef _GLIBCPP_USE_LONG_LONG
00794   type_trait<long long>();
00795   type_trait<unsigned long long>();
00796 #endif
00797 
00798   type_trait<float>();
00799   type_trait<double>();
00800   type_trait<long double>();
00801   
00802   // x86/linux gets this weirdness for the min/max functions:
00803   // static long double min() throw()
00804   // { return (__extension__ ((union __convert_long_double) 
00805   // {__convert_long_double_i: {0x0, 0x80000000, 0x1, 0x0}})
00806   // .__convert_long_double_d); }
00807 }
00808 
00809 // G++ doesn't have support for automatic instantiation of static data
00810 // members on platforms that don't have weak symbols.  On AIX, in
00811 // particular, static data members must be explicitly instantiated.
00812 // So, we explicitly instantiate some of the ones we need.  To save
00813 // typing, we don't name the static data members explicitly; we
00814 // instead name their containing types.
00815 
00816 #define INSTANTIATIONS(TYPE)            \
00817   template struct predicate<TYPE>;      \
00818   template struct value<TYPE>
00819 
00820 INSTANTIATIONS (bool);
00821 INSTANTIATIONS (char);
00822 INSTANTIATIONS (signed char);
00823 INSTANTIATIONS (unsigned char);
00824 INSTANTIATIONS (short);
00825 INSTANTIATIONS (unsigned short);
00826 INSTANTIATIONS (int);
00827 INSTANTIATIONS (unsigned int);
00828 INSTANTIATIONS (long);
00829 INSTANTIATIONS (unsigned long);
00830 INSTANTIATIONS (float);
00831 INSTANTIATIONS (double);
00832 INSTANTIATIONS (long double);
00833 #ifdef _GLIBCPP_USE_WCHAR_T
00834 INSTANTIATIONS (wchar_t);
00835 #endif

Generated at Tue May 1 16:28:38 2001 for libstdc++-v3 by doxygen1.2.6 written by Dimitri van Heesch, © 1997-2001