• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2015 Benoit Steiner <benoit.steiner.goog@gmail.com>
5 //
6 // This Source Code Form is subject to the terms of the Mozilla
7 // Public License v. 2.0. If a copy of the MPL was not distributed
8 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 
10 #ifndef CXX11_SRC_FIXEDPOINT_FIXEDPOINTTYPES_H_
11 #define CXX11_SRC_FIXEDPOINT_FIXEDPOINTTYPES_H_
12 
13 #include <cmath>
14 #include <iostream>
15 
16 namespace Eigen {
17 
18 // The mantissa part of the fixed point representation. See
19 // go/tensorfixedpoint for details
20 struct QInt8;
21 struct QUInt8;
22 struct QInt16;
23 struct QUInt16;
24 struct QInt32;
25 
26 template <>
27 struct NumTraits<QInt8> : GenericNumTraits<int8_t> {};
28 template <>
29 struct NumTraits<QUInt8> : GenericNumTraits<uint8_t> {};
30 template <>
31 struct NumTraits<QInt16> : GenericNumTraits<int16_t> {};
32 template <>
33 struct NumTraits<QUInt16> : GenericNumTraits<uint16_t> {};
34 template <>
35 struct NumTraits<QInt32> : GenericNumTraits<int32_t> {};
36 
37 namespace internal {
38 template <>
39 struct scalar_product_traits<QInt32, double> {
40   enum {
41     // Cost = NumTraits<T>::MulCost,
42     Defined = 1
43   };
44   typedef QInt32 ReturnType;
45 };
46 }
47 
48 // Wrap the 8bit int into a QInt8 struct instead of using a typedef to prevent
49 // the compiler from silently type cast the mantissa into a bigger or a smaller
50 // representation.
51 struct QInt8 {
52   QInt8() : value(0) {}
53   QInt8(const int8_t v) : value(v) {}
54   QInt8(const QInt32 v);
55 
56   operator int() const { return static_cast<int>(value); }
57 
58   int8_t value;
59 };
60 
61 struct QUInt8 {
62   QUInt8() : value(0) {}
63   QUInt8(const uint8_t v) : value(v) {}
64   QUInt8(const QInt32 v);
65 
66   operator int() const { return static_cast<int>(value); }
67 
68   uint8_t value;
69 };
70 
71 struct QInt16 {
72   QInt16() : value(0) {}
73   QInt16(const int16_t v) : value(v) {}
74   QInt16(const QInt32 v);
75   operator int() const { return static_cast<int>(value); }
76 
77   int16_t value;
78 };
79 
80 struct QUInt16 {
81   QUInt16() : value(0) {}
82   QUInt16(const uint16_t v) : value(v) {}
83   QUInt16(const QInt32 v);
84   operator int() const { return static_cast<int>(value); }
85 
86   uint16_t value;
87 };
88 
89 struct QInt32 {
90   QInt32() : value(0) {}
91   QInt32(const int8_t v) : value(v) {}
92   QInt32(const int32_t v) : value(v) {}
93   QInt32(const uint32_t v) : value(static_cast<int32_t>(v)) {}
94   QInt32(const QInt8 v) : value(v.value) {}
95   QInt32(const float v) : value(static_cast<int32_t>(lrint(v))) {}
96 #ifdef EIGEN_MAKING_DOCS
97   // Workaround to fix build on PPC.
98   QInt32(unsigned long v) : value(v) {}
99 #endif
100 
101   operator float() const { return static_cast<float>(value); }
102 
103   int32_t value;
104 };
105 
106 EIGEN_STRONG_INLINE QInt8::QInt8(const QInt32 v)
107     : value(v.value > 127 ? 127 : (v.value < -128 ? -128 : v.value)) {}
108 EIGEN_STRONG_INLINE QUInt8::QUInt8(const QInt32 v)
109     : value(v.value > 255 ? 255 : (v.value < 0 ? 0 : v.value)) {}
110 EIGEN_STRONG_INLINE QInt16::QInt16(const QInt32 v)
111     : value(v.value > 32767 ? 32767 : (v.value < -32768 ? -32768 : v.value)) {}
112 EIGEN_STRONG_INLINE QUInt16::QUInt16(const QInt32 v)
113     : value(v.value > 65535 ? 65535 : (v.value < 0 ? 0 : v.value)) {}
114 
115 // Basic widening 8-bit operations: This will be vectorized in future CLs.
116 EIGEN_STRONG_INLINE QInt32 operator*(const QInt8 a, const QInt8 b) {
117   return QInt32(static_cast<int32_t>(a.value) * static_cast<int32_t>(b.value));
118 }
119 EIGEN_STRONG_INLINE QInt32 operator*(const QInt8 a, const QUInt8 b) {
120   return QInt32(static_cast<int32_t>(a.value) * static_cast<int32_t>(b.value));
121 }
122 EIGEN_STRONG_INLINE QInt32 operator+(const QInt8 a, const QInt8 b) {
123   return QInt32(static_cast<int32_t>(a.value) + static_cast<int32_t>(b.value));
124 }
125 EIGEN_STRONG_INLINE QInt32 operator-(const QInt8 a, const QInt8 b) {
126   return QInt32(static_cast<int32_t>(a.value) - static_cast<int32_t>(b.value));
127 }
128 
129 // Basic widening 16-bit operations: This will be vectorized in future CLs.
130 EIGEN_STRONG_INLINE QInt32 operator*(const QInt16 a, const QInt16 b) {
131   return QInt32(static_cast<int32_t>(a.value) * static_cast<int32_t>(b.value));
132 }
133 EIGEN_STRONG_INLINE QInt32 operator*(const QInt16 a, const QUInt16 b) {
134   return QInt32(static_cast<int32_t>(a.value) * static_cast<int32_t>(b.value));
135 }
136 EIGEN_STRONG_INLINE QInt32 operator+(const QInt16 a, const QInt16 b) {
137   return QInt32(static_cast<int32_t>(a.value) + static_cast<int32_t>(b.value));
138 }
139 EIGEN_STRONG_INLINE QInt32 operator-(const QInt16 a, const QInt16 b) {
140   return QInt32(static_cast<int32_t>(a.value) - static_cast<int32_t>(b.value));
141 }
142 
143 // Mixed QInt32 op QInt8 operations. This will be vectorized in future CLs.
144 EIGEN_STRONG_INLINE QInt32 operator+(const QInt32 a, const QInt8 b) {
145   return QInt32(a.value + static_cast<int32_t>(b.value));
146 }
147 EIGEN_STRONG_INLINE QInt32 operator+(const QInt8 a, const QInt32 b) {
148   return QInt32(static_cast<int32_t>(a.value) + b.value);
149 }
150 EIGEN_STRONG_INLINE QInt32 operator-(const QInt32 a, const QInt8 b) {
151   return QInt32(a.value - static_cast<int32_t>(b.value));
152 }
153 EIGEN_STRONG_INLINE QInt32 operator-(const QInt8 a, const QInt32 b) {
154   return QInt32(static_cast<int32_t>(a.value) - b.value);
155 }
156 EIGEN_STRONG_INLINE QInt32 operator*(const QInt32 a, const QInt8 b) {
157   return QInt32(a.value * static_cast<int32_t>(b.value));
158 }
159 EIGEN_STRONG_INLINE QInt32 operator*(const QInt8 a, const QInt32 b) {
160   return QInt32(static_cast<int32_t>(a.value) * b.value);
161 }
162 
163 // Mixed QInt32 op QInt16 operations. This will be vectorized in future CLs.
164 EIGEN_STRONG_INLINE QInt32 operator+(const QInt32 a, const QInt16 b) {
165   return QInt32(a.value + static_cast<int32_t>(b.value));
166 }
167 EIGEN_STRONG_INLINE QInt32 operator+(const QInt16 a, const QInt32 b) {
168   return QInt32(static_cast<int32_t>(a.value) + b.value);
169 }
170 EIGEN_STRONG_INLINE QInt32 operator-(const QInt32 a, const QInt16 b) {
171   return QInt32(a.value - static_cast<int32_t>(b.value));
172 }
173 EIGEN_STRONG_INLINE QInt32 operator-(const QInt16 a, const QInt32 b) {
174   return QInt32(static_cast<int32_t>(a.value) - b.value);
175 }
176 EIGEN_STRONG_INLINE QInt32 operator*(const QInt32 a, const QInt16 b) {
177   return QInt32(a.value * static_cast<int32_t>(b.value));
178 }
179 EIGEN_STRONG_INLINE QInt32 operator*(const QInt16 a, const QInt32 b) {
180   return QInt32(static_cast<int32_t>(a.value) * b.value);
181 }
182 
183 // Mixed QInt32 op QUInt8 operations. This will be vectorized in future CLs.
184 EIGEN_STRONG_INLINE QInt32 operator+(const QInt32 a, const QUInt8 b) {
185   return QInt32(a.value + static_cast<int32_t>(b.value));
186 }
187 EIGEN_STRONG_INLINE QInt32 operator+(const QUInt8 a, const QInt32 b) {
188   return QInt32(static_cast<int32_t>(a.value) + b.value);
189 }
190 EIGEN_STRONG_INLINE QInt32 operator-(const QInt32 a, const QUInt8 b) {
191   return QInt32(a.value - static_cast<int32_t>(b.value));
192 }
193 EIGEN_STRONG_INLINE QInt32 operator-(const QUInt8 a, const QInt32 b) {
194   return QInt32(static_cast<int32_t>(a.value) - b.value);
195 }
196 EIGEN_STRONG_INLINE QInt32 operator*(const QInt32 a, const QUInt8 b) {
197   return QInt32(a.value * static_cast<int32_t>(b.value));
198 }
199 EIGEN_STRONG_INLINE QInt32 operator*(const QUInt8 a, const QInt32 b) {
200   return QInt32(static_cast<int32_t>(a.value) * b.value);
201 }
202 
203 // Mixed QInt32 op QUInt16 operations. This will be vectorized in future CLs.
204 EIGEN_STRONG_INLINE QInt32 operator+(const QInt32 a, const QUInt16 b) {
205   return QInt32(a.value + static_cast<int32_t>(b.value));
206 }
207 EIGEN_STRONG_INLINE QInt32 operator+(const QUInt16 a, const QInt32 b) {
208   return QInt32(static_cast<int32_t>(a.value) + b.value);
209 }
210 EIGEN_STRONG_INLINE QInt32 operator-(const QInt32 a, const QUInt16 b) {
211   return QInt32(a.value - static_cast<int32_t>(b.value));
212 }
213 EIGEN_STRONG_INLINE QInt32 operator-(const QUInt16 a, const QInt32 b) {
214   return QInt32(static_cast<int32_t>(a.value) - b.value);
215 }
216 EIGEN_STRONG_INLINE QInt32 operator*(const QInt32 a, const QUInt16 b) {
217   return QInt32(a.value * static_cast<int32_t>(b.value));
218 }
219 EIGEN_STRONG_INLINE QInt32 operator*(const QUInt16 a, const QInt32 b) {
220   return QInt32(static_cast<int32_t>(a.value) * b.value);
221 }
222 
223 // Basic arithmetic operations on QInt32, which behaves like a int32_t.
224 EIGEN_STRONG_INLINE QInt32 operator+(const QInt32 a, const QInt32 b) {
225   return a.value + b.value;
226 }
227 EIGEN_STRONG_INLINE QInt32 operator-(const QInt32 a, const QInt32 b) {
228   return a.value - b.value;
229 }
230 EIGEN_STRONG_INLINE QInt32 operator*(const QInt32 a, const QInt32 b) {
231   return a.value * b.value;
232 }
233 EIGEN_STRONG_INLINE QInt32 operator/(const QInt32 a, const QInt32 b) {
234   return a.value / b.value;
235 }
236 EIGEN_STRONG_INLINE QInt32& operator+=(QInt32& a, const QInt32 b) {
237   a.value += b.value;
238   return a;
239 }
240 EIGEN_STRONG_INLINE QInt32& operator-=(QInt32& a, const QInt32 b) {
241   a.value -= b.value;
242   return a;
243 }
244 EIGEN_STRONG_INLINE QInt32& operator*=(QInt32& a, const QInt32 b) {
245   a.value *= b.value;
246   return a;
247 }
248 EIGEN_STRONG_INLINE QInt32& operator/=(QInt32& a, const QInt32 b) {
249   a.value /= b.value;
250   return a;
251 }
252 EIGEN_STRONG_INLINE QInt32 operator-(const QInt32 a) { return -a.value; }
253 
254 // Scaling QInt32 by double. We do the arithmetic in double because
255 // float only has 23 bits of mantissa, so casting QInt32 to float might reduce
256 // accuracy by discarding up to 7 (least significant) bits.
257 EIGEN_STRONG_INLINE QInt32 operator*(const QInt32 a, const double b) {
258   return static_cast<int32_t>(lrint(static_cast<double>(a.value) * b));
259 }
260 EIGEN_STRONG_INLINE QInt32 operator*(const double a, const QInt32 b) {
261   return static_cast<int32_t>(lrint(a * static_cast<double>(b.value)));
262 }
263 EIGEN_STRONG_INLINE QInt32& operator*=(QInt32& a, const double b) {
264   a.value = static_cast<int32_t>(lrint(static_cast<double>(a.value) * b));
265   return a;
266 }
267 
268 // Comparisons
269 EIGEN_STRONG_INLINE bool operator==(const QInt8 a, const QInt8 b) {
270   return a.value == b.value;
271 }
272 EIGEN_STRONG_INLINE bool operator==(const QUInt8 a, const QUInt8 b) {
273   return a.value == b.value;
274 }
275 EIGEN_STRONG_INLINE bool operator==(const QInt16 a, const QInt16 b) {
276   return a.value == b.value;
277 }
278 EIGEN_STRONG_INLINE bool operator==(const QUInt16 a, const QUInt16 b) {
279   return a.value == b.value;
280 }
281 EIGEN_STRONG_INLINE bool operator==(const QInt32 a, const QInt32 b) {
282   return a.value == b.value;
283 }
284 
285 EIGEN_STRONG_INLINE bool operator<(const QInt8 a, const QInt8 b) {
286   return a.value < b.value;
287 }
288 EIGEN_STRONG_INLINE bool operator<(const QUInt8 a, const QUInt8 b) {
289   return a.value < b.value;
290 }
291 EIGEN_STRONG_INLINE bool operator<(const QInt16 a, const QInt16 b) {
292   return a.value < b.value;
293 }
294 EIGEN_STRONG_INLINE bool operator<(const QUInt16 a, const QUInt16 b) {
295   return a.value < b.value;
296 }
297 EIGEN_STRONG_INLINE bool operator<(const QInt32 a, const QInt32 b) {
298   return a.value < b.value;
299 }
300 
301 EIGEN_STRONG_INLINE bool operator>(const QInt8 a, const QInt8 b) {
302   return a.value > b.value;
303 }
304 EIGEN_STRONG_INLINE bool operator>(const QUInt8 a, const QUInt8 b) {
305   return a.value > b.value;
306 }
307 EIGEN_STRONG_INLINE bool operator>(const QInt16 a, const QInt16 b) {
308   return a.value > b.value;
309 }
310 EIGEN_STRONG_INLINE bool operator>(const QUInt16 a, const QUInt16 b) {
311   return a.value > b.value;
312 }
313 EIGEN_STRONG_INLINE bool operator>(const QInt32 a, const QInt32 b) {
314   return a.value > b.value;
315 }
316 
317 EIGEN_STRONG_INLINE std::ostream& operator<<(std::ostream& os, QInt8 a) {
318   os << static_cast<int>(a.value);
319   return os;
320 }
321 EIGEN_STRONG_INLINE std::ostream& operator<<(std::ostream& os, QUInt8 a) {
322   os << static_cast<int>(a.value);
323   return os;
324 }
325 EIGEN_STRONG_INLINE std::ostream& operator<<(std::ostream& os, QInt16 a) {
326   os << static_cast<int>(a.value);
327   return os;
328 }
329 EIGEN_STRONG_INLINE std::ostream& operator<<(std::ostream& os, QUInt16 a) {
330   os << static_cast<int>(a.value);
331   return os;
332 }
333 EIGEN_STRONG_INLINE std::ostream& operator<<(std::ostream& os, QInt32 a) {
334   os << a.value;
335   return os;
336 }
337 
338 }  // namespace Eigen
339 
340 #endif  // CXX11_SRC_FIXEDPOINT_FIXEDPOINTTYPES_H_
341