aboutsummaryrefslogtreecommitdiffhomepage
path: root/tvmet-1.7.1/include/tvmet/TypePromotion.h
blob: 06c6b4ee7a2653ed2ca6d6169872529a3cfc0041 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
/*
 * Tiny Vector Matrix Library
 * Dense Vector Matrix Libary of Tiny size using Expression Templates
 *
 * Copyright (C) 2001 - 2003 Olaf Petzold <opetzold@users.sourceforge.net>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * $Id: TypePromotion.h,v 1.6 2003/11/30 08:26:25 opetzold Exp $
 */

#ifndef TVMET_TYPE_PROMOTION_H
#define TVMET_TYPE_PROMOTION_H

namespace tvmet {


/**
 * \class PrecisionTraits TypePromotion.h "tvmet/TypePromotion.h"
 * \brief Declaring ranks of types to avoid specializing
 *
 * All possible promoted types. For example, bool=1, int=2, float=3, double=4,
 * etc. We can use a traits class to map from a type such as float onto its
 * "precision rank". We will promote to whichever type has a higher
 * "precision rank". f there is no "precision rank" for a type, we'll
 * promote to whichever type requires more storage space
 * (and hopefully more precision).
 */
template<class T>
struct PrecisionTraits {
  enum {
    rank = 0,			/**< the rank of type. */
    known = 0 			/**< true, if the rank is specialized = known. */
  };
};


#define TVMET_PRECISION(T,R)      					\
template<>                          					\
struct PrecisionTraits< T > {        					\
  enum {                          					\
    rank = R,                   					\
    known = 1                   					\
  };                              					\
};


/*
 * pod types
 */
TVMET_PRECISION(int, 100)
TVMET_PRECISION(float, 700)
TVMET_PRECISION(double, 800)

/*
 * complex types
 */
#if defined(TVMET_HAVE_COMPLEX)
TVMET_PRECISION(std::complex<int>, 1000)
TVMET_PRECISION(std::complex<float>, 1600)
TVMET_PRECISION(std::complex<double>, 1700)
#endif // defined(TVMET_HAVE_COMPLEX)


/** \class PrecisionTraits<int>				TypePromotion.h "tvmet/TypePromotion.h" */
/** \class PrecisionTraits<unsigned int> 		TypePromotion.h "tvmet/TypePromotion.h" */
/** \class PrecisionTraits<long>			TypePromotion.h "tvmet/TypePromotion.h" */
/** \class PrecisionTraits<unsigned long> 		TypePromotion.h "tvmet/TypePromotion.h" */
/** \class PrecisionTraits<long long>			TypePromotion.h "tvmet/TypePromotion.h" */
/** \class PrecisionTraits<unsigned long long> 		TypePromotion.h "tvmet/TypePromotion.h" */
/** \class PrecisionTraits<float>			TypePromotion.h "tvmet/TypePromotion.h" */
/** \class PrecisionTraits<double>			TypePromotion.h "tvmet/TypePromotion.h" */
/** \class PrecisionTraits<long double>			TypePromotion.h "tvmet/TypePromotion.h" */
/** \class PrecisionTraits< std::complex<int> >		TypePromotion.h "tvmet/TypePromotion.h" */
/** \class PrecisionTraits< std::complex<unsigned int> > TypePromotion.h "tvmet/TypePromotion.h" */
/** \class PrecisionTraits< std::complex<long> >	TypePromotion.h "tvmet/TypePromotion.h" */
/** \class PrecisionTraits< std::complex<unsigned long> > TypePromotion.h "tvmet/TypePromotion.h" */
/** \class PrecisionTraits< std::complex<long long> >	TypePromotion.h "tvmet/TypePromotion.h" */
/** \class PrecisionTraits< std::complex<unsigned long long> > TypePromotion.h "tvmet/TypePromotion.h" */
/** \class PrecisionTraits< std::complex<float> >	TypePromotion.h "tvmet/TypePromotion.h" */
/** \class PrecisionTraits< std::complex<double> >	TypePromotion.h "tvmet/TypePromotion.h" */
/** \class PrecisionTraits< std::complex<long double> >	TypePromotion.h "tvmet/TypePromotion.h" */

#undef TVMET_PRECISION


/**
 * \class AutopromoteTraits TypePromotion.h "tvmet/TypePromotion.h"
 * \brief The promoted types traits.
 */
template<class T>
struct AutopromoteTraits {
  typedef T value_type;
};

/**
 * \class promoteTo TypePromotion.h "tvmet/TypePromotion.h"
 * \brief Promote to T1.
 */
template<class T1, class T2, int promoteToT1>
struct promoteTo {
  typedef T1 value_type;
};


/**
 * \class promoteTo<T1,T2,0> TypePromotion.h "tvmet/TypePromotion.h"
 * \brief Promote to T2
 */
template<class T1, class T2>
struct promoteTo<T1,T2,0> {
  typedef T2 value_type;
};


/**
 * \class PromoteTraits TypePromotion.h "tvmet/TypePromotion.h"
 * \brief Promote type traits
 */
template<class T1org, class T2org>
class PromoteTraits {
  // Handle promotion of small integers to int/unsigned int
  typedef typename AutopromoteTraits<T1org>::value_type T1;
  typedef typename AutopromoteTraits<T2org>::value_type T2;

  enum {
    // True if T1 is higher ranked
    T1IsBetter = int(PrecisionTraits<T1>::rank) > int(PrecisionTraits<T2>::rank),

    // True if we know ranks for both T1 and T2
    knowBothRanks = PrecisionTraits<T1>::known && PrecisionTraits<T2>::known,

    // True if we know T1 but not T2
    knowT1butNotT2 = PrecisionTraits<T1>::known && !(PrecisionTraits<T2>::known),

    // True if we know T2 but not T1
    knowT2butNotT1 =  PrecisionTraits<T2>::known && !(PrecisionTraits<T1>::known),

    // True if T1 is bigger than T2
    T1IsLarger = sizeof(T1) >= sizeof(T2),

    // We know T1 but not T2: true
    // We know T2 but not T1: false
    // Otherwise, if T1 is bigger than T2: true
    defaultPromotion = knowT1butNotT2 ? false : (knowT2butNotT1 ? true : T1IsLarger),

    // If we have both ranks, then use them.
    // If we have only one rank, then use the unknown type.
    // If we have neither rank, then promote to the larger type.
    promoteToT1 = (knowBothRanks ? T1IsBetter : defaultPromotion) ? 1 : 0
  };

 public:
  typedef typename promoteTo<T1,T2,promoteToT1>::value_type value_type;
};


} // namespace tvmet

#endif // TVMET_TYPE_PROMOTION_H

// Local Variables:
// mode:C++
// End: