blob: 5c62977b91f64bc25f20f385f527e6c81a14f066 [file] [log] [blame]
Moritz Pflanzer09e4f982017-08-30 12:47:06 +01001/*
Michalis Spyrou40df1e92018-02-06 16:53:47 +00002 * Copyright (c) 2017-2018 ARM Limited.
Moritz Pflanzer09e4f982017-08-30 12:47:06 +01003 *
4 * SPDX-License-Identifier: MIT
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24#ifndef ARM_COMPUTE_TEST_MEASUREMENT
25#define ARM_COMPUTE_TEST_MEASUREMENT
26
27#include "../Utils.h"
Anthony Barbierab14c152017-11-09 10:29:59 +000028#include "arm_compute/core/Error.h"
Moritz Pflanzer09e4f982017-08-30 12:47:06 +010029
Anthony Barbierab14c152017-11-09 10:29:59 +000030#include <list>
Moritz Pflanzer09e4f982017-08-30 12:47:06 +010031#include <ostream>
32#include <string>
33
34namespace arm_compute
35{
36namespace test
37{
38namespace framework
39{
Anthony Barbierab14c152017-11-09 10:29:59 +000040/** Generic measurement that stores values as either double or long long int. */
41struct Measurement
Moritz Pflanzer09e4f982017-08-30 12:47:06 +010042{
Alex Gildayc357c472018-03-21 13:54:09 +000043 /** Measurement value */
Anthony Barbierab14c152017-11-09 10:29:59 +000044 struct Value
Moritz Pflanzer09e4f982017-08-30 12:47:06 +010045 {
Anthony Barbierab14c152017-11-09 10:29:59 +000046 /** Constructor
47 *
48 * @param[in] is_floating Will the value stored be floating point ?
49 */
50 Value(bool is_floating)
51 : v{ 0 }, is_floating_point(is_floating)
52 {
53 }
54
55 /** Add the value stored to the stream as a string
56 */
57 friend std::ostream &operator<<(std::ostream &os, const Value &value)
58 {
59 if(value.is_floating_point)
60 {
Giorgio Arenace58a9f2017-10-31 17:59:17 +000061 os << arithmetic_to_string(value.v.floating_point, 4);
Anthony Barbierab14c152017-11-09 10:29:59 +000062 }
63 else
64 {
65 os << arithmetic_to_string(value.v.integer);
66 }
67 return os;
68 }
69 /** Convert the value stored to string
70 */
71 std::string to_string() const
72 {
73 std::stringstream ss;
74 ss << *this;
75 return ss.str();
76 }
77 /** Add with another value and return the sum
78 *
79 * @param[in] b Other value
80 *
81 * @return Sum of the stored value + b
82 */
83 Value operator+(Value b) const
84 {
85 if(is_floating_point)
86 {
87 b.v.floating_point += v.floating_point;
88 }
89 else
90 {
91 b.v.integer += v.integer;
92 }
93 return b;
94 }
95
Joel Liang5b73ce12017-11-21 16:50:53 +080096 /** Subtract with another value and return the result
97 *
98 * @param[in] b Other value
99 *
100 * @return Result of the stored value - b
101 */
102 Value operator-(Value b) const
103 {
104 if(is_floating_point)
105 {
106 b.v.floating_point -= v.floating_point;
107 }
108 else
109 {
110 b.v.integer -= v.integer;
111 }
112 return b;
113 }
114
115 /** Multiple with another value and return the result
116 *
117 * @param[in] b Other value
118 *
119 * @return Result of the stored value * b
120 */
121 Value operator*(Value b) const
122 {
123 if(is_floating_point)
124 {
125 b.v.floating_point *= v.floating_point;
126 }
127 else
128 {
129 b.v.integer *= v.integer;
130 }
131 return b;
132 }
133
Anthony Barbierab14c152017-11-09 10:29:59 +0000134 /** Return the stored value divided by an integer.
135 *
136 * @param[in] b Integer to divide the value by.
137 *
138 * @return Stored value / b
139 */
140 Value operator/(int b) const
141 {
142 Value res(is_floating_point);
143 if(is_floating_point)
144 {
145 res.v.floating_point = v.floating_point / b;
146 }
147 else
148 {
149 res.v.integer = v.integer / b;
150 }
151 return res;
152 }
153
154 /** Subtract another value and return the updated stored value.
155 *
156 * @param[in] b Other value
157 *
158 * @return The updated stored value
159 */
160 Value &operator-=(const Value &b)
161 {
162 if(is_floating_point)
163 {
164 v.floating_point -= b.v.floating_point;
165 }
166 else
167 {
168 v.integer -= b.v.integer;
169 }
170 return *this;
171 }
172
173 /** Compare the stored value with another value
174 *
175 * @param[in] b Value to compare against
176 *
177 * @return The result of stored value < b
178 */
179 bool operator<(const Value &b) const
180 {
181 if(is_floating_point)
182 {
183 return v.floating_point < b.v.floating_point;
184 }
185 else
186 {
187 return v.integer < b.v.integer;
188 }
189 }
190
Alex Gildayc357c472018-03-21 13:54:09 +0000191 /** Get the relative standard deviation to a given distribution as a percentage.
192 *
193 * @param[in] variance The variance of the distribution.
194 * @param[in] mean The mean of the distribution.
195 *
196 * @return the relative standard deviation.
197 */
Joel Liang5b73ce12017-11-21 16:50:53 +0800198 static double relative_standard_deviation(const Value &variance, const Value &mean)
199 {
200 if(variance.is_floating_point)
201 {
202 return 100.0 * sqrt(variance.v.floating_point) / mean.v.floating_point;
203 }
204 else
205 {
206 return 100.0 * sqrt(static_cast<double>(variance.v.integer)) / mean.v.integer;
207 }
208 }
209
Anthony Barbierab14c152017-11-09 10:29:59 +0000210 /** Stored value */
211 union
212 {
213 double floating_point;
214 long long int integer;
215 } v;
216 bool is_floating_point; /**< Is the stored value floating point or integer ? */
217 };
218
Michalis Spyrou40df1e92018-02-06 16:53:47 +0000219 /** Compare the stored value with another value
220 *
221 * @param[in] b Value to compare against
222 *
223 * @return The result of stored value < b
224 */
225 bool operator<(const Measurement &b) const
226 {
227 return _value < b.value();
228 }
229
Anthony Barbierab14c152017-11-09 10:29:59 +0000230 /** Stream output operator to print the measurement.
231 *
232 * Prints value and unit.
Alex Gildayc357c472018-03-21 13:54:09 +0000233 *
234 * @param[out] os Output stream.
235 * @param[in] measurement Measurement.
236 *
237 * @return the modified output stream.
Anthony Barbierab14c152017-11-09 10:29:59 +0000238 */
239 friend inline std::ostream &operator<<(std::ostream &os, const Measurement &measurement)
240 {
241 os << measurement._value << " " << measurement._unit;
242 return os;
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100243 }
244
Anthony Barbierab14c152017-11-09 10:29:59 +0000245 /** Constructor to store a floating point value
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100246 *
Anthony Barbierab14c152017-11-09 10:29:59 +0000247 * @param[in] v Value to store
248 * @param[in] unit Unit of @p v
249 * @param[in] raw (Optional) The raw value(s) @p was generated from.
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100250 */
Anthony Barbierab14c152017-11-09 10:29:59 +0000251 template < typename Floating, typename std::enable_if < !std::is_integral<Floating>::value, int >::type = 0 >
252 Measurement(Floating v, std::string unit, std::list<std::string> raw = {})
253 : _unit(unit), _raw_data(std::move(raw)), _value(true)
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100254 {
Anthony Barbierab14c152017-11-09 10:29:59 +0000255 _value.v.floating_point = static_cast<double>(v);
256 if(_raw_data.empty())
257 {
258 _raw_data = { _value.to_string() };
259 }
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100260 }
261
Anthony Barbierab14c152017-11-09 10:29:59 +0000262 /** Constructor to store an integer value
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100263 *
Anthony Barbierab14c152017-11-09 10:29:59 +0000264 * @param[in] v Value to store
265 * @param[in] unit Unit of @p v
266 * @param[in] raw (Optional) The raw value(s) @p was generated from.
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100267 */
Anthony Barbierab14c152017-11-09 10:29:59 +0000268 template <typename Integer, typename std::enable_if<std::is_integral<Integer>::value, int>::type = 0>
269 Measurement(Integer v, std::string unit, std::list<std::string> raw = {})
270 : _unit(unit), _raw_data(std::move(raw)), _value(false)
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100271 {
Anthony Barbierab14c152017-11-09 10:29:59 +0000272 _value.v.integer = static_cast<long long int>(v);
273 if(_raw_data.empty())
274 {
275 _raw_data = { _value.to_string() };
276 }
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100277 }
Anthony Barbierab14c152017-11-09 10:29:59 +0000278
279 /** Accessor for the unit of the measurement
280 *
281 * @return Unit of the measurement
282 */
283 const std::string &unit() const
284 {
285 return _unit;
286 }
287
288 /** Accessor for the raw data
289 *
290 * @return The raw data
291 */
292 const std::list<std::string> &raw_data() const
293 {
294 return _raw_data;
295 }
296
297 /** Accessor for the stored value
298 *
299 * @return The stored value
300 */
301 const Value &value() const
302 {
303 return _value;
304 }
305
306private:
307 std::string _unit;
308 std::list<std::string> _raw_data;
309 Value _value;
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100310};
Anthony Barbierab14c152017-11-09 10:29:59 +0000311
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100312} // namespace framework
313} // namespace test
314} // namespace arm_compute
315#endif /* ARM_COMPUTE_TEST_MEASUREMENT */