blob: 9fb75d7b99aab18233e6a54272d38fa9d83f6e01 [file] [log] [blame]
Moritz Pflanzer09e4f982017-08-30 12:47:06 +01001/*
2 * Copyright (c) 2017 ARM Limited.
3 *
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{
Anthony Barbierab14c152017-11-09 10:29:59 +000043 struct Value
Moritz Pflanzer09e4f982017-08-30 12:47:06 +010044 {
Anthony Barbierab14c152017-11-09 10:29:59 +000045 /** Constructor
46 *
47 * @param[in] is_floating Will the value stored be floating point ?
48 */
49 Value(bool is_floating)
50 : v{ 0 }, is_floating_point(is_floating)
51 {
52 }
53
54 /** Add the value stored to the stream as a string
55 */
56 friend std::ostream &operator<<(std::ostream &os, const Value &value)
57 {
58 if(value.is_floating_point)
59 {
Giorgio Arenace58a9f2017-10-31 17:59:17 +000060 os << arithmetic_to_string(value.v.floating_point, 4);
Anthony Barbierab14c152017-11-09 10:29:59 +000061 }
62 else
63 {
64 os << arithmetic_to_string(value.v.integer);
65 }
66 return os;
67 }
68 /** Convert the value stored to string
69 */
70 std::string to_string() const
71 {
72 std::stringstream ss;
73 ss << *this;
74 return ss.str();
75 }
76 /** Add with another value and return the sum
77 *
78 * @param[in] b Other value
79 *
80 * @return Sum of the stored value + b
81 */
82 Value operator+(Value b) const
83 {
84 if(is_floating_point)
85 {
86 b.v.floating_point += v.floating_point;
87 }
88 else
89 {
90 b.v.integer += v.integer;
91 }
92 return b;
93 }
94
Joel Liang5b73ce12017-11-21 16:50:53 +080095 /** Subtract with another value and return the result
96 *
97 * @param[in] b Other value
98 *
99 * @return Result of the stored value - b
100 */
101 Value operator-(Value b) const
102 {
103 if(is_floating_point)
104 {
105 b.v.floating_point -= v.floating_point;
106 }
107 else
108 {
109 b.v.integer -= v.integer;
110 }
111 return b;
112 }
113
114 /** Multiple with another value and return the result
115 *
116 * @param[in] b Other value
117 *
118 * @return Result of the stored value * b
119 */
120 Value operator*(Value b) const
121 {
122 if(is_floating_point)
123 {
124 b.v.floating_point *= v.floating_point;
125 }
126 else
127 {
128 b.v.integer *= v.integer;
129 }
130 return b;
131 }
132
Anthony Barbierab14c152017-11-09 10:29:59 +0000133 /** Return the stored value divided by an integer.
134 *
135 * @param[in] b Integer to divide the value by.
136 *
137 * @return Stored value / b
138 */
139 Value operator/(int b) const
140 {
141 Value res(is_floating_point);
142 if(is_floating_point)
143 {
144 res.v.floating_point = v.floating_point / b;
145 }
146 else
147 {
148 res.v.integer = v.integer / b;
149 }
150 return res;
151 }
152
153 /** Subtract another value and return the updated stored value.
154 *
155 * @param[in] b Other value
156 *
157 * @return The updated stored value
158 */
159 Value &operator-=(const Value &b)
160 {
161 if(is_floating_point)
162 {
163 v.floating_point -= b.v.floating_point;
164 }
165 else
166 {
167 v.integer -= b.v.integer;
168 }
169 return *this;
170 }
171
172 /** Compare the stored value with another value
173 *
174 * @param[in] b Value to compare against
175 *
176 * @return The result of stored value < b
177 */
178 bool operator<(const Value &b) const
179 {
180 if(is_floating_point)
181 {
182 return v.floating_point < b.v.floating_point;
183 }
184 else
185 {
186 return v.integer < b.v.integer;
187 }
188 }
189
Joel Liang5b73ce12017-11-21 16:50:53 +0800190 static double relative_standard_deviation(const Value &variance, const Value &mean)
191 {
192 if(variance.is_floating_point)
193 {
194 return 100.0 * sqrt(variance.v.floating_point) / mean.v.floating_point;
195 }
196 else
197 {
198 return 100.0 * sqrt(static_cast<double>(variance.v.integer)) / mean.v.integer;
199 }
200 }
201
Anthony Barbierab14c152017-11-09 10:29:59 +0000202 /** Stored value */
203 union
204 {
205 double floating_point;
206 long long int integer;
207 } v;
208 bool is_floating_point; /**< Is the stored value floating point or integer ? */
209 };
210
211 /** Stream output operator to print the measurement.
212 *
213 * Prints value and unit.
214 */
215 friend inline std::ostream &operator<<(std::ostream &os, const Measurement &measurement)
216 {
217 os << measurement._value << " " << measurement._unit;
218 return os;
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100219 }
220
Anthony Barbierab14c152017-11-09 10:29:59 +0000221 /** Constructor to store a floating point value
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100222 *
Anthony Barbierab14c152017-11-09 10:29:59 +0000223 * @param[in] v Value to store
224 * @param[in] unit Unit of @p v
225 * @param[in] raw (Optional) The raw value(s) @p was generated from.
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100226 */
Anthony Barbierab14c152017-11-09 10:29:59 +0000227 template < typename Floating, typename std::enable_if < !std::is_integral<Floating>::value, int >::type = 0 >
228 Measurement(Floating v, std::string unit, std::list<std::string> raw = {})
229 : _unit(unit), _raw_data(std::move(raw)), _value(true)
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100230 {
Anthony Barbierab14c152017-11-09 10:29:59 +0000231 _value.v.floating_point = static_cast<double>(v);
232 if(_raw_data.empty())
233 {
234 _raw_data = { _value.to_string() };
235 }
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100236 }
237
Anthony Barbierab14c152017-11-09 10:29:59 +0000238 /** Constructor to store an integer value
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100239 *
Anthony Barbierab14c152017-11-09 10:29:59 +0000240 * @param[in] v Value to store
241 * @param[in] unit Unit of @p v
242 * @param[in] raw (Optional) The raw value(s) @p was generated from.
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100243 */
Anthony Barbierab14c152017-11-09 10:29:59 +0000244 template <typename Integer, typename std::enable_if<std::is_integral<Integer>::value, int>::type = 0>
245 Measurement(Integer v, std::string unit, std::list<std::string> raw = {})
246 : _unit(unit), _raw_data(std::move(raw)), _value(false)
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100247 {
Anthony Barbierab14c152017-11-09 10:29:59 +0000248 _value.v.integer = static_cast<long long int>(v);
249 if(_raw_data.empty())
250 {
251 _raw_data = { _value.to_string() };
252 }
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100253 }
Anthony Barbierab14c152017-11-09 10:29:59 +0000254
255 /** Accessor for the unit of the measurement
256 *
257 * @return Unit of the measurement
258 */
259 const std::string &unit() const
260 {
261 return _unit;
262 }
263
264 /** Accessor for the raw data
265 *
266 * @return The raw data
267 */
268 const std::list<std::string> &raw_data() const
269 {
270 return _raw_data;
271 }
272
273 /** Accessor for the stored value
274 *
275 * @return The stored value
276 */
277 const Value &value() const
278 {
279 return _value;
280 }
281
282private:
283 std::string _unit;
284 std::list<std::string> _raw_data;
285 Value _value;
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100286};
Anthony Barbierab14c152017-11-09 10:29:59 +0000287
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100288} // namespace framework
289} // namespace test
290} // namespace arm_compute
291#endif /* ARM_COMPUTE_TEST_MEASUREMENT */