You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

117 lines
4.2 KiB
C

1 month ago
/*------------------------------------------------------------------------------
* Copyright (c) 2023 by Bai Bing (seread@163.com)
* See COPYING file for copying and redistribution conditions.
*
* Alians IT Studio.
*----------------------------------------------------------------------------*/
#pragma once
#include <cmath>
#include <complex>
#include <string>
#include "core/DataTypeInfo.h"
#include "core/TypeTraits.h"
namespace ais
{
namespace utils
{
//============================================================================
/// tests that 2 integer values are "essentially equal"
///
/// @param value1
/// @param value2
///
/// @return bool
///
template <typename dtype, enable_if_t<std::is_integral<dtype>::value, int> = 0>
bool essentially_equal(dtype value1, dtype value2) noexcept
{
return value1 == value2;
}
//============================================================================
/// tests that 2 floating point values are "essentially equal"
///
/// @param value1
/// @param value2
/// @param inEpsilon
///
/// @return bool
///
template <typename dtype, enable_if_t<std::is_floating_point<dtype>::value, int> = 0>
bool essentially_equal(dtype value1, dtype value2, dtype inEpsilon) noexcept
{
// const auto absValue1 = std::abs(value1);
// const auto absValue2 = std::abs(value2);
// return std::abs(value1 - value2) <=
// ((absValue1 > absValue2 ? absValue2 : absValue1) * std::abs(inEpsilon));
return (std::fabs(value1 - value2) <= std::abs(inEpsilon));
}
//============================================================================
/// tests that 2 complex values are "essentially equal"
///
/// @param value1
/// @param value2
///
/// @return bool
///
template <typename dtype, enable_if_t<std::is_integral<dtype>::value, int> = 0>
bool essentially_equal(const std::complex<dtype> &value1, const std::complex<dtype> &value2) noexcept
{
return value1 == value2;
}
//============================================================================
/// tests that 2 complex values are "essentially equal"
///
/// @param value1
/// @param value2
/// @param inEpsilon
///
/// @return bool
///
template <typename dtype, enable_if_t<std::is_floating_point<dtype>::value, int> = 0>
bool essentially_equal(const std::complex<dtype> &value1,
const std::complex<dtype> &value2,
const std::complex<dtype> &inEpsilon) noexcept
{
const auto absValue1 = std::abs(value1);
const auto absValue2 = std::abs(value2);
return std::abs(value1 - value2) <=
((absValue1 > absValue2 ? absValue2 : absValue1) * std::abs(inEpsilon));
}
//============================================================================
/// tests that 2 floating point values are "essentially equal"
///
/// @param value1
/// @param value2
///
/// @return bool
///
template <typename dtype, enable_if_t<std::is_floating_point<dtype>::value, int> = 0>
bool essentially_equal(dtype value1, dtype value2) noexcept
{
return essentially_equal(value1, value2, DataTypeInfo<dtype>::epsilon());
}
//============================================================================
/// tests that 2 floating point values are "essentially equal"
///
/// @param value1
/// @param value2
///
/// @return bool
///
template <typename dtype, enable_if_t<std::is_floating_point<dtype>::value, int> = 0>
bool essentially_equal(const std::complex<dtype> &value1, const std::complex<dtype> &value2) noexcept
{
return essentially_equal(value1, value2, DataTypeInfo<std::complex<dtype>>::epsilon());
}
} // namespace utils
} // namespace ais