OSDN Git Service

* configure.in (toplevel_srcdir, auxdir): Set.
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / src / gen-num-limits.cc
1 // Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
2 //
3 // This file is part of the GNU ISO C++ Library.  This library is free
4 // software; you can redistribute it and/or modify it under the
5 // terms of the GNU General Public License as published by the
6 // Free Software Foundation; either version 2, or (at your option)
7 // any later version.
8
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13
14 // You should have received a copy of the GNU General Public License along
15 // with this library; see the file COPYING.  If not, write to the Free
16 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
17 // USA.
18
19 // As a special exception, you may use this file as part of a free software
20 // library without restriction.  Specifically, if other files instantiate
21 // templates or use macros or inline functions from this file, or you compile
22 // this file and link it with other files to produce an executable, this
23 // file does not by itself cause the resulting executable to be covered by
24 // the GNU General Public License.  This exception does not however
25 // invalidate any other reasons why the executable file might be covered by
26 // the GNU General Public License.
27
28 //
29 // Written by Gabriel Dos Reis <gdr@gcc.gnu.org>
30 // 
31 // Note: This program outputs speciliazations of ISO C++ class template
32 // numeric_limits<> as described in 18.2.1.
33 // Do not compile with optimization turned on.
34 //
35
36 #include <bits/c++config.h>
37
38 //
39 // Force Linux <limits.h> to define the *LONG_LONG*
40 //
41 #if __linux__ && _GLIBCPP_USE_LONG_LONG
42 # ifndef __USE_GNU
43 #  define __USE_GNU 1
44 # endif
45 # ifndef _GNU_SOURCE
46 #  define _GNU_SOURCE 1
47 # endif
48 #endif
49
50 #include <limits.h>
51 #include <float.h>
52 #include <stdio.h>
53 #include <signal.h>
54 #include <setjmp.h>
55 #include <math.h>
56 #ifdef _GLIBCPP_USE_WCHAR_T
57 #include <wchar.h>
58 #endif
59
60
61 const char tab[] = "    ";
62 const char tab2[] = "        ";
63 const char* bool_alpha[] = { "false", "true" };
64 const double log10_of_two = .30102999566398119;
65 const int bits_per_byte = CHAR_BIT;
66 const int integer_base_rep = 2;
67
68
69 //
70 // numeric_limits members are all static (as it is usually the case for
71 // traits) and of three kinds: predicates, values and functions.
72 // Actually there is no harm to think of values and functions as being
73 // of the same kind.  Their main purposes are to denote values.
74 //
75
76
77 //
78 // Integer types: bool, char, signed char, unsigned char, wchar_t,
79 // short, unsigned short, int, unsigned, long, unsigned long,
80 // and possibly long long and unsigned long long
81 //
82 // Here ISO 14882 disagrees with LIA-1 in stating bool to be an
83 // integer type.  Therefore itn't suprising to see ambiguity in the
84 // interpretation of some members.  Need to keep track of the discusion
85 // in LWG on this topic.
86 //
87 // Integer types are first promoted to int or long before the actual
88 // arithmetical operations are carried out.  Therefore testing whether
89 // traps occur amounts -- for integer types -- to test whether traps
90 // occur for int, unsigned, long, unsigned long. Furthermore
91 // overflow cannot happen for unsigned integer types.
92
93 jmp_buf env;
94
95 /* The prototype of signal() may vary.  Accomodate variations such as
96    void(*)(int) and void(*)(...).  */
97 template <typename signal_handler_type, typename signal_number_type>
98 inline void (*signal_adapter (signal_handler_type
99                               (*signal_func)(signal_number_type,
100                                              signal_handler_type),
101                        signal_number_type arg,
102                        void (*handler)(int)))(int)
103 {
104   return (void (*)(int))(*signal_func)(arg, (signal_handler_type)handler);
105 }
106
107 void signal_handler(int sig) 
108
109 #ifdef __CYGWIN__
110   static sigset_t x;
111   signal_adapter (signal, sig, signal_handler);
112   sigemptyset (&x);
113   sigprocmask(SIG_SETMASK, &x, NULL);
114 #endif /* __CYGWIN__ */
115   longjmp(env, sig); 
116 }
117
118 template<typename Operation>
119 bool trapping(const Operation& op)
120 {
121     if (setjmp(env) == 0) op();
122     else return true;
123     return false;
124 }
125
126 template<typename T> struct division_by_zero {
127     void operator() () const
128     {
129         volatile T zero = T();
130         volatile T one = T(1);
131         volatile T infinity = one / zero;
132     }
133 };
134
135 template<typename T> struct overflow {
136     void operator() () const
137     {
138         T i = T(1);
139         T j = T();
140         while (i>j) {
141             j = i;
142             i = i * 2 + 1;
143         }
144     }
145 };
146
147 template<typename T> struct underflow {};
148
149 // traps
150 template<typename T> void traps()
151 {
152     signal_adapter (signal, SIGFPE, signal_handler);
153     signal_adapter (signal, SIGTRAP, signal_handler);
154     bool trap_flag = trapping(division_by_zero<T>());
155     signal_adapter (signal, SIGFPE, signal_handler);
156     signal_adapter (signal, SIGTRAP, signal_handler);
157     trap_flag = trap_flag || trapping(overflow<T>());
158     const char* p = bool_alpha[trap_flag];
159     printf("%s%s = %s;\n", tab2, "static const bool traps", p);    
160 }
161
162 #define SPECIALIZE_TRAPPING(T)                                          \
163 template<> void traps< T >()                                            \
164 {                                                                       \
165     signal_adapter (signal, SIGFPE, signal_handler);                    \
166     signal_adapter (signal, SIGTRAP, signal_handler);                    \
167     const char* p = bool_alpha[trapping(division_by_zero<T>())];        \
168     printf("%s%s = %s;\n", tab2, "static const bool traps", p);         \
169 }
170
171 SPECIALIZE_TRAPPING(unsigned char);
172 SPECIALIZE_TRAPPING(unsigned short);
173 SPECIALIZE_TRAPPING(unsigned int);
174 SPECIALIZE_TRAPPING(unsigned long);
175 #if _GLIBCPP_USE_LONG_LONG
176 SPECIALIZE_TRAPPING(unsigned long long);
177 #endif
178
179 #undef SPECIALIZE_TRAPPING
180
181 template<typename T> struct type_name_trait {
182     static const char type_name[];
183     static const char trait_name[];
184 };
185
186 #define DEFINED_TYPE_NAME(T)                                            \
187 const char type_name_trait< T >::type_name[] = #T;                      \
188 const char type_name_trait< T >::trait_name[] = "numeric_limits<" #T ">";
189
190 DEFINED_TYPE_NAME(bool);
191 DEFINED_TYPE_NAME(char);
192 DEFINED_TYPE_NAME(signed char);
193 DEFINED_TYPE_NAME(unsigned char);
194 DEFINED_TYPE_NAME(wchar_t);
195 DEFINED_TYPE_NAME(short);
196 DEFINED_TYPE_NAME(unsigned short);
197 DEFINED_TYPE_NAME(int);
198 DEFINED_TYPE_NAME(unsigned int);
199 DEFINED_TYPE_NAME(long);
200 DEFINED_TYPE_NAME(unsigned long);
201 #ifdef _GLIBCPP_USE_LONG_LONG
202 DEFINED_TYPE_NAME(long long);
203 DEFINED_TYPE_NAME(unsigned long long);
204 #endif
205 DEFINED_TYPE_NAME(float);
206 DEFINED_TYPE_NAME(double);
207 DEFINED_TYPE_NAME(long double);
208
209 #undef DEFINED_TYPE_NAME
210
211 // declarator
212 template<typename T> struct declarator : type_name_trait<T> {
213     typedef type_name_trait<T> base;
214     static void start()
215     {
216         printf("%s%s %s %s\n", tab, "template<> struct",
217                base::trait_name, "{");
218     }
219
220     static void end()
221     {
222         printf("%s};\n\n", tab);
223     }
224 };
225
226
227 //
228 // Predicates
229 // 
230 template<typename T> struct predicate {
231     static const bool is_signed;
232     static const bool is_integer;
233     static const bool is_exact;
234
235     static const bool has_infinity;
236     static const bool has_quiet_nan;
237     static const bool has_signaling_nan;
238     static const bool has_denorm;
239     static const bool has_denorm_loss;
240
241     static const bool is_iec559;
242     static const bool is_bounded;
243
244     static const bool traps;
245 };
246
247 template<typename T>
248 const bool predicate<T>::is_signed = T(-1) < 0;
249
250 // Non integer types should specialize this
251 template<typename T>
252 const bool predicate<T>::is_integer = true;
253
254 // Non exact types should specialize this;
255 template<typename T>
256 const bool predicate<T>::is_exact = true;
257
258 #define SPECIALIZE_EXACTNESS(T)                                         \
259 const bool predicate< T >::is_integer = false;                          \
260 const bool predicate< T >::is_exact = false
261
262 SPECIALIZE_EXACTNESS(float);
263 SPECIALIZE_EXACTNESS(double);
264 SPECIALIZE_EXACTNESS(long double);
265
266 #undef SPECIALIZE_EXACTNESS
267
268
269 template<typename T>
270 const bool predicate<T>::has_infinity = false;
271
272 template<typename T>
273 const bool predicate<T>::has_quiet_nan = false;
274
275 template<typename T>
276 const bool predicate<T>::has_signaling_nan = false;
277
278 template<typename T>
279 const bool predicate<T>::has_denorm = false;
280
281 template<typename T>
282 const bool predicate<T>::has_denorm_loss = false;
283
284
285
286 // Each type conforming to IEC559 specifications should specialize this.
287 template<typename T>
288 const bool predicate<T>::is_iec559 = false;
289
290 #define SPECIALIZE_IEC559(T)                                            \
291 const bool predicate< T >::is_iec559 = true
292
293 SPECIALIZE_IEC559(bool);
294 SPECIALIZE_IEC559(int);
295 SPECIALIZE_IEC559(unsigned int);
296 SPECIALIZE_IEC559(long);
297 SPECIALIZE_IEC559(unsigned long);
298 #ifdef _GLIBCPP_USE_LONG_LONG
299 SPECIALIZE_IEC559(long long);
300 SPECIALIZE_IEC559(unsigned long long);
301 #endif
302
303 #undef SPECIALIZE_IEC559
304
305 //
306 // Values
307 // 
308
309 template<typename T> struct value {
310     static const char min[];
311     static const char max[];
312
313     static const int digits;
314     static const int digits10;
315     
316     static const int radix;
317     static const char epsilon[];
318     static const char round_error[];
319
320     static const int min_exponent;
321     static const int min_exponent10;
322     static const int max_exponent;
323     static const int max_exponent10;
324 };
325
326 #define DEFINE_EXTREMA(T, m, M)  DO_DEFINE_EXTREMA(T, m, M)
327 #define DO_DEFINE_EXTREMA(T, m, M)                                      \
328 const char value< T >::min[] = #m;                                      \
329 const char value< T >::max[] = #M
330
331 DEFINE_EXTREMA(bool, false, true);
332 DEFINE_EXTREMA(char, CHAR_MIN, CHAR_MAX);
333 DEFINE_EXTREMA(signed char, SCHAR_MIN, SCHAR_MAX);
334 DEFINE_EXTREMA(unsigned char, 0, UCHAR_MAX);
335 #ifdef _GLIBCPP_USE_WCHAR_T
336 DEFINE_EXTREMA(wchar_t, WCHAR_MIN, WCHAR_MAX);
337 #endif
338 DEFINE_EXTREMA(short, SHRT_MIN, SHRT_MAX);
339 DEFINE_EXTREMA(unsigned short, 0, USHRT_MAX);
340 DEFINE_EXTREMA(int, INT_MIN, INT_MAX);
341 DEFINE_EXTREMA(unsigned int, 0, UINT_MAX);
342 DEFINE_EXTREMA(long, LONG_MIN, LONG_MAX);
343 DEFINE_EXTREMA(unsigned long, 0, ULONG_MAX);
344 #ifdef _GLIBCPP_USE_LONG_LONG
345 DEFINE_EXTREMA(long long, LONG_LONG_MIN, LONG_LONG_MAX);
346 DEFINE_EXTREMA(unsigned long long, 0, ULONG_LONG_MAX);
347 #endif
348 DEFINE_EXTREMA(float, FLT_MIN, FLT_MAX);
349 DEFINE_EXTREMA(double, DBL_MIN, DBL_MAX);
350 DEFINE_EXTREMA(long double, LDBL_MIN, LDBL_MAX);
351
352 #undef DEFINE_EXTREMA
353 #undef DO_DEFINE_EXTREMA
354
355 // Non integer types should specialize this
356 template<typename T>
357 const int value<T>::digits =
358       bits_per_byte * sizeof(T) - int(predicate<T>::is_signed);
359
360 // Non integer types should specialize this.  Always two for
361 // integer types.
362 template<typename T>
363 const int value<T>::radix = 2;
364
365 #define SPECIALIZE_DIGITS(T, D, D10)                                    \
366 const int value< T >::digits = D;                                       \
367 const int value< T >::digits10 = D10
368
369 SPECIALIZE_DIGITS(float, FLT_MANT_DIG, FLT_DIG);
370 SPECIALIZE_DIGITS(double, DBL_MANT_DIG, DBL_DIG);
371 SPECIALIZE_DIGITS(long double, LDBL_MANT_DIG, LDBL_DIG);
372
373 #undef SPECIALIZE_DIGITS
374
375
376 #define SPECIALIZE_RADIX(T, R) const int value< T >::radix = R
377
378 SPECIALIZE_RADIX(float, FLT_RADIX);
379 SPECIALIZE_RADIX(double, FLT_RADIX);
380 SPECIALIZE_RADIX(long double, FLT_RADIX);
381
382 #undef SPECIALIZE_RADIX
383
384 // Non integer types should specialize this.  
385 // Unfortunately, systems that don't deal with weak linking correctly
386 // (Ie, hpux and aix), cannot use this sophisticated yet sane method. So,
387 // explicitly instantiate all the data members here so that they will
388 // be happy.
389
390 // sophisticated, sane method
391 #if 0
392 template<typename T>
393 const char value<T>::epsilon[] = "0";
394 #endif
395
396 #define SPECIALIZE_EPSILON(T, E) DO_SPECIALIZE_EPSILON(T, E)
397 #define DO_SPECIALIZE_EPSILON(T, E) const char value< T >::epsilon[] = #E
398
399 // unsophisticated, gross method
400 #if 1
401 SPECIALIZE_EPSILON(bool, 0);
402 SPECIALIZE_EPSILON(char, 0);
403 SPECIALIZE_EPSILON(unsigned char, 0);
404 SPECIALIZE_EPSILON(signed char, 0);
405 SPECIALIZE_EPSILON(wchar_t, 0);
406 SPECIALIZE_EPSILON(short, 0);
407 SPECIALIZE_EPSILON(unsigned short, 0);
408 SPECIALIZE_EPSILON(int, 0);
409 SPECIALIZE_EPSILON(unsigned int, 0);
410 SPECIALIZE_EPSILON(long, 0);
411 SPECIALIZE_EPSILON(unsigned long, 0);
412 SPECIALIZE_EPSILON(long long, 0);
413 SPECIALIZE_EPSILON(unsigned long long, 0);
414 #endif
415
416 SPECIALIZE_EPSILON(float, FLT_EPSILON);
417 SPECIALIZE_EPSILON(double, DBL_EPSILON);
418 SPECIALIZE_EPSILON(long double, LDBL_EPSILON);
419
420 #undef DO_SPECIALIZE_EPSILON
421 #undef SPECIALIZE_EPSILON
422
423
424 // Non integer types should specialize this.  
425 // Unfortunately, systems that don't deal with weak linking correctly
426 // (Ie, hpux and aix), cannot use this sophisticated yet sane method. So,
427 // explicitly instantiate all the data members here so that they will
428 // be happy.
429
430 // sophisticated, sane method
431 #if 0
432 template<typename T>
433 const char value<T>::round_error[] = "0";
434 #endif
435
436 #define SPECIALIZE_ROUND_ERROR(T, R) const char value< T >::round_error[] = #R
437 // unsophisticated, gross method
438 #if 1
439 SPECIALIZE_ROUND_ERROR(bool, 0);
440 SPECIALIZE_ROUND_ERROR(char, 0);
441 SPECIALIZE_ROUND_ERROR(unsigned char, 0);
442 SPECIALIZE_ROUND_ERROR(signed char, 0);
443 SPECIALIZE_ROUND_ERROR(wchar_t, 0);
444 SPECIALIZE_ROUND_ERROR(short, 0);
445 SPECIALIZE_ROUND_ERROR(unsigned short, 0);
446 SPECIALIZE_ROUND_ERROR(int, 0);
447 SPECIALIZE_ROUND_ERROR(unsigned int, 0);
448 SPECIALIZE_ROUND_ERROR(long, 0);
449 SPECIALIZE_ROUND_ERROR(unsigned long, 0);
450 SPECIALIZE_ROUND_ERROR(long long, 0);
451 SPECIALIZE_ROUND_ERROR(unsigned long long, 0);
452 #endif
453
454 SPECIALIZE_ROUND_ERROR(float, 1.0f);
455 SPECIALIZE_ROUND_ERROR(double, 1.0);
456 SPECIALIZE_ROUND_ERROR(long double, 1.0L);
457
458 #undef SPECIALIZE_ROUND_ERROR
459
460
461 template<typename T>
462 const int value<T>::min_exponent = 0;
463
464 template<typename T>
465 const int value<T>::min_exponent10 = 0;
466
467 template<typename T>
468 const int value<T>::max_exponent = 0;
469
470 template<typename T>
471 const int value<T>::max_exponent10 = 0;
472
473 #define SPECIALIZE_EXPONENTS(T, m, m10, M, M10)                         \
474 const int value< T >::min_exponent = m;                                 \
475 const int value< T >::min_exponent10 = m10;                             \
476 const int value< T >::max_exponent = M;                                 \
477 const int value< T >::max_exponent10 = M10
478
479 SPECIALIZE_EXPONENTS(float, FLT_MIN_EXP, FLT_MIN_10_EXP,
480                      FLT_MAX_EXP, FLT_MAX_10_EXP);
481 SPECIALIZE_EXPONENTS(double, DBL_MIN_EXP, DBL_MIN_10_EXP,
482                      DBL_MAX_EXP, DBL_MAX_10_EXP);
483 SPECIALIZE_EXPONENTS(long double, LDBL_MIN_EXP, LDBL_MIN_10_EXP,
484                      LDBL_MAX_EXP, LDBL_MAX_10_EXP);
485
486 #undef SPECIALIZE_EXPONENTS
487
488 //
489 // Functions to output predicates and values.
490 //
491
492 template<typename T> void is_signed()
493 {
494     printf("%s%s = %s;\n", tab2, "static const bool is_signed",
495            bool_alpha[predicate<T>::is_signed]);
496 }
497
498 // a fundamental type is modulo iff it isn't signed
499 template<typename T> void is_modulo()
500 {
501     printf("%s%s = %s;\n", tab2, "static const bool is_modulo",
502            bool_alpha[! predicate<T>::is_signed]);
503 }
504
505 template<typename T>
506 void min()
507 {
508     printf("%s%s%s%s\n%s%s%s%s\n", tab2, "static ", declarator<T>::type_name,
509            " min() throw()", tab2, "{ return ", value<T>::min, "; }");
510 }
511
512 template<typename T>
513 void max()
514 {
515     printf("%s%s%s%s\n%s%s%s%s\n", tab2, "static ", declarator<T>::type_name,
516            " max() throw()", tab2, "{ return ", value<T>::max, "; }");
517 }
518
519 template<typename T>
520 void is_integer()
521 {
522     printf("%s%s = %s;\n", tab2, "static const bool is_integer",
523            bool_alpha[predicate<T>::is_integer]);        
524 }
525
526 template<typename T>
527 void is_exact()
528 {
529     printf("%s%s = %s;\n", tab2, "static const bool is_exact",
530            bool_alpha[predicate<T>::is_exact]);    
531 }
532
533 template<typename T>
534 void digits()
535 {
536     printf("%s%s = %d;\n", tab2, "static const int digits",
537            value<T>::digits);
538 }
539
540 template<typename T>
541 void digits10()
542 {
543     printf("%s%s = %d;\n", tab2, "static const int digits10",
544            int(log10_of_two * value<T>::digits));
545 }
546
547 template<typename T>
548 void radix()
549 {
550     printf("%s%s = %d;\n", tab2, "static const int radix",
551            value<T>::radix);
552 }
553
554 template<typename T>
555 void epsilon()
556 {
557     printf("%s%s %s %s\n%s%s %s%s\n", tab2, "static",
558            declarator<T>::type_name, "epsilon() throw()",
559            tab2, "{ return", value<T>::epsilon, "; }");
560 }
561
562 template<typename T>
563 void round_error()
564 {
565     printf("%s%s %s %s\n%s%s %s%s\n", tab2, "static",
566            declarator<T>::type_name, "round_error() throw()",
567            tab2, "{ return", value<T>::round_error, "; }");
568 }
569
570 template<typename T>
571 void min_exponent()
572 {
573     printf("%s%s = %d;\n", tab2, "static const int min_exponent",
574            value<T>::min_exponent);    
575 }
576
577 template<typename T>
578 void min_exponent10()
579 {
580     printf("%s%s = %d;\n", tab2, "static const int min_exponent10",
581            value<T>::min_exponent10);    
582 }
583
584 template<typename T>
585 void max_exponent()
586 {
587     printf("%s%s = %d;\n", tab2, "static const int max_exponent",
588            value<T>::max_exponent);    
589 }
590
591 template<typename T>
592 void max_exponent10()
593 {
594     printf("%s%s = %d;\n", tab2, "static const int max_exponent10",
595            value<T>::max_exponent10);    
596 }
597
598 template<typename T>
599 void has_infinity()
600 {
601     printf("%s%s = %s;\n", tab2, "static const bool has_infinity",
602            bool_alpha[predicate<T>::has_infinity]);
603 }
604
605 template<typename T>
606 void has_quiet_nan()
607 {
608     printf("%s%s = %s;\n", tab2, "static const bool has_quiet_NaN",
609            bool_alpha[predicate<T>::has_quiet_nan]);
610 }
611
612 template<typename T>
613 void has_signaling_nan()
614 {
615     printf("%s%s = %s;\n", tab2, "static const bool has_signaling_NaN",
616            bool_alpha[predicate<T>::has_signaling_nan]);
617 }
618
619 template<typename T>
620 void has_denorm_loss()
621 {
622     printf("%s%s = %s;\n", tab2, "static const bool has_denorm_loss",
623            bool_alpha[predicate<T>::has_denorm_loss]);
624 }
625
626 template<typename T> struct infinity_trait {
627     static void has_denorm()
628     {
629         printf("%s%s;\n", tab2, "static const float_denorm_style "
630                "has_denorm = denorm_absent");
631     }
632
633     static void infinity()
634     {
635         printf("%s%s %s %s\n%s%s%s%s\n", tab2, "static",
636                declarator<T>::type_name, "infinity() throw()",
637                tab2, "{ return static_cast<", declarator<T>::type_name, 
638                ">(0); }");
639     }
640
641     static void quiet_NaN()
642     {
643         printf("%s%s %s %s\n%s%s%s%s\n", tab2, "static",
644                declarator<T>::type_name, "quiet_NaN() throw()",
645                tab2, "{ return static_cast<", declarator<T>::type_name, 
646                ">(0); }");
647     }
648
649     static void signaling_NaN()
650     {
651         printf("%s%s %s %s\n%s%s%s%s\n", tab2, "static",
652                declarator<T>::type_name, "signaling_NaN() throw()",
653                tab2, "{ return static_cast<", declarator<T>::type_name, 
654                ">(0); }");
655     }
656
657     static void denorm_min()
658     {
659         printf("%s%s %s %s\n%s%s%s%s\n", tab2, "static",
660                declarator<T>::type_name, "denorm_min() throw()",
661                tab2, "{ return static_cast<", declarator<T>::type_name, 
662                ">(0); }");
663     }
664 };
665
666
667 template<typename T>
668 void is_iec559()
669 {
670     printf("%s%s = %s;\n", tab2, "static const bool is_iec559",
671            bool_alpha[predicate<T>::is_iec559]);
672 }
673
674 // tinyness_before
675 template<typename T>
676 void tinyness_before()
677 {
678     printf("%s%s;\n", tab2, "static const bool tinyness_before = false");
679 }
680
681 // round style
682 template<typename T>
683 void round_style()
684 {
685     printf("%s%s;\n", tab2, "static const float_round_style "
686            "round_style = round_toward_zero");    
687 }
688
689
690
691 // type traits
692 template<typename T> struct type_trait {
693     
694     type_trait()
695     {
696         declarator<T>::start();
697         printf("%s%s;\n\n", tab2, "static const bool is_specialized = true");
698         min<T>();
699         max<T>();
700         printf("\n");
701         digits<T>();
702         digits10<T>();
703         is_signed<T>();
704         is_integer<T>();
705         is_exact<T>();
706         radix<T>();
707         epsilon<T>();
708         round_error<T>();
709         printf("\n");
710         min_exponent<T>();
711         min_exponent10<T>();
712         max_exponent<T>();
713         max_exponent10<T>();
714         printf("\n");
715         has_infinity<T>();
716         has_quiet_nan<T>();
717         has_signaling_nan<T>();
718         infinity_trait<T>::has_denorm();
719         has_denorm_loss<T>();
720         printf("\n");
721         infinity_trait<T>::infinity();
722         infinity_trait<T>::quiet_NaN();
723         infinity_trait<T>::signaling_NaN();
724         infinity_trait<T>::denorm_min();
725         printf("\n");
726         is_iec559<T>();
727         printf("%s%s;\n", tab2, "static const bool is_bounded = true");
728         is_modulo<T>();
729         printf("\n");
730         traps<T>();
731         tinyness_before<T>();
732         round_style<T>();
733         declarator<T>::end();
734     }
735 };
736
737 int main()
738 {
739     type_trait<bool>();
740
741     type_trait<char>();
742     type_trait<signed char>();
743     type_trait<unsigned char>();
744 #if defined( _GLIBCPP_USE_WCHAR_T) 
745     type_trait<wchar_t>();
746 #endif
747     
748     type_trait<short>();
749     type_trait<unsigned short>();
750
751     type_trait<int>();
752     type_trait<unsigned int>();
753
754     type_trait<long>();
755     type_trait<unsigned long>();
756
757 #ifdef _GLIBCPP_USE_LONG_LONG
758     type_trait<long long>();
759     type_trait<unsigned long long>();
760 #endif
761
762     type_trait<float>();
763     type_trait<double>();
764     type_trait<long double>();
765
766     // x86/linux gets this weirdness for the min/max functions:
767     // static long double min() throw()
768     // { return (__extension__ ((union __convert_long_double) 
769     // {__convert_long_double_i: {0x0, 0x80000000, 0x1, 0x0}})
770     // .__convert_long_double_d); }
771 }
772
773 // G++ doesn't have support for automatic instantiation of static data
774 // members on platforms that don't have weak symbols.  On AIX, in
775 // particular, static data members must be explicitly instantiated.
776 // So, we explicitly instantiate some of the ones we need.  To save
777 // typing, we don't name the static data members explicitly; we
778 // instead name their containing types.
779
780 #define INSTANTIATIONS(TYPE)                    \
781   template struct predicate<TYPE>;              \
782   template struct value<TYPE>
783
784 INSTANTIATIONS (bool);
785 INSTANTIATIONS (char);
786 INSTANTIATIONS (signed char);
787 INSTANTIATIONS (unsigned char);
788 INSTANTIATIONS (short);
789 INSTANTIATIONS (unsigned short);
790 INSTANTIATIONS (int);
791 INSTANTIATIONS (unsigned int);
792 INSTANTIATIONS (long);
793 INSTANTIATIONS (unsigned long);
794 INSTANTIATIONS (float);
795 INSTANTIATIONS (double);
796 INSTANTIATIONS (long double);
797