source: XMLIO_V2/external/include/blitz/promote.h @ 73

Last change on this file since 73 was 73, checked in by ymipsl, 14 years ago
  • Property svn:eol-style set to native
File size: 5.2 KB
Line 
1// -*- C++ -*-
2/***********************************************************************
3 * promote.h   Arithmetic type promotion trait class
4 * Author: Todd Veldhuizen         (tveldhui@oonumerics.org)
5 *
6 * Copyright (C) 1997-2001 Todd Veldhuizen <tveldhui@oonumerics.org>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU General Public License for more details.
17 *
18 * Suggestions:          blitz-dev@oonumerics.org
19 * Bugs:                 blitz-bugs@oonumerics.org
20 *
21 * For more information, please see the Blitz++ Home Page:
22 *    http://oonumerics.org/blitz/
23 *
24 ***************************************************************************/
25
26#ifndef BZ_PROMOTE_H
27#define BZ_PROMOTE_H
28
29#include <blitz/blitz.h>
30
31BZ_NAMESPACE(blitz)
32
33#ifdef BZ_HAVE_TEMPLATE_QUALIFIED_RETURN_TYPE
34    #define BZ_PROMOTE(A,B) _bz_typename BZ_BLITZ_SCOPE(promote_trait)<A,B>::T_promote
35#else
36    #define BZ_PROMOTE(A,B) A
37#endif
38
39#if defined(BZ_HAVE_PARTIAL_SPECIALIZATION) && !defined(BZ_DISABLE_NEW_PROMOTE)
40
41/*
42 * This compiler supports partial specialization, so type promotion
43 * can be done the elegant way.  This implementation is after ideas
44 * by Jean-Louis Leroy.
45 */
46
47template<typename T>
48struct precision_trait {
49    static const int precisionRank = 0;
50    static const bool knowPrecisionRank = false;
51};
52
53#define BZ_DECLARE_PRECISION(T,rank)                  \
54    template<>                                        \
55    struct precision_trait< T > {                     \
56        static const int precisionRank = rank;        \
57        static const bool knowPrecisionRank = true;   \
58    };
59
60BZ_DECLARE_PRECISION(int,100)
61BZ_DECLARE_PRECISION(unsigned int,200)
62BZ_DECLARE_PRECISION(long,300)
63BZ_DECLARE_PRECISION(unsigned long,400)
64BZ_DECLARE_PRECISION(float,500)
65BZ_DECLARE_PRECISION(double,600)
66BZ_DECLARE_PRECISION(long double,700)
67
68#ifdef BZ_HAVE_COMPLEX
69BZ_DECLARE_PRECISION(complex<float>,800)
70BZ_DECLARE_PRECISION(complex<double>,900)
71BZ_DECLARE_PRECISION(complex<long double>,1000)
72#endif
73
74template<typename T>
75struct autopromote_trait {
76    typedef T T_numtype;
77};
78
79#define BZ_DECLARE_AUTOPROMOTE(T1,T2)     \
80    template<>                            \
81    struct autopromote_trait<T1> {        \
82      typedef T2 T_numtype;               \
83    };
84
85// These are the odd cases where small integer types
86// are automatically promoted to int or unsigned int for
87// arithmetic.
88BZ_DECLARE_AUTOPROMOTE(bool, int)
89BZ_DECLARE_AUTOPROMOTE(char, int)
90BZ_DECLARE_AUTOPROMOTE(unsigned char, int)
91BZ_DECLARE_AUTOPROMOTE(short int, int)
92BZ_DECLARE_AUTOPROMOTE(short unsigned int, unsigned int)
93
94template<typename T1, typename T2, bool promoteToT1>
95struct _bz_promote2 {
96    typedef T1 T_promote;
97};
98
99template<typename T1, typename T2>
100struct _bz_promote2<T1,T2,false> {
101    typedef T2 T_promote;
102};
103
104template<typename T1_orig, typename T2_orig>
105struct promote_trait {
106    // Handle promotion of small integers to int/unsigned int
107    typedef _bz_typename autopromote_trait<T1_orig>::T_numtype T1;
108    typedef _bz_typename autopromote_trait<T2_orig>::T_numtype T2;
109
110    // True if T1 is higher ranked
111    static const bool
112        T1IsBetter =
113            precision_trait<T1>::precisionRank >
114            precision_trait<T2>::precisionRank;
115
116    // True if we know ranks for both T1 and T2
117    static const bool
118        knowBothRanks =
119            precision_trait<T1>::knowPrecisionRank && 
120            precision_trait<T2>::knowPrecisionRank;
121
122    // True if we know T1 but not T2
123    static const bool
124        knowT1butNotT2 = 
125            precision_trait<T1>::knowPrecisionRank && 
126            !precision_trait<T2>::knowPrecisionRank;
127
128    // True if we know T2 but not T1
129    static const bool
130        knowT2butNotT1 = 
131            precision_trait<T2>::knowPrecisionRank && 
132            !precision_trait<T1>::knowPrecisionRank;
133
134    // True if T1 is bigger than T2
135    static const bool
136        T1IsLarger = sizeof(T1) >= sizeof(T2);
137
138    // We know T1 but not T2: false
139    // We know T2 but not T1: true
140    // Otherwise, if T1 is bigger than T2: true
141//     static const bool
142//         defaultPromotion = knowT1butNotT2 ? false :
143//             (knowT2butNotT1 ? true : T1IsLarger);
144
145    // If we have both ranks, then use them.
146    // If we have only one rank, then use the unknown type.
147    // If we have neither rank, then promote to the larger type.
148    static const bool
149        promoteToT1 = knowBothRanks ? T1IsBetter : (knowT1butNotT2 ? false : 
150            (knowT2butNotT1 ? true : T1IsLarger));
151//     static const bool
152//         promoteToT1 = knowBothRanks ? T1IsBetter : defaultPromotion;
153
154    typedef _bz_typename _bz_promote2<T1,T2,promoteToT1>::T_promote T_promote;
155};
156
157#else  // !BZ_HAVE_PARTIAL_SPECIALIZATION
158
159  // No partial specialization -- have to do it the ugly way.
160  #include <blitz/promote-old.h>
161
162#endif // !BZ_HAVE_PARTIAL_SPECIALIZATION
163
164BZ_NAMESPACE_END
165
166#endif // BZ_PROMOTE_H
Note: See TracBrowser for help on using the repository browser.