316 lines
8.8 KiB
C++
316 lines
8.8 KiB
C++
/*
|
|
* Copyright (c) 2017-2018 Arm Limited.
|
|
*
|
|
* SPDX-License-Identifier: MIT
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to
|
|
* deal in the Software without restriction, including without limitation the
|
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
* sell copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in all
|
|
* copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
* SOFTWARE.
|
|
*/
|
|
#ifndef ARM_COMPUTE_TEST_MEASUREMENT
|
|
#define ARM_COMPUTE_TEST_MEASUREMENT
|
|
|
|
#include "../Utils.h"
|
|
#include "arm_compute/core/Error.h"
|
|
|
|
#include <list>
|
|
#include <ostream>
|
|
#include <string>
|
|
|
|
namespace arm_compute
|
|
{
|
|
namespace test
|
|
{
|
|
namespace framework
|
|
{
|
|
/** Generic measurement that stores values as either double or long long int. */
|
|
struct Measurement
|
|
{
|
|
/** Measurement value */
|
|
struct Value
|
|
{
|
|
/** Constructor
|
|
*
|
|
* @param[in] is_floating Will the value stored be floating point ?
|
|
*/
|
|
Value(bool is_floating)
|
|
: v{ 0 }, is_floating_point(is_floating)
|
|
{
|
|
}
|
|
|
|
/** Add the value stored to the stream as a string
|
|
*/
|
|
friend std::ostream &operator<<(std::ostream &os, const Value &value)
|
|
{
|
|
if(value.is_floating_point)
|
|
{
|
|
os << arithmetic_to_string(value.v.floating_point, 4);
|
|
}
|
|
else
|
|
{
|
|
os << arithmetic_to_string(value.v.integer);
|
|
}
|
|
return os;
|
|
}
|
|
/** Convert the value stored to string
|
|
*/
|
|
std::string to_string() const
|
|
{
|
|
std::stringstream ss;
|
|
ss << *this;
|
|
return ss.str();
|
|
}
|
|
/** Add with another value and return the sum
|
|
*
|
|
* @param[in] b Other value
|
|
*
|
|
* @return Sum of the stored value + b
|
|
*/
|
|
Value operator+(Value b) const
|
|
{
|
|
if(is_floating_point)
|
|
{
|
|
b.v.floating_point += v.floating_point;
|
|
}
|
|
else
|
|
{
|
|
b.v.integer += v.integer;
|
|
}
|
|
return b;
|
|
}
|
|
|
|
/** Subtract with another value and return the result
|
|
*
|
|
* @param[in] b Other value
|
|
*
|
|
* @return Result of the stored value - b
|
|
*/
|
|
Value operator-(Value b) const
|
|
{
|
|
if(is_floating_point)
|
|
{
|
|
b.v.floating_point -= v.floating_point;
|
|
}
|
|
else
|
|
{
|
|
b.v.integer -= v.integer;
|
|
}
|
|
return b;
|
|
}
|
|
|
|
/** Multiple with another value and return the result
|
|
*
|
|
* @param[in] b Other value
|
|
*
|
|
* @return Result of the stored value * b
|
|
*/
|
|
Value operator*(Value b) const
|
|
{
|
|
if(is_floating_point)
|
|
{
|
|
b.v.floating_point *= v.floating_point;
|
|
}
|
|
else
|
|
{
|
|
b.v.integer *= v.integer;
|
|
}
|
|
return b;
|
|
}
|
|
|
|
/** Return the stored value divided by an integer.
|
|
*
|
|
* @param[in] b Integer to divide the value by.
|
|
*
|
|
* @return Stored value / b
|
|
*/
|
|
Value operator/(int b) const
|
|
{
|
|
Value res(is_floating_point);
|
|
if(is_floating_point)
|
|
{
|
|
res.v.floating_point = v.floating_point / b;
|
|
}
|
|
else
|
|
{
|
|
res.v.integer = v.integer / b;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
/** Subtract another value and return the updated stored value.
|
|
*
|
|
* @param[in] b Other value
|
|
*
|
|
* @return The updated stored value
|
|
*/
|
|
Value &operator-=(const Value &b)
|
|
{
|
|
if(is_floating_point)
|
|
{
|
|
v.floating_point -= b.v.floating_point;
|
|
}
|
|
else
|
|
{
|
|
v.integer -= b.v.integer;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
/** Compare the stored value with another value
|
|
*
|
|
* @param[in] b Value to compare against
|
|
*
|
|
* @return The result of stored value < b
|
|
*/
|
|
bool operator<(const Value &b) const
|
|
{
|
|
if(is_floating_point)
|
|
{
|
|
return v.floating_point < b.v.floating_point;
|
|
}
|
|
else
|
|
{
|
|
return v.integer < b.v.integer;
|
|
}
|
|
}
|
|
|
|
/** Get the relative standard deviation to a given distribution as a percentage.
|
|
*
|
|
* @param[in] variance The variance of the distribution.
|
|
* @param[in] mean The mean of the distribution.
|
|
*
|
|
* @return the relative standard deviation.
|
|
*/
|
|
static double relative_standard_deviation(const Value &variance, const Value &mean)
|
|
{
|
|
if(variance.is_floating_point)
|
|
{
|
|
return 100.0 * sqrt(variance.v.floating_point) / mean.v.floating_point;
|
|
}
|
|
else
|
|
{
|
|
return 100.0 * sqrt(static_cast<double>(variance.v.integer)) / mean.v.integer;
|
|
}
|
|
}
|
|
|
|
/** Stored value */
|
|
union
|
|
{
|
|
double floating_point;
|
|
long long int integer;
|
|
} v;
|
|
bool is_floating_point; /**< Is the stored value floating point or integer ? */
|
|
};
|
|
|
|
/** Compare the stored value with another value
|
|
*
|
|
* @param[in] b Value to compare against
|
|
*
|
|
* @return The result of stored value < b
|
|
*/
|
|
bool operator<(const Measurement &b) const
|
|
{
|
|
return _value < b.value();
|
|
}
|
|
|
|
/** Stream output operator to print the measurement.
|
|
*
|
|
* Prints value and unit.
|
|
*
|
|
* @param[out] os Output stream.
|
|
* @param[in] measurement Measurement.
|
|
*
|
|
* @return the modified output stream.
|
|
*/
|
|
friend inline std::ostream &operator<<(std::ostream &os, const Measurement &measurement)
|
|
{
|
|
os << measurement._value << " " << measurement._unit;
|
|
return os;
|
|
}
|
|
|
|
/** Constructor to store a floating point value
|
|
*
|
|
* @param[in] v Value to store
|
|
* @param[in] unit Unit of @p v
|
|
* @param[in] raw (Optional) The raw value(s) @p was generated from.
|
|
*/
|
|
template < typename Floating, typename std::enable_if < !std::is_integral<Floating>::value, int >::type = 0 >
|
|
Measurement(Floating v, std::string unit, std::list<std::string> raw = {})
|
|
: _unit(unit), _raw_data(std::move(raw)), _value(true)
|
|
{
|
|
_value.v.floating_point = static_cast<double>(v);
|
|
if(_raw_data.empty())
|
|
{
|
|
_raw_data = { _value.to_string() };
|
|
}
|
|
}
|
|
|
|
/** Constructor to store an integer value
|
|
*
|
|
* @param[in] v Value to store
|
|
* @param[in] unit Unit of @p v
|
|
* @param[in] raw (Optional) The raw value(s) @p was generated from.
|
|
*/
|
|
template <typename Integer, typename std::enable_if<std::is_integral<Integer>::value, int>::type = 0>
|
|
Measurement(Integer v, std::string unit, std::list<std::string> raw = {})
|
|
: _unit(unit), _raw_data(std::move(raw)), _value(false)
|
|
{
|
|
_value.v.integer = static_cast<long long int>(v);
|
|
if(_raw_data.empty())
|
|
{
|
|
_raw_data = { _value.to_string() };
|
|
}
|
|
}
|
|
|
|
/** Accessor for the unit of the measurement
|
|
*
|
|
* @return Unit of the measurement
|
|
*/
|
|
const std::string &unit() const
|
|
{
|
|
return _unit;
|
|
}
|
|
|
|
/** Accessor for the raw data
|
|
*
|
|
* @return The raw data
|
|
*/
|
|
const std::list<std::string> &raw_data() const
|
|
{
|
|
return _raw_data;
|
|
}
|
|
|
|
/** Accessor for the stored value
|
|
*
|
|
* @return The stored value
|
|
*/
|
|
const Value &value() const
|
|
{
|
|
return _value;
|
|
}
|
|
|
|
private:
|
|
std::string _unit;
|
|
std::list<std::string> _raw_data;
|
|
Value _value;
|
|
};
|
|
|
|
} // namespace framework
|
|
} // namespace test
|
|
} // namespace arm_compute
|
|
#endif /* ARM_COMPUTE_TEST_MEASUREMENT */
|