Whole document tree gen-num-limits.ccGo 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 ![]() |