ATLAS Offline Software
Loading...
Searching...
No Matches
ap_fixedTest.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3*/
4
7
8#include "gtest/gtest.h"
9#include "../ap_fixed.h"
10
11#include <sstream>
12#include <cmath>
13
14// this function will be templated on the int type.
15constexpr int pow(int base, int exp) noexcept {
16 auto result{1};
17
18 for(int i = 0; i < exp; ++i) {
19 result *= base;
20 }
21
22 return result;
23}
24
25template<int W, int P>
26constexpr double min() {
27 static_assert(W >= P);
28 static_assert(P >= 0);
29 return -pow(2, W-1)/pow(2, P);
30}
31
32template<int W, int P>
33constexpr double max () {
34 static_assert(W >= P);
35 static_assert(P >= 0);
36 return static_cast<double>(pow(2, W-1)-1)/static_cast<double>(pow(2, P));
37}
38
39TEST (ap_fixedTester, minmax) {
40
41 auto min_v = min<10, 5>();
42 auto max_v = max<10, 5>();
43 EXPECT_EQ(-16, min_v);
44 EXPECT_EQ(15.96875, max_v);
45}
46
47TEST(ap_fixedTester, stablity) {
48
49
50 constexpr int width{10};
51 constexpr int prec{5};
52 double delta = pow(2, -prec-1); // step by a value less then precision
53
54 double val = min<width, prec>();
55 double max_val = max<width, prec>();
56 double cval = -val;
57
58 std::size_t i{0};
59
60 while (cval <= max_val) {
61
63 double d0 = static_cast<double>(ap_gs0);
64 auto ap_gs1 = GlobalSim::ap_fixed<10, 5>(d0);
65 double d1 = static_cast<double>(ap_gs1);
66 auto ap_gs2 = GlobalSim::ap_fixed<10, 5>(d1);
67 double d2 = static_cast<double>(ap_gs2);
68
69 EXPECT_EQ (d2, d0);
70 EXPECT_EQ (ap_gs0.m_value, ap_gs2.m_value);
71 EXPECT_LT (std::abs(d0 -cval), 1./(2*2*2*2*2));
72
73
74 cval = -val + ((++i) * delta);
75 }
76}
77
78TEST(ap_fixedTester, specialValue) {
79
80 //Xylinx ap_fixed gets this wrong
81 auto apf = GlobalSim::ap_fixed<10, 5, GlobalSim::Round>(-0.327374935);
82 EXPECT_EQ (-0.3125, static_cast<double>(apf));
83 std::stringstream ss;
84 ss << std::hex << apf.m_value;
85 EXPECT_EQ ("fff6", ss.str());
86}
87
88
89
90TEST(ap_fixedTester, overflow_h) {
91 constexpr int width{10};
92 constexpr int prec{5};
93
96 // out of range by 0.5*prec
97 double outOfRange = max<width, prec>() + pow(2, -prec-1);
98
99 EXPECT_THROW ((ap(outOfRange)), std::out_of_range);
100}
101
102TEST(ap_fixedTester, overflow_l) {
103 constexpr int width{10};
104 constexpr int prec{5};
105
106 // out of range by 0.5*prec
107 double outOfRange = min<width, prec>() - pow(2, -prec-1);
109
110 EXPECT_THROW ((ap(outOfRange)), std::out_of_range);
111}
112
113
114TEST(ap_fixedTester, addition) {
115
116 constexpr int width{10};
117 constexpr int prec{5};
118 const double eps {std::pow(2.0, -prec)};
120
121 ap ap_sum = ap(1) + ap(2);
122 auto val = static_cast<double>(ap_sum);
123 auto diff = std::abs(val - 3);
124
125 EXPECT_EQ (3, val);
126 EXPECT_LT (diff, eps);
127
128 ap_sum = ap(1.5) + ap(2.5);
129 val = static_cast<double>(ap_sum);
130 diff = std::abs(val - 4);
131
132 EXPECT_EQ (4, val);
133 EXPECT_LT (diff, eps);
134}
135
136TEST(ap_fixedTester, addition1) {
137
138 constexpr int width{10};
139 constexpr int prec{5};
140 const double eps {std::pow(2.0, -prec)};
142
143 ap ap_sum = ap(2) += 1;
144 auto val = static_cast<double>(ap_sum);
145 auto diff = std::abs(val - 3);
146
147 EXPECT_EQ (3, val);
148 EXPECT_LT (diff, eps);
149
150 ap_sum = ap(1.5) += 2.5;
151 val = static_cast<double>(ap_sum);
152 diff = std::abs(val - 4);
153
154 EXPECT_EQ (4, val);
155 EXPECT_LT (diff, eps);
156}
157
158
159TEST(ap_fixedTester, subtraction) {
160
161 constexpr int width{10};
162 constexpr int prec{5};
163 const double eps {std::pow(2.0, -prec)};
165
166 ap ap_diff = ap(1) - ap(2);
167 auto val = static_cast<double>(ap_diff);
168 auto diff = std::abs(val + 1);
169
170 EXPECT_EQ (-1, val);
171 EXPECT_LT (diff, eps);
172
173 ap_diff = ap(1.5) - ap(2.5);
174 val = static_cast<double>(ap_diff);
175 diff = std::abs(val + 1);
176
177 EXPECT_EQ (-1, val);
178 EXPECT_LT (diff, eps);
179}
180
181TEST(ap_fixedTester, subtraction1) {
182
183 constexpr int width{10};
184 constexpr int prec{5};
185 const double eps {std::pow(2.0, -prec)};
187
188 ap ap_diff = ap(1) -= 2;
189 auto val = static_cast<double>(ap_diff);
190 auto diff = std::abs(val + 1);
191
192 EXPECT_EQ (-1, val);
193 EXPECT_LT (diff, eps);
194
195 ap_diff = ap(1.5) -= 2.5;
196 val = static_cast<double>(ap_diff);
197 diff = std::abs(val + 1);
198
199 EXPECT_EQ (-1, val);
200 EXPECT_LT (diff, eps);
201}
202
203
204
205TEST(ap_fixedTester, multiplication) {
206
207 constexpr int width{10};
208 constexpr int prec{5};
209 const double eps {std::pow(2.0, -prec)};
211
212 ap ap_prod = ap(1) * ap(2);
213 auto val = static_cast<double>(ap_prod);
214 auto diff = std::abs(val - 2);
215
216 EXPECT_EQ (2, val);
217 EXPECT_LT (diff, eps);
218
219 ap_prod = ap(-1.5)*ap(2);
220 val = static_cast<double>(ap_prod);
221 diff = std::abs(val +3);
222
223 EXPECT_EQ (-3, val);
224 EXPECT_LT (diff, eps);
225}
226
227TEST(ap_fixedTester, multiplication1) {
228 constexpr int width{10};
229 constexpr int prec{5};
230 const double eps {std::pow(2.0, -prec)};
232
233 ap ap_prod = ap(1) *= ap(2);
234 auto val = static_cast<double>(ap_prod);
235 auto diff = std::abs(val - 2);
236
237 EXPECT_EQ (2, val);
238 EXPECT_LT (diff, eps);
239
240 ap_prod = ap(-1.5) *= ap(2.);
241 val = static_cast<double>(ap_prod);
242 diff = std::abs(val +3);
243
244 EXPECT_EQ (-3, val);
245 EXPECT_LT (diff, eps);
246}
247
248
249TEST(ap_fixedTester, division) {
250
251 constexpr int width{10};
252 constexpr int prec{5};
253 const double eps {std::pow(2.0, -prec)};
255
256 ap ap_div = ap(1)/ap(2);
257 auto val = static_cast<double>(ap_div);
258 auto diff = std::abs(val - 0.5);
259
260 EXPECT_EQ (0.5, val);
261 EXPECT_LT (diff, eps);
262
263 ap_div = ap(-1.5)/ap(2);
264 val = static_cast<double>(ap_div);
265 diff = std::abs(val + 0.75);
266
267 EXPECT_EQ (-0.75, val);
268 EXPECT_LT (diff, eps);
269}
270
271
272TEST(ap_fixedTester, division1) {
273
274 constexpr int width{10};
275 constexpr int prec{5};
276 const double eps {std::pow(2.0, -prec)};
278
279 ap ap_div = ap(1)/=ap(2);
280 auto val = static_cast<double>(ap_div);
281 auto diff = std::abs(val - 0.5);
282
283 EXPECT_EQ (0.5, val);
284 EXPECT_LT (diff, eps);
285
286 ap_div = ap(-1.5)/ap(2);
287 val = static_cast<double>(ap_div);
288 diff = std::abs(val + 0.75);
289
290 EXPECT_EQ (-0.75, val);
291 EXPECT_LT (diff, eps);
292}
293
294
295TEST(ap_fixedTester, negation) {
296
297 constexpr int width{10};
298 constexpr int prec{5};
299
301
302 auto ap_p = ap(1);
303 auto ap_n = -ap_p;
304 auto ap_pp = -ap_n;
305
306 auto val_p = static_cast<double>(ap_p);
307 auto val_n = static_cast<double>(ap_n);
308 auto val_pp = static_cast<double>(ap_pp);
309
310 EXPECT_EQ (val_p, -val_n);
311 EXPECT_EQ (val_p, val_pp);
312}
313
314TEST(ap_fixedTester, doubleMult) {
315
316 constexpr int width{10};
317 constexpr int prec{5};
318
320 ap ap_mul = 9.99 * ap(1);
321
322 EXPECT_EQ (10, static_cast<double>(ap_mul));
323}
324
325
static Double_t ss
static Double_t P(Double_t *tt, Double_t *par)
void diff(const Jet &rJet1, const Jet &rJet2, std::map< std::string, double > varDiff)
Difference between jets - Non-Class function required by trigger.
Definition Jet.cxx:631
const double width
constexpr int pow(int base, int exp) noexcept
TEST(ap_fixedTester, minmax)
constexpr double min()
constexpr double max()
Define macros for attributes used to control the static checker.
#define ATLAS_NO_CHECK_FILE_THREAD_SAFETY
std::string base
Definition hcg.cxx:81