source: Sophya/trunk/SophyaExt/Blitz/blitz/promote.h@ 3188

Last change on this file since 3188 was 221, checked in by ansari, 26 years ago

Creation module DPC/Blitz (blitz 0.4) Reza 09/04/99

File size: 4.9 KB
Line 
1/***********************************************************************
2 * promote.h Arithmetic type promotion trait class
3 * Author: Todd Veldhuizen (tveldhui@seurat.uwaterloo.ca)
4 *
5 * Copyright (C) 1997,1998 Todd Veldhuizen <tveldhui@seurat.uwaterloo.ca>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * Suggestions: blitz-suggest@cybervision.com
18 * Bugs: blitz-bugs@cybervision.com
19 *
20 * For more information, please see the Blitz++ Home Page:
21 * http://seurat.uwaterloo.ca/blitz/
22 *
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_TEMPLATE_QUALIFIED_RETURN_TYPE
34 #define BZ_PROMOTE(A,B) _bz_typename promote_trait<A,B>::T_promote
35#else
36 #define BZ_PROMOTE(A,B) A
37#endif
38
39#if defined(BZ_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<class T>
48struct precision_trait {
49 enum { precisionRank = 0,
50 knowPrecisionRank = 0 };
51};
52
53#define BZ_DECLARE_PRECISION(T,rank) \
54 template<> \
55 struct precision_trait<T> { \
56 enum { precisionRank = rank, \
57 knowPrecisionRank = 1 }; \
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<class 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<class T1, class T2, int promoteToT1>
95struct _bz_promote2 {
96 typedef T1 T_promote;
97};
98
99template<class T1, class T2>
100struct _bz_promote2<T1,T2,0> {
101 typedef T2 T_promote;
102};
103
104template<class T1_orig, class 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 enum {
112 T1IsBetter =
113 BZ_ENUM_CAST(precision_trait<T1>::precisionRank) >
114 BZ_ENUM_CAST(precision_trait<T2>::precisionRank),
115
116 // True if we know ranks for both T1 and T2
117 knowBothRanks =
118 BZ_ENUM_CAST(precision_trait<T1>::knowPrecisionRank)
119 && BZ_ENUM_CAST(precision_trait<T2>::knowPrecisionRank),
120
121 // True if we know T1 but not T2
122 knowT1butNotT2 = BZ_ENUM_CAST(precision_trait<T1>::knowPrecisionRank)
123 && !(BZ_ENUM_CAST(precision_trait<T2>::knowPrecisionRank)),
124
125 // True if we know T2 but not T1
126 knowT2butNotT1 = BZ_ENUM_CAST(precision_trait<T2>::knowPrecisionRank)
127 && !(BZ_ENUM_CAST(precision_trait<T1>::knowPrecisionRank)),
128
129 // True if T1 is bigger than T2
130 T1IsLarger = sizeof(T1) >= sizeof(T2),
131
132 // We know T1 but not T2: true
133 // We know T2 but not T1: false
134 // Otherwise, if T1 is bigger than T2: true
135 defaultPromotion = knowT1butNotT2 ? _bz_false :
136 (knowT2butNotT1 ? _bz_true : T1IsLarger)
137 };
138
139 // If we have both ranks, then use them.
140 // If we have only one rank, then use the unknown type.
141 // If we have neither rank, then promote to the larger type.
142
143 enum {
144 promoteToT1 = (BZ_ENUM_CAST(knowBothRanks) ? BZ_ENUM_CAST(T1IsBetter)
145 : BZ_ENUM_CAST(defaultPromotion)) ? 1 : 0
146 };
147
148 typedef typename _bz_promote2<T1,T2,promoteToT1>::T_promote T_promote;
149};
150
151#else // !BZ_PARTIAL_SPECIALIZATION
152
153 // No partial specialization -- have to do it the ugly way.
154 #include <blitz/promote-old.h>
155
156#endif // !BZ_PARTIAL_SPECIALIZATION
157
158BZ_NAMESPACE_END
159
160#endif // BZ_PROMOTE_H
Note: See TracBrowser for help on using the repository browser.