xref: /aosp_15_r20/external/ComputeLibrary/tests/framework/instruments/Measurement.h (revision c217d954acce2dbc11938adb493fc0abd69584f3)
1 /*
2  * Copyright (c) 2017-2018,2021 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"
28 #include "arm_compute/core/Error.h"
29 
30 #include <list>
31 #include <ostream>
32 #include <string>
33 
34 namespace arm_compute
35 {
36 namespace test
37 {
38 namespace framework
39 {
40 /** Generic measurement that stores values as either double or long long int. */
41 struct Measurement
42 {
43     /** Measurement value */
44     struct Value
45     {
46         /** Constructor
47          *
48          * @param[in] is_floating Will the value stored be floating point ?
49          */
ValueMeasurement::Value50         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             {
61                 os << arithmetic_to_string(value.v.floating_point, 4);
62             }
63             else
64             {
65                 os << arithmetic_to_string(value.v.integer);
66             }
67             return os;
68         }
69         /** Convert the value stored to string
70          */
to_stringMeasurement::Value71         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 
96         /** 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 
134         /** 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 
191         /** 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          */
relative_standard_deviationMeasurement::Value198         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 
210         /** 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 
219     /** 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 
230     /** Stream output operator to print the measurement.
231      *
232      * Prints value and unit.
233      *
234      * @param[out] os          Output stream.
235      * @param[in]  measurement Measurement.
236      *
237      * @return the modified output stream.
238      */
239     friend inline std::ostream &operator<<(std::ostream &os, const Measurement &measurement)
240     {
241         os << measurement._value << " " << measurement._unit;
242         return os;
243     }
244 
245     /** Constructor to store a floating point value
246      *
247      * @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.
250      */
251     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 = {})
_unitMeasurement253         : _unit(unit), _raw_data(std::move(raw)), _value(true)
254     {
255         _value.v.floating_point = static_cast<double>(v);
256         if(_raw_data.empty())
257         {
258             _raw_data = { _value.to_string() };
259         }
260     }
261 
262     /** Constructor to store an integer value
263      *
264      * @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.
267      */
268     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 = {})
_unitMeasurement270         : _unit(unit), _raw_data(std::move(raw)), _value(false)
271     {
272         _value.v.integer = static_cast<long long int>(v);
273         if(_raw_data.empty())
274         {
275             _raw_data = { _value.to_string() };
276         }
277     }
278 
279     /** Accessor for the unit of the measurement
280      *
281      * @return Unit of the measurement
282      */
unitMeasurement283     const std::string &unit() const
284     {
285         return _unit;
286     }
287 
288     /** Accessor for the raw data
289      *
290      * @return The raw data
291      */
raw_dataMeasurement292     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      */
valueMeasurement301     const Value &value() const
302     {
303         return _value;
304     }
305 
306 private:
307     std::string            _unit;
308     std::list<std::string> _raw_data;
309     Value                  _value;
310 };
311 
312 } // namespace framework
313 } // namespace test
314 } // namespace arm_compute
315 #endif /* ARM_COMPUTE_TEST_MEASUREMENT */
316