Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <type_traits>
- #include <atomic>
- template<typename _Ty, _Ty... _Mod>
- class atomic_cyclic_number;
- template<typename _Ty, _Ty... _Mod>
- class cyclic_number;
- template<typename _Ty, _Ty _Mod>
- class cyclic_number<_Ty, _Mod>
- {
- static_assert(std::is_integral<_Ty>::value, "Error: 'cyclic_number<_Ty, _Mod>' type must be integral.");
- static_assert(_Mod > (_Ty)1, "Error: 'cyclic_number<_Ty, _Mod>' modulus must be greater than one.");
- public:
- using type = cyclic_number<_Ty, _Mod>;
- using value_type = std::remove_cv_t<_Ty>;
- static constexpr value_type modulus{ _Mod };
- inline constexpr cyclic_number() : value_{ _0_ } { }
- inline constexpr cyclic_number(const value_type & _value) : value_{ normalize(_value) } { }
- inline constexpr cyclic_number(value_type && _value) : value_{ normalize(std::move(_value)) } { }
- template<typename _Tp> operator _Tp&() const = delete;
- inline constexpr operator const value_type&() const { return value_; }
- inline constexpr const value_type & value() const { return value_; }
- inline void value(const value_type & _value) { value_ = normalize(_value); }
- inline constexpr bool operator==(const value_type & number) const { return (value_ == normalize(number)); }
- inline constexpr bool operator!=(const value_type & number) const { return (value_ != normalize(number)); }
- inline constexpr bool operator==(value_type && number) const { return (value_ == normalize(std::move(number))); }
- inline constexpr bool operator!=(value_type && number) const { return (value_ != normalize(std::move(number))); }
- inline type & operator++() { (value_ < modulus_minus_1_) ? (++value_) : (value_ -= modulus_minus_1_); return *this; }
- inline type & operator--() { (value_ > _0_) ? (--value_) : (value_ += modulus_minus_1_); return *this; }
- inline type operator++(int) { type result(*this); operator++(); return result; }
- inline type operator--(int) { type result(*this); operator--(); return result; }
- inline type & operator*=(const value_type & number) { value_ = normalize(value_ * number); return *this; }
- inline type & operator+=(const value_type & number) { value_ = normalize(value_ + number); return *this; }
- inline type & operator-=(const value_type & number) { value_ = normalize(value_ - number); return *this; }
- inline constexpr type forward_distance_to(const value_type & number) const { return forward_distance(value_, number); }
- inline constexpr type reverse_distance_to(const value_type & number) const { return reverse_distance(value_, number); }
- inline constexpr type minimum_distance_to(const value_type & number) const { return minimum_distance(value_, number); }
- static inline constexpr bool is_valid(const value_type & value) { return ((value >= _0_) && (value < modulus)); }
- static inline constexpr value_type & normalize(value_type & value)
- {
- return (value >= modulus ? (value -= modulus * (value / modulus)) :
- (value < _0_ ? (value += modulus * (_1_ - value / modulus)) : value));
- }
- static inline constexpr value_type && normalize(value_type && value)
- {
- return std::move(value >= modulus ? (value -= modulus * (value / modulus)) :
- (value < _0_ ? (value += modulus * (_1_ - value / modulus)) : value));
- }
- static inline constexpr value_type normalize(const value_type & value)
- {
- return (value >= modulus ? (value - modulus * (value / modulus)) :
- (value < _0_ ? (value + modulus * (_1_ - value / modulus)) : value));
- }
- static inline constexpr type forward_distance(const value_type & begin, const value_type & end)
- {
- return valid_number_t(end >= begin ?
- normalize(end - begin) : (value_type)(modulus - normalize(begin - end)));
- }
- static inline constexpr type reverse_distance(const value_type & begin, const value_type & end)
- {
- return valid_number_t(begin >= end ?
- normalize(begin - end) : (value_type)(modulus - normalize(end - begin)));
- }
- static inline constexpr type minimum_distance(const value_type & num1, const value_type & num2)
- {
- return valid_number_t(num1 >= num2 ?
- minimum_distance_to_zero_(normalize(num1 - num2)) :
- minimum_distance_to_zero_(normalize(num2 - num1)));
- }
- protected:
- friend atomic_cyclic_number<value_type, modulus>;
- class valid_number_t
- {
- public:
- inline constexpr explicit valid_number_t(const value_type & _value) : value_{ _value } { }
- const value_type & value_;
- };
- static constexpr value_type _0_{ (value_type)0 };
- static constexpr value_type _1_{ (value_type)1 };
- static constexpr value_type modulus_minus_1_{ (value_type)(_Mod - _1_) };
- inline constexpr cyclic_number(const valid_number_t & valid_value) : value_{ valid_value.value_ } { }
- static inline constexpr const value_type && minimum_(const value_type && v1, const value_type && v2) { return std::move(v1 <= v2 ? v1 : v2); }
- static inline constexpr const value_type && minimum_distance_to_zero_(const value_type && num) { return minimum_(std::move(num), (value_type)(modulus - num)); }
- value_type value_;
- };
- template<typename _Ty>
- class cyclic_number<_Ty>
- {
- static_assert(std::is_integral<_Ty>::value, "Error: 'cyclic_number<_Ty>' type must be integral.");
- public:
- using type = cyclic_number<_Ty>;
- using value_type = std::remove_cv_t<_Ty>;
- inline constexpr explicit cyclic_number(const value_type & _modulus) :
- modulus_{ (_modulus < _1_) ? throw std::invalid_argument("invalid_argument") : _modulus },
- value_{ _0_ } { }
- inline constexpr cyclic_number(const value_type & _modulus, const value_type & _value) :
- modulus_{ (_modulus < _1_) ? throw std::invalid_argument("invalid_argument") : _modulus },
- value_{ normalize(_value, _modulus) } { }
- inline constexpr cyclic_number(const value_type & _modulus, value_type && _value) :
- modulus_{ (_modulus < _1_) ? throw std::invalid_argument("invalid_argument") : _modulus },
- value_{ normalize(std::move(_value), _modulus) } { }
- template<typename _Tp> operator _Tp&() const = delete;
- inline constexpr operator const value_type&() const { return value_; }
- inline constexpr const value_type & value() const { return value_; }
- inline void value(const value_type & _value) { value_ = normalize(_value, modulus_); }
- inline constexpr bool operator==(const value_type & number) const { return (value_ == normalize(number, modulus_)); }
- inline constexpr bool operator!=(const value_type & number) const { return (value_ != normalize(number, modulus_)); }
- inline constexpr bool operator==(value_type && number) const { return (value_ == normalize(std::move(number), modulus_)); }
- inline constexpr bool operator!=(value_type && number) const { return (value_ != normalize(std::move(number), modulus_)); }
- inline type & operator++() { (value_ < (value_type)(modulus_ - _1_)) ? (++value_) : (value_ -= (value_type)(modulus_ - _1_)); return *this; }
- inline type & operator--() { (value_ > _0_) ? (--value_) : (value_ += (value_type)(modulus_ - _1_)); return *this; }
- inline value_type operator++(int) { value_type result = this->value_; operator++(); return result; }
- inline value_type operator--(int) { value_type result = this->value_; operator--(); return result; }
- inline type & operator*=(const value_type & number) { value_ = normalize(value_ * number, modulus_); return *this; }
- inline type & operator+=(const value_type & number) { value_ = normalize(value_ + number, modulus_); return *this; }
- inline type & operator-=(const value_type & number) { value_ = normalize(value_ - number, modulus_); return *this; }
- inline constexpr value_type forward_distance_to(const value_type & number) const { return forward_distance(value_, number, modulus_); }
- inline constexpr value_type reverse_distance_to(const value_type & number) const { return reverse_distance(value_, number, modulus_); }
- inline constexpr value_type minimum_distance_to(const value_type & number) const { return minimum_distance(value_, number, modulus_); }
- static inline constexpr bool is_valid(const value_type & value, const value_type & modulus) { return ((value >= _0_) && (value < modulus)); }
- static inline constexpr value_type & normalize(value_type & value, const value_type & modulus)
- {
- return (value >= modulus ? (value -= modulus * (value / modulus)) :
- (value < _0_ ? (value += modulus * (_1_ - value / modulus)) : value));
- }
- static inline constexpr value_type && normalize(value_type && value, const value_type & modulus)
- {
- return std::move(value >= modulus ? (value -= modulus * (value / modulus)) :
- (value < _0_ ? (value += modulus * (_1_ - value / modulus)) : value));
- }
- static inline constexpr value_type normalize(const value_type & value, const value_type & modulus)
- {
- return (value >= modulus ? (value - modulus * (value / modulus)) :
- (value < _0_ ? (value + modulus * (_1_ - value / modulus)) : value));
- }
- static inline constexpr value_type forward_distance(const value_type & begin, const value_type & end, const value_type & modulus)
- {
- return (end >= begin ?
- normalize(end - begin, modulus) :
- (value_type)(modulus - normalize(begin - end, modulus)));
- }
- static inline constexpr value_type reverse_distance(const value_type & begin, const value_type & end, const value_type & modulus)
- {
- return (begin >= end ?
- normalize(begin - end, modulus) :
- (value_type)(modulus - normalize(end - begin, modulus)));
- }
- static inline constexpr value_type minimum_distance(const value_type & num1, const value_type & num2, const value_type & modulus)
- {
- return (num1 >= num2 ?
- minimum_distance_to_zero_(normalize(num1 - num2, modulus), modulus) :
- minimum_distance_to_zero_(normalize(num2 - num1, modulus), modulus));
- }
- protected:
- static constexpr value_type _0_{ (value_type)0 };
- static constexpr value_type _1_{ (value_type)1 };
- static inline constexpr const value_type && minimum_(const value_type && v1, const value_type && v2)
- {
- return std::move(v1 <= v2 ? v1 : v2);
- }
- static inline constexpr const value_type && minimum_distance_to_zero_(const value_type && num, const value_type & modulus)
- {
- return minimum_(std::move(num), (value_type)(modulus - num));
- }
- value_type value_;
- const value_type modulus_;
- };
- template<typename _Ty, _Ty _Mod>
- class atomic_cyclic_number<_Ty, _Mod>
- {
- static_assert(std::is_integral<_Ty>::value, "Error: 'atomic_cyclic_number<_Ty, _Mod>' type must be integral.");
- static_assert(_Mod > (_Ty)1, "Error: 'atomic_cyclic_number<_Ty, _Mod>' modulus must be greater than one.");
- public:
- using noatomic_type = cyclic_number<_Ty, _Mod>;
- using type = atomic_cyclic_number<_Ty, _Mod>;
- using value_type = std::remove_cv_t<_Ty>;
- static constexpr value_type modulus{ _Mod };
- inline constexpr atomic_cyclic_number() : value_{ _0_ } { }
- inline constexpr atomic_cyclic_number(const value_type & _value) : value_{ normalize(_value) } { }
- inline constexpr atomic_cyclic_number(value_type && _value) : value_{ normalize(std::move(_value)) } { }
- template<typename _Tp> operator _Tp&() const = delete;
- inline constexpr operator const value_type&() const { return value_; }
- inline constexpr const value_type & value() const { return value_; }
- inline void value(const value_type & _value) { value_ = normalize(_value); }
- inline void value(value_type && _value) { value_ = normalize(std::move(_value)); }
- inline constexpr bool operator==(const value_type & number) const { return (value_ == normalize(number)); }
- inline constexpr bool operator!=(const value_type & number) const { return (value_ != normalize(number)); }
- inline constexpr bool operator==(value_type && number) const { return (value_ == normalize(std::move(number))); }
- inline constexpr bool operator!=(value_type && number) const { return (value_ != normalize(std::move(number))); }
- inline noatomic_type operator++()
- {
- value_type capture = value_;
- do
- {
- value_type && draft = ((capture < modulus_minus_1_) ? (capture + _1_) : (capture - modulus_minus_1_));
- if (value_.compare_exchange_weak(capture, draft))
- return noatomic_type::valid_number_t(draft);
- } while (true);
- }
- inline noatomic_type operator--()
- {
- value_type capture = value_;
- do
- {
- value_type && draft = ((capture > _0_) ? (capture - _1_) : (capture + modulus_minus_1_));
- if (value_.compare_exchange_weak(capture, draft))
- return noatomic_type::valid_number_t(draft);
- } while (true);
- }
- inline noatomic_type operator++(int)
- {
- value_type capture = value_;
- while (!value_.compare_exchange_weak(capture, (capture < modulus_minus_1_) ? (capture + _1_) : (capture - modulus_minus_1_)));
- return noatomic_type::valid_number_t(capture);
- }
- inline noatomic_type operator--(int)
- {
- value_type capture = value_;
- while (!value_.compare_exchange_weak(capture, (capture > _0_) ? (capture - _1_) : (capture + modulus_minus_1_)));
- return noatomic_type::valid_number_t(capture);
- }
- inline noatomic_type operator*=(const value_type & number)
- {
- value_type capture = value_;
- do
- {
- value_type && draft = normalize(capture * number);
- if (value_.compare_exchange_weak(capture, draft))
- return noatomic_type::valid_number_t(draft);
- } while (true);
- }
- inline noatomic_type operator+=(const value_type & number)
- {
- value_type capture = value_;
- do
- {
- value_type && draft = normalize(capture + number);
- if (value_.compare_exchange_weak(capture, draft))
- return noatomic_type::valid_number_t(draft);
- } while (true);
- }
- inline noatomic_type operator-=(const value_type & number)
- {
- value_type capture = value_;
- do
- {
- value_type && draft = normalize(capture - number);
- if (value_.compare_exchange_weak(capture, draft))
- return noatomic_type::valid_number_t(draft);
- } while (true);
- }
- inline constexpr noatomic_type forward_distance_to(const value_type & number) const { return forward_distance(value_, number); }
- inline constexpr noatomic_type reverse_distance_to(const value_type & number) const { return reverse_distance(value_, number); }
- inline constexpr noatomic_type minimum_distance_to(const value_type & number) const { return minimum_distance(value_, number); }
- static inline constexpr bool is_valid(const value_type & value) { return ((value >= _0_) && (value < modulus)); }
- static inline constexpr value_type & normalize(value_type & value)
- {
- return (value >= modulus ? (value -= modulus * (value / modulus)) :
- (value < _0_ ? (value += modulus * (_1_ - value / modulus)) : value));
- }
- static inline constexpr value_type && normalize(value_type && value)
- {
- return std::move(value >= modulus ? (value -= modulus * (value / modulus)) :
- (value < _0_ ? (value += modulus * (_1_ - value / modulus)) : value));
- }
- static inline constexpr value_type normalize(const value_type & value)
- {
- return (value >= modulus ? (value - modulus * (value / modulus)) :
- (value < _0_ ? (value + modulus * (_1_ - value / modulus)) : value));
- }
- static inline constexpr noatomic_type forward_distance(const value_type & begin, const value_type & end)
- {
- return noatomic_type::valid_number_t(end >= begin ?
- normalize(end - begin) : (value_type)(modulus - normalize(begin - end)));
- }
- static inline constexpr noatomic_type reverse_distance(const value_type & begin, const value_type & end)
- {
- return noatomic_type::valid_number_t(begin >= end ?
- normalize(begin - end) : (value_type)(modulus - normalize(end - begin)));
- }
- static inline constexpr noatomic_type minimum_distance(const value_type & num1, const value_type & num2)
- {
- return noatomic_type::valid_number_t(num1 >= num2 ?
- minimum_distance_to_zero_(normalize(num1 - num2)) :
- minimum_distance_to_zero_(normalize(num2 - num1)));
- }
- protected:
- static constexpr value_type _0_{ (value_type)0 };
- static constexpr value_type _1_{ (value_type)1 };
- static constexpr value_type modulus_minus_1_{ (value_type)(_Mod - _1_) };
- static inline constexpr const value_type && minimum_(const value_type && v1, const value_type && v2) { return std::move(v1 <= v2 ? v1 : v2); }
- static inline constexpr const value_type && minimum_distance_to_zero_(const value_type && num) { return minimum_(std::move(num), (value_type)(modulus - num)); }
- std::atomic<value_type> value_;
- };
- template<typename _Ty>
- class atomic_cyclic_number<_Ty>
- {
- static_assert(std::is_integral<_Ty>::value, "Error: 'atomic_cyclic_number<_Ty>' type must be integral.");
- public:
- using type = atomic_cyclic_number<_Ty>;
- using value_type = std::remove_cv_t<_Ty>;
- inline constexpr explicit atomic_cyclic_number(const value_type & _modulus) :
- modulus_{ (_modulus < _1_) ? throw std::invalid_argument("invalid_argument") : _modulus },
- value_{ _0_ } { }
- inline constexpr atomic_cyclic_number(const value_type & _modulus, const value_type & _value) :
- modulus_{ (_modulus < _1_) ? throw std::invalid_argument("invalid_argument") : _modulus },
- value_{ normalize(_value, _modulus) } { }
- inline constexpr atomic_cyclic_number(const value_type & _modulus, value_type && _value) :
- modulus_{ (_modulus < _1_) ? throw std::invalid_argument("invalid_argument") : _modulus },
- value_{ normalize(std::move(_value), _modulus) } { }
- template<typename _Tp> operator _Tp&() const = delete;
- inline constexpr operator const value_type&() const { return value_; }
- inline constexpr const value_type & value() const { return value_; }
- inline void value(const value_type & _value) { value_ = normalize(_value, modulus_); }
- inline void value(value_type && _value) { value_ = normalize(std::move(_value), modulus_); }
- inline constexpr bool operator==(const value_type & number) const { return (value_ == normalize(number, modulus_)); }
- inline constexpr bool operator!=(const value_type & number) const { return (value_ != normalize(number, modulus_)); }
- inline constexpr bool operator==(value_type && number) const { return (value_ == normalize(std::move(number), modulus_)); }
- inline constexpr bool operator!=(value_type && number) const { return (value_ != normalize(std::move(number), modulus_)); }
- inline value_type operator++()
- {
- value_type capture = value_;
- do
- {
- value_type && draft = ((capture < (value_type)(modulus_ - _1_)) ? (capture + _1_) : (capture - (value_type)(modulus_ - _1_)));
- if (value_.compare_exchange_weak(capture, draft))
- return draft;
- } while (true);
- }
- inline value_type operator--()
- {
- value_type capture = value_;
- do
- {
- value_type && draft = ((capture > _0_) ? (capture - _1_) : (capture + (value_type)(modulus_ - _1_)));
- if (value_.compare_exchange_weak(capture, draft))
- return draft;
- } while (true);
- }
- inline value_type operator++(int)
- {
- value_type capture = value_;
- while (!value_.compare_exchange_weak(capture, (capture < (value_type)(modulus_ - _1_)) ? (capture + _1_) : (capture - (value_type)(modulus_ - _1_))));
- return capture;
- }
- inline value_type operator--(int)
- {
- value_type capture = value_;
- while (!value_.compare_exchange_weak(capture, (capture > _0_) ? (capture - _1_) : (capture + (value_type)(modulus_ - _1_))));
- return capture;
- }
- inline value_type operator*=(const value_type & number)
- {
- value_type capture = value_;
- do
- {
- value_type && draft = normalize(capture * number, modulus_);
- if (value_.compare_exchange_weak(capture, draft))
- return draft;
- } while (true);
- }
- inline value_type operator+=(const value_type & number)
- {
- value_type capture = value_;
- do
- {
- value_type && draft = normalize(capture + number, modulus_);
- if (value_.compare_exchange_weak(capture, draft))
- return draft;
- } while (true);
- }
- inline value_type operator-=(const value_type & number)
- {
- value_type capture = value_;
- do
- {
- value_type && draft = normalize(capture - number, modulus_);
- if (value_.compare_exchange_weak(capture, draft))
- return draft;
- } while (true);
- }
- inline constexpr value_type forward_distance_to(const value_type & number) const { return forward_distance(value_, number, modulus_); }
- inline constexpr value_type reverse_distance_to(const value_type & number) const { return reverse_distance(value_, number, modulus_); }
- inline constexpr value_type minimum_distance_to(const value_type & number) const { return minimum_distance(value_, number, modulus_); }
- static inline constexpr bool is_valid(const value_type & value, const value_type & modulus) { return ((value >= _0_) && (value < modulus)); }
- static inline constexpr value_type & normalize(value_type & value, const value_type & modulus)
- {
- return (value >= modulus ? (value -= modulus * (value / modulus)) :
- (value < _0_ ? (value += modulus * (_1_ - value / modulus)) : value));
- }
- static inline constexpr value_type && normalize(value_type && value, const value_type & modulus)
- {
- return std::move(value >= modulus ? (value -= modulus * (value / modulus)) :
- (value < _0_ ? (value += modulus * (_1_ - value / modulus)) : value));
- }
- static inline constexpr value_type normalize(const value_type & value, const value_type & modulus)
- {
- return (value >= modulus ? (value - modulus * (value / modulus)) :
- (value < _0_ ? (value + modulus * (_1_ - value / modulus)) : value));
- }
- static inline constexpr value_type forward_distance(const value_type & begin, const value_type & end, const value_type & modulus)
- {
- return (end >= begin ?
- normalize(end - begin, modulus) :
- (value_type)(modulus - normalize(begin - end, modulus)));
- }
- static inline constexpr value_type reverse_distance(const value_type & begin, const value_type & end, const value_type & modulus)
- {
- return (begin >= end ?
- normalize(begin - end, modulus) :
- (value_type)(modulus - normalize(end - begin, modulus)));
- }
- static inline constexpr value_type minimum_distance(const value_type & num1, const value_type & num2, const value_type & modulus)
- {
- return (num1 >= num2 ?
- minimum_distance_to_zero_(normalize(num1 - num2, modulus), modulus) :
- minimum_distance_to_zero_(normalize(num2 - num1, modulus), modulus));
- }
- protected:
- static constexpr value_type _0_{ (value_type)0 };
- static constexpr value_type _1_{ (value_type)1 };
- static inline constexpr const value_type && minimum_(const value_type && v1, const value_type && v2)
- {
- return std::move(v1 <= v2 ? v1 : v2);
- }
- static inline constexpr const value_type && minimum_distance_to_zero_(const value_type && num, const value_type & modulus)
- {
- return minimum_(std::move(num), (value_type)(modulus - num));
- }
- std::atomic<value_type> value_;
- const value_type modulus_;
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement