Whole document tree
    

Whole document tree

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

Generated on Mon Apr 8 03:11:25 2002 for libstdc++-v3 Source by doxygen1.2.15