头文件:
cpp
#ifndef LIBSCL_UTILITY_H_
#define LIBSCL_UTILITY_H_
//////////////////////////////////////////////////////////////////////////
#include "base.h"
#include <type_traits>
#include <limits>
#include <istream>
#include <ostream>
//////////////////////////////////////////////////////////////////////////
namespace scl {
//////////////////////////////////////////////////////////////////////////
bool float_equal(double a, double b, double eps = 1e-9) noexcept;
bool float_greater(double a, double b, double eps = 1e-9) noexcept;
bool float_greater_equal(double a, double b, double eps = 1e-9) noexcept;
bool float_less(double a, double b, double eps = 1e-9) noexcept;
bool float_less_equal(double a, double b, double eps = 1e-9) noexcept;
double float_round_one(double a) noexcept;
double float_round_two(double a) noexcept;
double float_round_three(double a) noexcept;
double float_round_four(double a) noexcept;
double float_round_five(double a) noexcept;
double float_round_six(double a) noexcept;
double float_round(double a, int precision) noexcept;
//////////////////////////////////////////////////////////////////////////
class float_num_t {
public:
double value = 0.0;
public:
float_num_t() noexcept {
}
float_num_t(const double &val) noexcept
: value(val) {
}
float_num_t &operator=(const double &val) noexcept {
value = val;
return *this;
}
operator double() const noexcept {
return value;
}
/// <
template <typename T>
bool operator<(const T &val) const noexcept {
return float_less(value, static_cast<double>(val));
}
/// <=
template <typename T>
bool operator<=(const T &val) const noexcept {
return float_less_equal(value, static_cast<double>(val));
}
/// >
template <typename T>
bool operator>(const T &val) const noexcept {
return float_greater(value, static_cast<double>(val));
}
/// >=
template <typename T>
bool operator>=(const T &val) const noexcept {
return float_greater_equal(value, static_cast<double>(val));
}
/// ==
template <typename T>
bool operator==(const T &val) const noexcept {
return float_equal(value, static_cast<double>(val));
}
/// +
template <typename T>
float_num_t operator+(const T &val) noexcept {
return float_num_t(value + static_cast<double>(val));
}
/// +=
template <typename T>
float_num_t &operator+=(const T &val) noexcept {
value += static_cast<double>(val);
return *this;
}
/// -
template <typename T>
float_num_t operator-(const T &val) noexcept {
return float_num_t(value - static_cast<double>(val));
}
/// -=
template <typename T>
float_num_t &operator-=(const T &val) noexcept {
value -= static_cast<double>(val);
return *this;
}
/// *
template <typename T>
float_num_t operator*(const T &val) noexcept {
return float_num_t(value * static_cast<double>(val));
}
/// *=
template <typename T>
float_num_t &operator*=(const T &val) noexcept {
value *= static_cast<double>(val);
return *this;
}
/// /
template <typename T>
float_num_t operator/(const T &val) noexcept {
return float_num_t(value / static_cast<double>(val));
}
/// /=
template <typename T>
float_num_t &operator/=(const T &val) noexcept {
value /= static_cast<double>(val);
return *this;
}
float_num_t &round_one() noexcept {
value = float_round_one(value);
return *this;
}
float_num_t &round_two() noexcept {
value = float_round_two(value);
return *this;
}
float_num_t &round_three() noexcept {
value = float_round_three(value);
return *this;
}
float_num_t &round_four() noexcept {
value = float_round_four(value);
return *this;
}
float_num_t &round_five() noexcept {
value = float_round_five(value);
return *this;
}
float_num_t &round_six() noexcept {
value = float_round_six(value);
return *this;
}
float_num_t &round(int precision) noexcept {
value = float_round(value, precision);
return *this;
}
/// >>
friend std::ostream &operator<<(std::ostream &os, const float_num_t &v) noexcept {
os << v.value;
return os;
}
/// <<
friend std::istream &operator>>(std::istream &is, float_num_t &v) noexcept {
is >> v.value;
return is;
}
};
//////////////////////////////////////////////////////////////////////////
template <typename T>
class range_t {
public:
T min = std::numeric_limits<T>::min();
T max = std::numeric_limits<T>::max();
public:
range_t() noexcept {
}
range_t(T first, T last) noexcept
: min(first), max(last) {
clean();
}
range_t(const std::pair<T, T> &p) noexcept
: min(p.first), max(p.second) {
clean();
}
range_t &operator=(const range_t &p) noexcept {
if (&p != this) {
min = p.min;
max = p.max;
clean();
}
return *this;
}
range_t &operator=(const std::pair<T, T> &p) noexcept {
min = p.first;
max = p.second;
clean();
return *this;
}
bool contains(T v) const noexcept {
if constexpr (std::is_floating_point_v<T>) {
return float_greater_equal(v, min) && float_less_equal(v, max);
}
return min <= v && v <= max;
}
bool min_limits() const noexcept {
return min == std::numeric_limits<T>::min();
}
bool max_limits() const noexcept {
return max == std::numeric_limits<T>::max();
}
void clean() noexcept {
if constexpr (std::is_floating_point_v<T>) {
if (float_greater(min, max)) {
std::swap(min, max);
}
} else {
if (min > max) {
std::swap(min, max);
}
}
}
};
template <>
inline bool range_t<float_num_t>::min_limits() const noexcept {
return min.value == std::numeric_limits<double>::min();
}
template <>
inline bool range_t<float_num_t>::max_limits() const noexcept {
return max.value == std::numeric_limits<double>::max();
}
template <typename T>
range_t<T> make_range(T first, T last) noexcept {
return range_t<T>(first, last);
}
//////////////////////////////////////////////////////////////////////////
template <typename T>
class Singleton {
public:
Singleton() {
if (singleton_ != nullptr) {
throw std::runtime_error("Singleton constructor should only be called once");
}
singleton_ = static_cast<T *>(this);
}
virtual ~Singleton() noexcept {
singleton_ = nullptr;
}
DISABLE_COPY_AND_ASSIGN(Singleton)
static T *instance() noexcept {
return singleton_;
}
private:
static T *singleton_;
};
template <typename T>
T *Singleton<T>::singleton_ = nullptr;
//////////////////////////////////////////////////////////////////////////
uint16_t make_word(uint8_t l, uint8_t h) noexcept;
uint8_t low_byte(uint16_t v) noexcept;
uint8_t high_byte(uint16_t v) noexcept;
uint32_t make_dword(uint16_t l, uint16_t h) noexcept;
uint16_t low_word(uint32_t v) noexcept;
uint16_t high_word(uint32_t v) noexcept;
uint64_t make_qword(uint32_t l, uint32_t h) noexcept;
uint32_t low_dword(uint64_t v) noexcept;
uint32_t high_dword(uint64_t v) noexcept;
//////////////////////////////////////////////////////////////////////////
void random_seed(unsigned int seed) noexcept;
int random_range_value(int min, int max) noexcept;
double random_float_value(unsigned int precision) noexcept;
//////////////////////////////////////////////////////////////////////////
class random_t {
public:
random_t(unsigned int seed = 0) noexcept;
virtual ~random_t() noexcept;
public:
int range_value(int min, int max) noexcept;
double float_value(unsigned int precision) noexcept;
private:
unsigned int seed_;
};
//////////////////////////////////////////////////////////////////////////
} // namespace scl
//////////////////////////////////////////////////////////////////////////
// std::numeric_limits for scl::float_num_t
template <>
struct std::numeric_limits<scl::float_num_t> {
static constexpr double min() noexcept {
return std::numeric_limits<double>::min();
}
static constexpr double max() noexcept {
return std::numeric_limits<double>::max();
}
};
//////////////////////////////////////////////////////////////////////////
#endif // !LIBSCL_UTILITY_H_
源文件:
cpp
#include "utility.h"
#include <cmath>
#include <ctime>
//////////////////////////////////////////////////////////////////////////
namespace scl {
//////////////////////////////////////////////////////////////////////////
bool float_equal(double a, double b, double eps /*= 1e-9*/) noexcept {
return std::abs(a - b) < eps;
}
bool float_greater(double a, double b, double eps /*= 1e-9*/) noexcept {
return a - b > eps;
}
bool float_greater_equal(double a, double b, double eps /*= 1e-9*/) noexcept {
return a - b > -eps;
}
bool float_less(double a, double b, double eps /*= 1e-9*/) noexcept {
return b - a > eps;
}
bool float_less_equal(double a, double b, double eps /*= 1e-9*/) noexcept {
return b - a > -eps;
}
double float_round_one(double a) noexcept {
return std::round(a * 10.0) / 10.0;
}
double float_round_two(double a) noexcept {
return std::round(a * 100.0) / 100.0;
}
double float_round_three(double a) noexcept {
return std::round(a * 1'000.0) / 1'000.0;
}
double float_round_four(double a) noexcept {
return std::round(a * 10'000.0) / 10'000.0;
}
double float_round_five(double a) noexcept {
return std::round(a * 100'000.0) / 100'000.0;
}
double float_round_six(double a) noexcept {
return std::round(a * 1'000'000.0) / 1'000'000.0;
}
double float_round(double a, int precision) noexcept {
double m = std::pow(10.0, precision);
return std::round(a * m) / m;
}
//////////////////////////////////////////////////////////////////////////
uint16_t make_word(uint8_t l, uint8_t h) noexcept {
return static_cast<uint16_t>(l & 0xff) | static_cast<uint16_t>((h & 0xff) << 8);
}
uint8_t low_byte(uint16_t v) noexcept {
return static_cast<uint8_t>(v & 0xff);
}
uint8_t high_byte(uint16_t v) noexcept {
return static_cast<uint8_t>(v >> 8 & 0xff);
}
uint32_t make_dword(uint16_t l, uint16_t h) noexcept {
return static_cast<uint32_t>(l & 0xffff) | static_cast<uint32_t>((h & 0xffff) << 16);
}
uint16_t low_word(uint32_t v) noexcept {
return static_cast<uint16_t>(v & 0xffff);
}
uint16_t high_word(uint32_t v) noexcept {
return static_cast<uint16_t>((v >> 16) & 0xffff);
}
uint64_t make_qword(uint32_t l, uint32_t h) noexcept {
uint64_t v = 0;
uint32_t *pv = reinterpret_cast<uint32_t *>(&v);
pv[0] = l & 0xffffffff;
pv[1] = h & 0xffffffff;
return v;
}
uint32_t low_dword(uint64_t v) noexcept {
uint32_t *pv = reinterpret_cast<uint32_t *>(&v);
return static_cast<uint32_t>(pv[0] & 0xffffffff);
}
uint32_t high_dword(uint64_t v) noexcept {
uint32_t *pv = reinterpret_cast<uint32_t *>(&v);
return static_cast<uint32_t>(pv[1] & 0xffffffff);
}
//////////////////////////////////////////////////////////////////////////
void random_seed(unsigned int seed) noexcept {
if (seed == 0) {
seed = static_cast<unsigned int>((std::time(nullptr) << 16) * 1664525L + 1013904223L);
}
std::srand(seed);
}
int random_range_value(int min, int max) noexcept {
double ratio = (std::rand() * 1.0) / (RAND_MAX + 1.0);
if (min < max) {
return static_cast<int>(ratio * (max - min + 1.0) + min);
} else if (min > max) {
return static_cast<int>(ratio * (min - max + 1.0) + max);
} else {
return min;
}
}
double random_float_value(unsigned int precision) noexcept {
if (precision == 0) {
precision = RAND_MAX;
}
return (random_range_value(0, precision) * 1.0) / (precision + 1.0);
}
//////////////////////////////////////////////////////////////////////////
namespace {
int update_seed(unsigned int *seed) noexcept {
*seed = *seed * 1103515245 + 12345;
return ((unsigned)(*seed / 65536) % 32768);
}
} // namespace
random_t::random_t(unsigned int seed /*= 0*/) noexcept {
if (seed == 0) {
seed = (unsigned int)((std::time(nullptr) << 16) * 1664525L + 1013904223L);
}
seed_ = seed;
}
random_t::~random_t() noexcept {
}
int random_t::range_value(int min, int max) noexcept {
double ratio = (update_seed(&seed_) * 1.0) / (32767 + 1.0);
if (min < max) {
return static_cast<int>(ratio * (max - min + 1.0) + min);
} else if (min > max) {
return static_cast<int>(ratio * (min - max + 1.0) + max);
} else {
return min;
}
}
double random_t::float_value(unsigned int precision) noexcept {
if (precision == 0) {
precision = 32767;
}
return (range_value(0, precision) * 1.0) / (precision + 1.0);
}
//////////////////////////////////////////////////////////////////////////
} // namespace scl
//////////////////////////////////////////////////////////////////////////