21namespace swoc {
inline namespace SWOC_VERSION_NS {
28template <
intmax_t N,
typename C,
typename T>
class Scalar;
43template <
intmax_t N,
intmax_t S,
typename C>
45scale_conversion_round_up(C c) {
46 using R = std::ratio<N, S>;
47 if constexpr (N == S) {
49 }
else if constexpr (R::den == 1) {
50 return c / R::num + (0 != c % R::num);
51 }
else if constexpr (R::num == 1) {
54 return (c / R::num) * R::den + ((c % R::num) * R::den) / R::num + (0 != (c % R::num));
58template <
intmax_t N,
intmax_t S,
typename C>
60scale_conversion_round_down(C c) {
61 using R = std::ratio<N, S>;
62 if constexpr (N == S) {
64 }
else if constexpr (R::den == 1) {
66 }
else if constexpr (R::num == 1) {
69 return (c / R::num) * R::den + ((c % R::num) * R::den) / R::num;
101template <
typename C>
struct scalar_unit_round_up_t {
104 template <
intmax_t N,
typename I>
107 return static_cast<I
>(_n / N + (0 != (_n % N)));
112template <
typename C>
struct scalar_unit_round_down_t {
115 template <
intmax_t N,
typename I>
118 return static_cast<I
>(_n / N);
123template <
intmax_t N,
typename C,
typename T>
struct scalar_round_up_t {
126 template <
intmax_t S,
typename I>
128 operator Scalar<S, I, T>()
const {
129 return Scalar<S, I, T>(scale_conversion_round_up<S, N>(_n));
134template <
intmax_t N,
typename C,
typename T>
struct scalar_round_down_t {
137 template <
intmax_t S,
typename I>
139 operator Scalar<S, I, T>()
const {
140 return Scalar<S, I, T>(scale_conversion_round_down<S, N>(_n));
172template <
intmax_t N,
typename C =
int,
typename T = tag::
generic>
class Scalar {
177 constexpr static intmax_t
SCALE = N;
181 static_assert(N > 0,
"The scaling factor (1st template argument) must be a positive integer");
182 static_assert(std::is_integral<C>::value,
"The counter type (2nd template argument) must be an integral type");
202 constexpr Scalar(detail::scalar_round_up_t<N, C, T>
const &v);
205 constexpr Scalar(detail::scalar_round_down_t<N, C, T>
const &that);
208 template <
typename I>
constexpr Scalar(detail::scalar_unit_round_up_t<I> v);
211 template <
typename I>
constexpr Scalar(detail::scalar_unit_round_down_t<I> v);
237 template <
typename I> self_type &
operator=(detail::scalar_unit_round_up_t<I> n);
245 template <
typename I> self_type &
operator=(detail::scalar_unit_round_down_t<I> n);
255 self_type &
operator=(detail::scalar_round_up_t<N, C, T> v);
265 self_type &
operator=(detail::scalar_round_down_t<N, C, T> v);
286 template <
typename I> self_type &
assign(detail::scalar_unit_round_up_t<I> n);
288 template <
typename I> self_type &
assign(detail::scalar_unit_round_down_t<I> n);
290 self_type &
assign(detail::scalar_round_up_t<N, C, T> v);
292 self_type &
assign(detail::scalar_round_down_t<N, C, T> v);
322 template <
typename I> self_type &
operator+=(detail::scalar_unit_round_up_t<I> n);
324 template <
typename I> self_type &
operator+=(detail::scalar_unit_round_down_t<I> n);
326 self_type &
operator+=(detail::scalar_round_up_t<N, C, T> v);
328 self_type &
operator+=(detail::scalar_round_down_t<N, C, T> v);
367 template <
typename I> self_type &
operator-=(detail::scalar_unit_round_up_t<I> n);
369 template <
typename I> self_type &
operator-=(detail::scalar_unit_round_down_t<I> n);
371 self_type &
operator-=(detail::scalar_round_up_t<N, C, T> v);
373 self_type &
operator-=(detail::scalar_round_down_t<N, C, T> v);
404template <
intmax_t N,
typename C,
typename T>
constexpr Scalar<N, C, T>::Scalar(self_type
const &that) : _n(that._n) {}
406template <
intmax_t N,
typename C,
typename T>
410template <
intmax_t N,
typename C,
typename T>
411template <
intmax_t S,
typename I>
413 static_assert(std::ratio<S, N>::den == 1,
414 "Construction not permitted - target scale is not an integral multiple of source scale.");
417template <
intmax_t N,
typename C,
typename T>
420template <
intmax_t N,
typename C,
typename T>
423template <
intmax_t N,
typename C,
typename T>
427template <
intmax_t N,
typename C,
typename T>
431template <
intmax_t N,
typename C,
typename T>
437template <
intmax_t N,
typename C,
typename T>
447template <
intmax_t N,
typename C,
typename T>
454template <
intmax_t N,
typename C,
typename T>
461template <
intmax_t N,
typename C,
typename T>
468template <
intmax_t N,
typename C,
typename T>
475template <
intmax_t N,
typename C,
typename T>
482template <
intmax_t N,
typename C,
typename T>
489template <
intmax_t N,
typename C,
typename T>
493 _n = v.template scale<N, C>();
497template <
intmax_t N,
typename C,
typename T>
501 _n = v.template scale<N, C>();
505template <
intmax_t N,
typename C,
typename T>
509 _n = v.template scale<N, C>();
513template <
intmax_t N,
typename C,
typename T>
517 _n = v.template scale<N, C>();
521template <
intmax_t N,
typename C,
typename T>
522template <
intmax_t S,
typename I>
525 using R = std::ratio<S, N>;
526 static_assert(R::den == 1,
"Assignment not permitted - target scale is not an integral multiple of source scale.");
527 _n = that.count() * R::num;
531template <
intmax_t N,
typename C,
typename T>
532template <
intmax_t S,
typename I>
535 using R = std::ratio<S, N>;
536 static_assert(R::den == 1,
"Assignment not permitted - target scale is not an integral multiple of source scale.");
537 _n = that.count() * R::num;
541template <
intmax_t N,
typename C,
typename T>
542constexpr inline intmax_t
558constexpr detail::scalar_unit_round_up_t<C>
571template <
intmax_t N,
typename C,
typename T>
572constexpr detail::scalar_round_up_t<N, C, T>
584constexpr detail::scalar_unit_round_down_t<C>
597template <
intmax_t N,
typename C,
typename T>
598constexpr detail::scalar_round_down_t<N, C, T>
606template <
intmax_t N,
typename C1,
intmax_t S,
typename I,
typename T>
608operator<(Scalar<N, C1, T>
const &lhs, Scalar<S, I, T>
const &rhs) {
609 using R = std::ratio<N, S>;
610 return lhs.
count() * R::num < rhs.count() * R::den;
613template <
intmax_t N,
typename C1,
intmax_t S,
typename I,
typename T>
616 using R = std::ratio<N, S>;
617 return lhs.count() * R::num == rhs.count() * R::den;
620template <
intmax_t N,
typename C1,
intmax_t S,
typename I,
typename T>
623 using R = std::ratio<N, S>;
624 return lhs.count() * R::num <= rhs.count() * R::den;
628template <
intmax_t N,
typename C,
intmax_t S,
typename I,
typename T>
634template <
intmax_t N,
typename C,
intmax_t S,
typename I,
typename T>
641template <
intmax_t N,
typename C,
typename T>
648template <
intmax_t N,
typename C,
typename T>
649template <
intmax_t S,
typename I>
652 using R = std::ratio<S, N>;
653 static_assert(R::den == 1,
"Addition not permitted - target scale is not an integral multiple of source scale.");
654 _n += that.count() * R::num;
659template <
intmax_t N,
typename C,
typename T>
663 _n += v.template scale<N, C>();
667template <
intmax_t N,
typename C,
typename T>
671 _n += v.template scale<N, C>();
675template <
intmax_t N,
typename C,
typename T>
682template <
intmax_t N,
typename C,
typename T>
691template <
intmax_t N,
typename C,
intmax_t S,
typename I,
typename T>
693operator+(
Scalar<N, C, T> lhs,
Scalar<S, I, T> const &rhs) ->
typename std::common_type<Scalar<N, C, T>,
Scalar<S, I, T>>::type {
694 return typename std::common_type<Scalar<N, C, T>,
Scalar<S, I, T>>::type(lhs) += rhs;
700template <
intmax_t N,
typename C,
typename T>
708template <
intmax_t N,
typename C,
typename T,
typename I>
710operator+(detail::scalar_unit_round_up_t<I> lhs, Scalar<N, C, T>
const &rhs) {
711 return Scalar<N, C, T>(rhs) += lhs;
714template <
intmax_t N,
typename C,
typename T,
typename I>
716operator+(
Scalar<N, C, T> const &lhs, detail::scalar_unit_round_up_t<I> rhs) {
720template <
intmax_t N,
typename C,
typename T,
typename I>
722operator+(detail::scalar_unit_round_down_t<I> lhs,
Scalar<N, C, T> const &rhs) {
726template <
intmax_t N,
typename C,
typename T,
typename I>
728operator+(
Scalar<N, C, T> const &lhs, detail::scalar_unit_round_down_t<I> rhs) {
732template <
intmax_t N,
typename C,
typename T>
734operator+(detail::scalar_round_up_t<N, C, T> lhs,
Scalar<N, C, T> const &rhs) {
738template <
intmax_t N,
typename C,
typename T>
740operator+(
Scalar<N, C, T> const &lhs, detail::scalar_round_up_t<N, C, T> rhs) {
744template <
intmax_t N,
typename C,
typename T>
746operator+(detail::scalar_round_down_t<N, C, T> lhs,
Scalar<N, C, T> const &rhs) {
750template <
intmax_t N,
typename C,
typename T>
752operator+(
Scalar<N, C, T> const &lhs, detail::scalar_round_down_t<N, C, T> rhs) {
757template <
intmax_t N,
typename C,
typename T>
764template <
intmax_t N,
typename C,
typename T>
765template <
intmax_t S,
typename I>
768 using R = std::ratio<S, N>;
769 static_assert(R::den == 1,
"Subtraction not permitted - target scale is not an integral multiple of source scale.");
770 _n -= that.count() * R::num;
776template <
intmax_t N,
typename C,
typename T>
780 _n -= v.template scale<N, C>();
784template <
intmax_t N,
typename C,
typename T>
788 _n -= v.template scale<N, C>();
792template <
intmax_t N,
typename C,
typename T>
799template <
intmax_t N,
typename C,
typename T>
808template <
intmax_t N,
typename C,
intmax_t S,
typename I,
typename T>
810operator-(
Scalar<N, C, T> lhs,
Scalar<S, I, T> const &rhs) ->
typename std::common_type<Scalar<N, C, T>,
Scalar<S, I, T>>::type {
811 return typename std::common_type<Scalar<N, C, T>,
Scalar<S, I, T>>::type(lhs) -= rhs;
817template <
intmax_t N,
typename C,
typename T>
825template <
intmax_t N,
typename C,
typename T,
typename I>
827operator-(detail::scalar_unit_round_up_t<I> lhs, Scalar<N, C, T>
const &rhs) {
828 return Scalar<N, C, T>(lhs.template scale<N, C>()) -= rhs;
831template <
intmax_t N,
typename C,
typename T,
typename I>
833operator-(
Scalar<N, C, T> const &lhs, detail::scalar_unit_round_up_t<I> rhs) {
837template <
intmax_t N,
typename C,
typename T,
typename I>
839operator-(detail::scalar_unit_round_down_t<I> lhs,
Scalar<N, C, T> const &rhs) {
843template <
intmax_t N,
typename C,
typename T,
typename I>
845operator-(
Scalar<N, C, T> const &lhs, detail::scalar_unit_round_down_t<I> rhs) {
849template <
intmax_t N,
typename C,
typename T>
851operator-(detail::scalar_round_up_t<N, C, T> lhs,
Scalar<N, C, T> const &rhs) {
855template <
intmax_t N,
typename C,
typename T>
857operator-(
Scalar<N, C, T> const &lhs, detail::scalar_round_up_t<N, C, T> rhs) {
861template <
intmax_t N,
typename C,
typename T>
863operator-(detail::scalar_round_down_t<N, C, T> lhs,
Scalar<N, C, T> const &rhs) {
867template <
intmax_t N,
typename C,
typename T>
869operator-(
Scalar<N, C, T> const &lhs, detail::scalar_round_down_t<N, C, T> rhs) {
874template <
intmax_t N,
typename C,
typename T>
881template <
intmax_t N,
typename C,
typename T>
884 self_type zret(*
this);
889template <
intmax_t N,
typename C,
typename T>
896template <
intmax_t N,
typename C,
typename T>
899 self_type zret(*
this);
904template <
intmax_t N,
typename C,
typename T>
911template <
intmax_t N,
typename C,
typename T>
918template <
intmax_t N,
typename C,
typename T>
925template <
intmax_t N,
typename C,
typename T>
931template <
intmax_t N,
typename C,
typename T>
933operator*(C n, Scalar<N, C, T>
const &rhs) {
934 return Scalar<N, C, T>(rhs) *= n;
937template <
intmax_t N,
typename C,
typename T>
943template <
intmax_t N,
typename C,
typename T>
961template <
intmax_t N,
typename C,
typename T>
968template <
intmax_t N,
typename C,
intmax_t S,
typename I,
typename T>
971 using R = std::ratio<N, S>;
972 return (lhs.count() * R::num) / (rhs.count() * R::den);
975template <
intmax_t N,
typename C,
typename T,
typename I>
977operator/(Scalar<N, C, T> lhs, I n) {
978 static_assert(std::is_integral<I>::value,
"Scalar divsion only support integral types.");
979 return Scalar<N, C, T>(lhs) /= n;
982template <
intmax_t N,
typename C,
typename T>
988template <
intmax_t N,
typename C,
typename T>
994template <
intmax_t N,
typename C,
typename T>
1013template <
intmax_t N,
typename C>
1016 return N * detail::scale_conversion_round_up<N, 1>(value);
1032template <
intmax_t N,
typename C>
1035 return N * detail::scale_conversion_round_down<N, 1>(value);
1039template <
typename T>
1041tag_label(std::ostream &,
const meta::CaseTag<0> &) ->
void {}
1043template <
typename T>
1045tag_label(std::ostream &w,
const meta::CaseTag<1> &) ->
decltype(T::label, meta::TypeFunc<void>()) {
1049template <
typename T>
1050inline std::ostream &
1051tag_label(std::ostream &w) {
1052 tag_label<T>(w, meta::CaseArg);
1062template <
intmax_t N,
typename C,
intmax_t S,
typename I,
typename T>
1064 using R = std::ratio<N, S>;
1065 using type =
swoc::Scalar<N / R::num,
typename common_type<C, I>::type, T>;
1068template <
intmax_t N,
typename C,
typename T>
1072 return swoc::detail::tag_label<T>(s);
self_type & operator/=(C n)
Division - divide (rounding down) the count by n.
self_type plus(Counter n) const
Return a value at the same scale with a count increased by n.
constexpr Counter count() const
The number of scale units.
self_type & operator*=(C n)
Multiplication - multiple the count by n.
self_type & operator+=(Scalar< S, I, T > const &that)
self_type & assign(Counter n)
self_type operator--(int)
Decrement - decrease count by 1.
constexpr Scalar(Scalar< S, I, T > const &that)
self_type & operator=(self_type const &that)
Self type assignment.
constexpr Counter value() const
The scaled value.
constexpr Scalar(Counter n)
Construct to have value that is n scaled units.
self_type & operator--()
Decrement - decrease count by 1.
constexpr Scalar()
Default constructor.
self_type & operator-=(self_type const &that)
self_type & operator-=(Scalar< S, I, T > const &that)
self_type & dec(Counter n)
Decrement by n.
self_type & operator+=(self_type const &that)
self_type minus(Counter n) const
Return a value at the same scale with a count decreased by n.
self_type & operator=(Scalar< S, I, T > const &that)
constexpr Scalar(self_type const &that)
Copy constructor.
self_type & operator++()
Increment - increase count by 1.
self_type operator()(Counter n) const
Utility overload of the function operator to create instances at the same scale.
static constexpr intmax_t scale()
Run time access to the scale (template arg N).
constexpr Scalar(Scalar< N, I, T > const &that)
Copy constructor.
self_type operator++(int)
Increment - increase count by 1.
self_type & inc(Counter n)
Increment by n.
static constexpr intmax_t SCALE
self_type & assign(Scalar< S, I, T > const &that)
For template deduction guides.
bool operator>(IP4Addr const &lhs, IP4Addr const &rhs)
bool operator<=(IP4Addr const &lhs, IP4Addr const &rhs)
bool operator>=(IP4Addr const &lhs, IP4Addr const &rhs)
Scalar_INTERNAL constexpr detail::scalar_unit_round_up_t< C > round_up(C n)
bool operator==(IPAddr const &lhs, sockaddr const *sa)
Equality.
bool operator<(IP4Addr const &lhs, IP4Addr const &rhs)
constexpr detail::scalar_unit_round_down_t< C > round_down(C n)