Advertisement
Guest User

Untitled

a guest
Sep 18th, 2019
94
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 21.85 KB | None | 0 0
  1. #include <type_traits>
  2. #include <atomic>
  3.  
  4. template<typename _Ty, _Ty... _Mod>
  5. class atomic_cyclic_number;
  6.  
  7. template<typename _Ty, _Ty... _Mod>
  8. class cyclic_number;
  9.  
  10. template<typename _Ty, _Ty _Mod>
  11. class cyclic_number<_Ty, _Mod>
  12. {
  13. static_assert(std::is_integral<_Ty>::value, "Error: 'cyclic_number<_Ty, _Mod>' type must be integral.");
  14. static_assert(_Mod > (_Ty)1, "Error: 'cyclic_number<_Ty, _Mod>' modulus must be greater than one.");
  15.  
  16. public:
  17. using type = cyclic_number<_Ty, _Mod>;
  18. using value_type = std::remove_cv_t<_Ty>;
  19. static constexpr value_type modulus{ _Mod };
  20.  
  21. inline constexpr cyclic_number() : value_{ _0_ } { }
  22.  
  23. inline constexpr cyclic_number(const value_type & _value) : value_{ normalize(_value) } { }
  24.  
  25. inline constexpr cyclic_number(value_type && _value) : value_{ normalize(std::move(_value)) } { }
  26.  
  27. template<typename _Tp> operator _Tp&() const = delete;
  28.  
  29. inline constexpr operator const value_type&() const { return value_; }
  30.  
  31. inline constexpr const value_type & value() const { return value_; }
  32.  
  33. inline void value(const value_type & _value) { value_ = normalize(_value); }
  34.  
  35. inline constexpr bool operator==(const value_type & number) const { return (value_ == normalize(number)); }
  36.  
  37. inline constexpr bool operator!=(const value_type & number) const { return (value_ != normalize(number)); }
  38.  
  39. inline constexpr bool operator==(value_type && number) const { return (value_ == normalize(std::move(number))); }
  40.  
  41. inline constexpr bool operator!=(value_type && number) const { return (value_ != normalize(std::move(number))); }
  42.  
  43. inline type & operator++() { (value_ < modulus_minus_1_) ? (++value_) : (value_ -= modulus_minus_1_); return *this; }
  44.  
  45. inline type & operator--() { (value_ > _0_) ? (--value_) : (value_ += modulus_minus_1_); return *this; }
  46.  
  47. inline type operator++(int) { type result(*this); operator++(); return result; }
  48.  
  49. inline type operator--(int) { type result(*this); operator--(); return result; }
  50.  
  51. inline type & operator*=(const value_type & number) { value_ = normalize(value_ * number); return *this; }
  52.  
  53. inline type & operator+=(const value_type & number) { value_ = normalize(value_ + number); return *this; }
  54.  
  55. inline type & operator-=(const value_type & number) { value_ = normalize(value_ - number); return *this; }
  56.  
  57. inline constexpr type forward_distance_to(const value_type & number) const { return forward_distance(value_, number); }
  58.  
  59. inline constexpr type reverse_distance_to(const value_type & number) const { return reverse_distance(value_, number); }
  60.  
  61. inline constexpr type minimum_distance_to(const value_type & number) const { return minimum_distance(value_, number); }
  62.  
  63. static inline constexpr bool is_valid(const value_type & value) { return ((value >= _0_) && (value < modulus)); }
  64.  
  65. static inline constexpr value_type & normalize(value_type & value)
  66. {
  67. return (value >= modulus ? (value -= modulus * (value / modulus)) :
  68. (value < _0_ ? (value += modulus * (_1_ - value / modulus)) : value));
  69. }
  70.  
  71. static inline constexpr value_type && normalize(value_type && value)
  72. {
  73. return std::move(value >= modulus ? (value -= modulus * (value / modulus)) :
  74. (value < _0_ ? (value += modulus * (_1_ - value / modulus)) : value));
  75. }
  76.  
  77. static inline constexpr value_type normalize(const value_type & value)
  78. {
  79. return (value >= modulus ? (value - modulus * (value / modulus)) :
  80. (value < _0_ ? (value + modulus * (_1_ - value / modulus)) : value));
  81. }
  82.  
  83. static inline constexpr type forward_distance(const value_type & begin, const value_type & end)
  84. {
  85. return valid_number_t(end >= begin ?
  86. normalize(end - begin) : (value_type)(modulus - normalize(begin - end)));
  87. }
  88.  
  89. static inline constexpr type reverse_distance(const value_type & begin, const value_type & end)
  90. {
  91. return valid_number_t(begin >= end ?
  92. normalize(begin - end) : (value_type)(modulus - normalize(end - begin)));
  93. }
  94.  
  95. static inline constexpr type minimum_distance(const value_type & num1, const value_type & num2)
  96. {
  97. return valid_number_t(num1 >= num2 ?
  98. minimum_distance_to_zero_(normalize(num1 - num2)) :
  99. minimum_distance_to_zero_(normalize(num2 - num1)));
  100. }
  101.  
  102. protected:
  103. friend atomic_cyclic_number<value_type, modulus>;
  104.  
  105. class valid_number_t
  106. {
  107. public:
  108. inline constexpr explicit valid_number_t(const value_type & _value) : value_{ _value } { }
  109. const value_type & value_;
  110. };
  111.  
  112. static constexpr value_type _0_{ (value_type)0 };
  113. static constexpr value_type _1_{ (value_type)1 };
  114. static constexpr value_type modulus_minus_1_{ (value_type)(_Mod - _1_) };
  115.  
  116. inline constexpr cyclic_number(const valid_number_t & valid_value) : value_{ valid_value.value_ } { }
  117.  
  118. static inline constexpr const value_type && minimum_(const value_type && v1, const value_type && v2) { return std::move(v1 <= v2 ? v1 : v2); }
  119.  
  120. static inline constexpr const value_type && minimum_distance_to_zero_(const value_type && num) { return minimum_(std::move(num), (value_type)(modulus - num)); }
  121.  
  122. value_type value_;
  123. };
  124.  
  125. template<typename _Ty>
  126. class cyclic_number<_Ty>
  127. {
  128. static_assert(std::is_integral<_Ty>::value, "Error: 'cyclic_number<_Ty>' type must be integral.");
  129.  
  130. public:
  131. using type = cyclic_number<_Ty>;
  132. using value_type = std::remove_cv_t<_Ty>;
  133.  
  134. inline constexpr explicit cyclic_number(const value_type & _modulus) :
  135. modulus_{ (_modulus < _1_) ? throw std::invalid_argument("invalid_argument") : _modulus },
  136. value_{ _0_ } { }
  137.  
  138. inline constexpr cyclic_number(const value_type & _modulus, const value_type & _value) :
  139. modulus_{ (_modulus < _1_) ? throw std::invalid_argument("invalid_argument") : _modulus },
  140. value_{ normalize(_value, _modulus) } { }
  141.  
  142. inline constexpr cyclic_number(const value_type & _modulus, value_type && _value) :
  143. modulus_{ (_modulus < _1_) ? throw std::invalid_argument("invalid_argument") : _modulus },
  144. value_{ normalize(std::move(_value), _modulus) } { }
  145.  
  146. template<typename _Tp> operator _Tp&() const = delete;
  147.  
  148. inline constexpr operator const value_type&() const { return value_; }
  149.  
  150. inline constexpr const value_type & value() const { return value_; }
  151.  
  152. inline void value(const value_type & _value) { value_ = normalize(_value, modulus_); }
  153.  
  154. inline constexpr bool operator==(const value_type & number) const { return (value_ == normalize(number, modulus_)); }
  155.  
  156. inline constexpr bool operator!=(const value_type & number) const { return (value_ != normalize(number, modulus_)); }
  157.  
  158. inline constexpr bool operator==(value_type && number) const { return (value_ == normalize(std::move(number), modulus_)); }
  159.  
  160. inline constexpr bool operator!=(value_type && number) const { return (value_ != normalize(std::move(number), modulus_)); }
  161.  
  162. inline type & operator++() { (value_ < (value_type)(modulus_ - _1_)) ? (++value_) : (value_ -= (value_type)(modulus_ - _1_)); return *this; }
  163.  
  164. inline type & operator--() { (value_ > _0_) ? (--value_) : (value_ += (value_type)(modulus_ - _1_)); return *this; }
  165.  
  166. inline value_type operator++(int) { value_type result = this->value_; operator++(); return result; }
  167.  
  168. inline value_type operator--(int) { value_type result = this->value_; operator--(); return result; }
  169.  
  170. inline type & operator*=(const value_type & number) { value_ = normalize(value_ * number, modulus_); return *this; }
  171.  
  172. inline type & operator+=(const value_type & number) { value_ = normalize(value_ + number, modulus_); return *this; }
  173.  
  174. inline type & operator-=(const value_type & number) { value_ = normalize(value_ - number, modulus_); return *this; }
  175.  
  176. inline constexpr value_type forward_distance_to(const value_type & number) const { return forward_distance(value_, number, modulus_); }
  177.  
  178. inline constexpr value_type reverse_distance_to(const value_type & number) const { return reverse_distance(value_, number, modulus_); }
  179.  
  180. inline constexpr value_type minimum_distance_to(const value_type & number) const { return minimum_distance(value_, number, modulus_); }
  181.  
  182. static inline constexpr bool is_valid(const value_type & value, const value_type & modulus) { return ((value >= _0_) && (value < modulus)); }
  183.  
  184. static inline constexpr value_type & normalize(value_type & value, const value_type & modulus)
  185. {
  186. return (value >= modulus ? (value -= modulus * (value / modulus)) :
  187. (value < _0_ ? (value += modulus * (_1_ - value / modulus)) : value));
  188. }
  189.  
  190. static inline constexpr value_type && normalize(value_type && value, const value_type & modulus)
  191. {
  192. return std::move(value >= modulus ? (value -= modulus * (value / modulus)) :
  193. (value < _0_ ? (value += modulus * (_1_ - value / modulus)) : value));
  194. }
  195.  
  196. static inline constexpr value_type normalize(const value_type & value, const value_type & modulus)
  197. {
  198. return (value >= modulus ? (value - modulus * (value / modulus)) :
  199. (value < _0_ ? (value + modulus * (_1_ - value / modulus)) : value));
  200. }
  201.  
  202. static inline constexpr value_type forward_distance(const value_type & begin, const value_type & end, const value_type & modulus)
  203. {
  204. return (end >= begin ?
  205. normalize(end - begin, modulus) :
  206. (value_type)(modulus - normalize(begin - end, modulus)));
  207. }
  208.  
  209. static inline constexpr value_type reverse_distance(const value_type & begin, const value_type & end, const value_type & modulus)
  210. {
  211. return (begin >= end ?
  212. normalize(begin - end, modulus) :
  213. (value_type)(modulus - normalize(end - begin, modulus)));
  214. }
  215.  
  216. static inline constexpr value_type minimum_distance(const value_type & num1, const value_type & num2, const value_type & modulus)
  217. {
  218. return (num1 >= num2 ?
  219. minimum_distance_to_zero_(normalize(num1 - num2, modulus), modulus) :
  220. minimum_distance_to_zero_(normalize(num2 - num1, modulus), modulus));
  221. }
  222.  
  223. protected:
  224. static constexpr value_type _0_{ (value_type)0 };
  225. static constexpr value_type _1_{ (value_type)1 };
  226.  
  227. static inline constexpr const value_type && minimum_(const value_type && v1, const value_type && v2)
  228. {
  229. return std::move(v1 <= v2 ? v1 : v2);
  230. }
  231.  
  232. static inline constexpr const value_type && minimum_distance_to_zero_(const value_type && num, const value_type & modulus)
  233. {
  234. return minimum_(std::move(num), (value_type)(modulus - num));
  235. }
  236.  
  237. value_type value_;
  238. const value_type modulus_;
  239. };
  240.  
  241. template<typename _Ty, _Ty _Mod>
  242. class atomic_cyclic_number<_Ty, _Mod>
  243. {
  244. static_assert(std::is_integral<_Ty>::value, "Error: 'atomic_cyclic_number<_Ty, _Mod>' type must be integral.");
  245. static_assert(_Mod > (_Ty)1, "Error: 'atomic_cyclic_number<_Ty, _Mod>' modulus must be greater than one.");
  246.  
  247. public:
  248. using noatomic_type = cyclic_number<_Ty, _Mod>;
  249. using type = atomic_cyclic_number<_Ty, _Mod>;
  250. using value_type = std::remove_cv_t<_Ty>;
  251. static constexpr value_type modulus{ _Mod };
  252.  
  253. inline constexpr atomic_cyclic_number() : value_{ _0_ } { }
  254.  
  255. inline constexpr atomic_cyclic_number(const value_type & _value) : value_{ normalize(_value) } { }
  256.  
  257. inline constexpr atomic_cyclic_number(value_type && _value) : value_{ normalize(std::move(_value)) } { }
  258.  
  259. template<typename _Tp> operator _Tp&() const = delete;
  260.  
  261. inline constexpr operator const value_type&() const { return value_; }
  262.  
  263. inline constexpr const value_type & value() const { return value_; }
  264.  
  265. inline void value(const value_type & _value) { value_ = normalize(_value); }
  266.  
  267. inline void value(value_type && _value) { value_ = normalize(std::move(_value)); }
  268.  
  269. inline constexpr bool operator==(const value_type & number) const { return (value_ == normalize(number)); }
  270.  
  271. inline constexpr bool operator!=(const value_type & number) const { return (value_ != normalize(number)); }
  272.  
  273. inline constexpr bool operator==(value_type && number) const { return (value_ == normalize(std::move(number))); }
  274.  
  275. inline constexpr bool operator!=(value_type && number) const { return (value_ != normalize(std::move(number))); }
  276.  
  277. inline noatomic_type operator++()
  278. {
  279. value_type capture = value_;
  280. do
  281. {
  282. value_type && draft = ((capture < modulus_minus_1_) ? (capture + _1_) : (capture - modulus_minus_1_));
  283. if (value_.compare_exchange_weak(capture, draft))
  284. return noatomic_type::valid_number_t(draft);
  285. } while (true);
  286. }
  287.  
  288. inline noatomic_type operator--()
  289. {
  290. value_type capture = value_;
  291. do
  292. {
  293. value_type && draft = ((capture > _0_) ? (capture - _1_) : (capture + modulus_minus_1_));
  294. if (value_.compare_exchange_weak(capture, draft))
  295. return noatomic_type::valid_number_t(draft);
  296. } while (true);
  297. }
  298.  
  299. inline noatomic_type operator++(int)
  300. {
  301. value_type capture = value_;
  302. while (!value_.compare_exchange_weak(capture, (capture < modulus_minus_1_) ? (capture + _1_) : (capture - modulus_minus_1_)));
  303. return noatomic_type::valid_number_t(capture);
  304. }
  305.  
  306. inline noatomic_type operator--(int)
  307. {
  308. value_type capture = value_;
  309. while (!value_.compare_exchange_weak(capture, (capture > _0_) ? (capture - _1_) : (capture + modulus_minus_1_)));
  310. return noatomic_type::valid_number_t(capture);
  311. }
  312.  
  313. inline noatomic_type operator*=(const value_type & number)
  314. {
  315. value_type capture = value_;
  316. do
  317. {
  318. value_type && draft = normalize(capture * number);
  319. if (value_.compare_exchange_weak(capture, draft))
  320. return noatomic_type::valid_number_t(draft);
  321. } while (true);
  322. }
  323.  
  324. inline noatomic_type operator+=(const value_type & number)
  325. {
  326. value_type capture = value_;
  327. do
  328. {
  329. value_type && draft = normalize(capture + number);
  330. if (value_.compare_exchange_weak(capture, draft))
  331. return noatomic_type::valid_number_t(draft);
  332. } while (true);
  333. }
  334.  
  335. inline noatomic_type operator-=(const value_type & number)
  336. {
  337. value_type capture = value_;
  338. do
  339. {
  340. value_type && draft = normalize(capture - number);
  341. if (value_.compare_exchange_weak(capture, draft))
  342. return noatomic_type::valid_number_t(draft);
  343. } while (true);
  344. }
  345.  
  346. inline constexpr noatomic_type forward_distance_to(const value_type & number) const { return forward_distance(value_, number); }
  347.  
  348. inline constexpr noatomic_type reverse_distance_to(const value_type & number) const { return reverse_distance(value_, number); }
  349.  
  350. inline constexpr noatomic_type minimum_distance_to(const value_type & number) const { return minimum_distance(value_, number); }
  351.  
  352. static inline constexpr bool is_valid(const value_type & value) { return ((value >= _0_) && (value < modulus)); }
  353.  
  354. static inline constexpr value_type & normalize(value_type & value)
  355. {
  356. return (value >= modulus ? (value -= modulus * (value / modulus)) :
  357. (value < _0_ ? (value += modulus * (_1_ - value / modulus)) : value));
  358. }
  359.  
  360. static inline constexpr value_type && normalize(value_type && value)
  361. {
  362. return std::move(value >= modulus ? (value -= modulus * (value / modulus)) :
  363. (value < _0_ ? (value += modulus * (_1_ - value / modulus)) : value));
  364. }
  365.  
  366. static inline constexpr value_type normalize(const value_type & value)
  367. {
  368. return (value >= modulus ? (value - modulus * (value / modulus)) :
  369. (value < _0_ ? (value + modulus * (_1_ - value / modulus)) : value));
  370. }
  371.  
  372. static inline constexpr noatomic_type forward_distance(const value_type & begin, const value_type & end)
  373. {
  374. return noatomic_type::valid_number_t(end >= begin ?
  375. normalize(end - begin) : (value_type)(modulus - normalize(begin - end)));
  376. }
  377.  
  378. static inline constexpr noatomic_type reverse_distance(const value_type & begin, const value_type & end)
  379. {
  380. return noatomic_type::valid_number_t(begin >= end ?
  381. normalize(begin - end) : (value_type)(modulus - normalize(end - begin)));
  382. }
  383.  
  384. static inline constexpr noatomic_type minimum_distance(const value_type & num1, const value_type & num2)
  385. {
  386. return noatomic_type::valid_number_t(num1 >= num2 ?
  387. minimum_distance_to_zero_(normalize(num1 - num2)) :
  388. minimum_distance_to_zero_(normalize(num2 - num1)));
  389. }
  390.  
  391. protected:
  392. static constexpr value_type _0_{ (value_type)0 };
  393. static constexpr value_type _1_{ (value_type)1 };
  394. static constexpr value_type modulus_minus_1_{ (value_type)(_Mod - _1_) };
  395.  
  396. static inline constexpr const value_type && minimum_(const value_type && v1, const value_type && v2) { return std::move(v1 <= v2 ? v1 : v2); }
  397.  
  398. static inline constexpr const value_type && minimum_distance_to_zero_(const value_type && num) { return minimum_(std::move(num), (value_type)(modulus - num)); }
  399.  
  400. std::atomic<value_type> value_;
  401. };
  402.  
  403. template<typename _Ty>
  404. class atomic_cyclic_number<_Ty>
  405. {
  406. static_assert(std::is_integral<_Ty>::value, "Error: 'atomic_cyclic_number<_Ty>' type must be integral.");
  407.  
  408. public:
  409. using type = atomic_cyclic_number<_Ty>;
  410. using value_type = std::remove_cv_t<_Ty>;
  411.  
  412. inline constexpr explicit atomic_cyclic_number(const value_type & _modulus) :
  413. modulus_{ (_modulus < _1_) ? throw std::invalid_argument("invalid_argument") : _modulus },
  414. value_{ _0_ } { }
  415.  
  416. inline constexpr atomic_cyclic_number(const value_type & _modulus, const value_type & _value) :
  417. modulus_{ (_modulus < _1_) ? throw std::invalid_argument("invalid_argument") : _modulus },
  418. value_{ normalize(_value, _modulus) } { }
  419.  
  420. inline constexpr atomic_cyclic_number(const value_type & _modulus, value_type && _value) :
  421. modulus_{ (_modulus < _1_) ? throw std::invalid_argument("invalid_argument") : _modulus },
  422. value_{ normalize(std::move(_value), _modulus) } { }
  423.  
  424. template<typename _Tp> operator _Tp&() const = delete;
  425.  
  426. inline constexpr operator const value_type&() const { return value_; }
  427.  
  428. inline constexpr const value_type & value() const { return value_; }
  429.  
  430. inline void value(const value_type & _value) { value_ = normalize(_value, modulus_); }
  431.  
  432. inline void value(value_type && _value) { value_ = normalize(std::move(_value), modulus_); }
  433.  
  434. inline constexpr bool operator==(const value_type & number) const { return (value_ == normalize(number, modulus_)); }
  435.  
  436. inline constexpr bool operator!=(const value_type & number) const { return (value_ != normalize(number, modulus_)); }
  437.  
  438. inline constexpr bool operator==(value_type && number) const { return (value_ == normalize(std::move(number), modulus_)); }
  439.  
  440. inline constexpr bool operator!=(value_type && number) const { return (value_ != normalize(std::move(number), modulus_)); }
  441.  
  442. inline value_type operator++()
  443. {
  444. value_type capture = value_;
  445. do
  446. {
  447. value_type && draft = ((capture < (value_type)(modulus_ - _1_)) ? (capture + _1_) : (capture - (value_type)(modulus_ - _1_)));
  448. if (value_.compare_exchange_weak(capture, draft))
  449. return draft;
  450. } while (true);
  451. }
  452.  
  453. inline value_type operator--()
  454. {
  455. value_type capture = value_;
  456. do
  457. {
  458. value_type && draft = ((capture > _0_) ? (capture - _1_) : (capture + (value_type)(modulus_ - _1_)));
  459. if (value_.compare_exchange_weak(capture, draft))
  460. return draft;
  461. } while (true);
  462. }
  463.  
  464. inline value_type operator++(int)
  465. {
  466. value_type capture = value_;
  467. while (!value_.compare_exchange_weak(capture, (capture < (value_type)(modulus_ - _1_)) ? (capture + _1_) : (capture - (value_type)(modulus_ - _1_))));
  468. return capture;
  469. }
  470.  
  471. inline value_type operator--(int)
  472. {
  473. value_type capture = value_;
  474. while (!value_.compare_exchange_weak(capture, (capture > _0_) ? (capture - _1_) : (capture + (value_type)(modulus_ - _1_))));
  475. return capture;
  476. }
  477.  
  478. inline value_type operator*=(const value_type & number)
  479. {
  480. value_type capture = value_;
  481. do
  482. {
  483. value_type && draft = normalize(capture * number, modulus_);
  484. if (value_.compare_exchange_weak(capture, draft))
  485. return draft;
  486. } while (true);
  487. }
  488.  
  489. inline value_type operator+=(const value_type & number)
  490. {
  491. value_type capture = value_;
  492. do
  493. {
  494. value_type && draft = normalize(capture + number, modulus_);
  495. if (value_.compare_exchange_weak(capture, draft))
  496. return draft;
  497. } while (true);
  498. }
  499.  
  500. inline value_type operator-=(const value_type & number)
  501. {
  502. value_type capture = value_;
  503. do
  504. {
  505. value_type && draft = normalize(capture - number, modulus_);
  506. if (value_.compare_exchange_weak(capture, draft))
  507. return draft;
  508. } while (true);
  509. }
  510.  
  511. inline constexpr value_type forward_distance_to(const value_type & number) const { return forward_distance(value_, number, modulus_); }
  512.  
  513. inline constexpr value_type reverse_distance_to(const value_type & number) const { return reverse_distance(value_, number, modulus_); }
  514.  
  515. inline constexpr value_type minimum_distance_to(const value_type & number) const { return minimum_distance(value_, number, modulus_); }
  516.  
  517. static inline constexpr bool is_valid(const value_type & value, const value_type & modulus) { return ((value >= _0_) && (value < modulus)); }
  518.  
  519. static inline constexpr value_type & normalize(value_type & value, const value_type & modulus)
  520. {
  521. return (value >= modulus ? (value -= modulus * (value / modulus)) :
  522. (value < _0_ ? (value += modulus * (_1_ - value / modulus)) : value));
  523. }
  524.  
  525. static inline constexpr value_type && normalize(value_type && value, const value_type & modulus)
  526. {
  527. return std::move(value >= modulus ? (value -= modulus * (value / modulus)) :
  528. (value < _0_ ? (value += modulus * (_1_ - value / modulus)) : value));
  529. }
  530.  
  531. static inline constexpr value_type normalize(const value_type & value, const value_type & modulus)
  532. {
  533. return (value >= modulus ? (value - modulus * (value / modulus)) :
  534. (value < _0_ ? (value + modulus * (_1_ - value / modulus)) : value));
  535. }
  536.  
  537. static inline constexpr value_type forward_distance(const value_type & begin, const value_type & end, const value_type & modulus)
  538. {
  539. return (end >= begin ?
  540. normalize(end - begin, modulus) :
  541. (value_type)(modulus - normalize(begin - end, modulus)));
  542. }
  543.  
  544. static inline constexpr value_type reverse_distance(const value_type & begin, const value_type & end, const value_type & modulus)
  545. {
  546. return (begin >= end ?
  547. normalize(begin - end, modulus) :
  548. (value_type)(modulus - normalize(end - begin, modulus)));
  549. }
  550.  
  551. static inline constexpr value_type minimum_distance(const value_type & num1, const value_type & num2, const value_type & modulus)
  552. {
  553. return (num1 >= num2 ?
  554. minimum_distance_to_zero_(normalize(num1 - num2, modulus), modulus) :
  555. minimum_distance_to_zero_(normalize(num2 - num1, modulus), modulus));
  556. }
  557.  
  558. protected:
  559. static constexpr value_type _0_{ (value_type)0 };
  560. static constexpr value_type _1_{ (value_type)1 };
  561.  
  562. static inline constexpr const value_type && minimum_(const value_type && v1, const value_type && v2)
  563. {
  564. return std::move(v1 <= v2 ? v1 : v2);
  565. }
  566.  
  567. static inline constexpr const value_type && minimum_distance_to_zero_(const value_type && num, const value_type & modulus)
  568. {
  569. return minimum_(std::move(num), (value_type)(modulus - num));
  570. }
  571.  
  572. std::atomic<value_type> value_;
  573. const value_type modulus_;
  574. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement