Poplar and PopLibs
HalfFloat.hpp
1// Copyright (c) 2015 Graphcore Ltd. All rights reserved.
2
3#ifndef poplar_HalfFloat_hpp_
4#define poplar_HalfFloat_hpp_
5
6#ifdef __IPU__
7
8#include <ipudef.h>
9
10#else
11
12#include <poplar/IeeeHalf.hpp>
13#include <type_traits>
14
15namespace poplar {
16
17template <typename T> class HalfFloatType {
18private:
19 T data;
20
21public:
22 HalfFloatType(float val) : data(val) {
23 static_assert(std::is_standard_layout<HalfFloatType>::value,
24 "Invalid HalfFloatType class layout");
25 }
26
27 HalfFloatType(double val) : HalfFloatType((float)val) {}
28
29 HalfFloatType(int val) : HalfFloatType((float)val) {}
30 HalfFloatType(unsigned val) : HalfFloatType((float)val) {}
31
32 HalfFloatType(int64_t val) : HalfFloatType((float)val) {}
33 HalfFloatType(uint64_t val) : HalfFloatType((float)val) {}
34
35 HalfFloatType() = default;
36
37 HalfFloatType &operator=(const float &other) {
38 this->data = other;
39 return *this;
40 }
41
42 operator float() const { return this->data; }
43
44 HalfFloatType &operator+=(const float &other) {
45 this->data += other;
46 return *this;
47 }
48
49 HalfFloatType &operator-=(const float &other) {
50 this->data -= other;
51 return *this;
52 }
53
54 HalfFloatType &operator*=(const float &other) {
55 this->data *= other;
56 return *this;
57 }
58
59 HalfFloatType &operator/=(const float &other) {
60 this->data /= other;
61 return *this;
62 }
63};
64
65typedef HalfFloatType<IeeeHalf> AccurateHalf;
66typedef HalfFloatType<float> FastHalf;
67
68static_assert(std::is_standard_layout<AccurateHalf>::value, "");
69static_assert(std::is_standard_layout<FastHalf>::value, "");
70
75template <typename T> struct is_poplar_half {
76 static const bool value = false;
77};
78
79template <> struct is_poplar_half<AccurateHalf> {
80 static const bool value = true;
81};
82
83template <> struct is_poplar_half<const AccurateHalf> {
84 static const bool value = true;
85};
86
87template <> struct is_poplar_half<FastHalf> { static const bool value = true; };
88
89template <> struct is_poplar_half<const FastHalf> {
90 static const bool value = true;
91};
92
93template <> struct is_poplar_half<IeeeHalf> { static const bool value = true; };
94
95template <> struct is_poplar_half<const IeeeHalf> {
96 static const bool value = true;
97};
98
99} // End namespace poplar.
100
101#ifdef POPLAR_ACCURATE_HALF
102typedef poplar::AccurateHalf half;
103#else
104typedef poplar::FastHalf half;
105#endif
106
107#include <limits>
108
109namespace std {
110
118template <> class numeric_limits<half> {
119public:
120 typedef half type;
121
122 static constexpr bool is_specialized = true;
123
124 static constexpr const bool is_signed = true;
125 static constexpr const int digits = 11;
126 static constexpr const int digits10 = 3;
127 static constexpr const int max_digits10 = 5;
128
129 static /*constexpr*/ type min() noexcept { return type(0.0f); }
130 static /*constexpr*/ type max() noexcept { return type(65504.0f); }
131 static /*constexpr*/ type lowest() noexcept { return type(-max()); }
132
133 static constexpr const bool is_integer = false;
134 static constexpr const bool is_exact = false;
135 static constexpr const int radix = 2;
136
137 static /*constexpr*/ type epsilon() noexcept {
138 // 2^-10
139 return type(0.0009765625f);
140 }
141 static /*constexpr*/ type round_error() noexcept {
142 // If stochastic rounding is enabled the error may be up to but
143 // not equal to 1 ULP.
144 return type(1.0f);
145 }
146
147 static constexpr const int min_exponent = -13;
148 static constexpr const int min_exponent10 = -4;
149 static constexpr const int max_exponent = 16;
150 static constexpr const int max_exponent10 = 4;
151
152 // Infinity is not supported and either saturates or is converted
153 // to a quiet NaN depending on the machine settings.
154 static constexpr const bool has_infinity = false;
155 static constexpr const bool has_quiet_NaN = true;
156 static constexpr const bool has_signaling_NaN = false;
157 static constexpr const float_denorm_style has_denorm = denorm_present;
158 static constexpr const bool has_denorm_loss = false;
159
160 // Warning: Infinity is not fully supported on hardware. Arithmetic operations
161 // never produce infinity, instead they either saturate or produce a quiet NaN
162 // depending on the $FP_CTL.NANOO flag (default is saturate). If an infinity
163 // is used as the input to an arithmetic operation it is treated as a
164 // signalling NaN. Also conversion from float infinity to half will produce a
165 // quiet NaN.
166 //
167 // However, comparison operations do support infinity.
168 //
169 // See section 2.10.4.2 in the tile manual.
170 static /*constexpr*/ type infinity() noexcept {
171 return type(std::numeric_limits<float>::infinity());
172 }
173
174 static /*constexpr*/ type quiet_NaN() noexcept {
175 return type(std::numeric_limits<float>::quiet_NaN());
176 }
177
178 // Signalling NaNs are not supported and are generally quietened.
179 static /*constexpr*/ type signaling_NaN() noexcept {
180 return type(std::numeric_limits<float>::quiet_NaN());
181 }
182
183 static /*constexpr*/ type denorm_min() noexcept {
184 // 2^-24
185 return type(0.00000005960464477539f);
186 }
187
188 // IEC559 requires signalling NaNs which are not supported.
189 static constexpr const bool is_iec559 = false;
190 static constexpr const bool is_bounded = true;
191 static constexpr const bool is_modulo = false;
192
193 static constexpr const bool traps = false;
194 static constexpr const bool tinyness_before = false;
195
196 // Stochastic rounding may or may not be enabled depending on the
197 // machine settings.
198 static constexpr const float_round_style round_style = round_indeterminate;
199};
200
201} // namespace std
202
203#endif // __IPU__
204
205#endif // poplar_HalfFloat_hpp_
half2 max(half2 src0, half2 src1)
Targets the f16v2max instruction.
Definition: ipu_intrinsics:333
half2 min(half2 src0, half2 src1)
Targets the f16v2min instruction.
Definition: ipu_intrinsics:384
Poplar classes and functions.
Definition: ArrayRef.hpp:14