blob: 2ec68d424bd8fabc67c860f713f18781e0be3feb [file] [log] [blame]
/*
* Copyright (c) 2017-2018,2021 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 */