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