From e6d67260f11c6936578cda67779eda1bfbe253cb Mon Sep 17 00:00:00 2001 From: "Alan M. Carroll" Date: Thu, 3 Aug 2017 16:18:07 -0500 Subject: [PATCH] Fixes to scalar for better handling of division and comparisons with built in types. --- cmd/traffic_cache_tool/CacheTool.cc | 2 +- lib/ts/Scalar.h | 236 ++-------------------------- lib/ts/test_Scalar.cc | 26 +++ 3 files changed, 43 insertions(+), 221 deletions(-) diff --git a/cmd/traffic_cache_tool/CacheTool.cc b/cmd/traffic_cache_tool/CacheTool.cc index e73e20f8d2e..ae35363f41e 100644 --- a/cmd/traffic_cache_tool/CacheTool.cc +++ b/cmd/traffic_cache_tool/CacheTool.cc @@ -1253,7 +1253,7 @@ main(int argc, char *argv[]) Commands.setArgIndex(optind); if (help) { - Commands.helpMessage(argc-1, argv+1); + Commands.helpMessage(argc - 1, argv + 1); exit(1); } diff --git a/lib/ts/Scalar.h b/lib/ts/Scalar.h index e7319678296..e22fed9d0d8 100644 --- a/lib/ts/Scalar.h +++ b/lib/ts/Scalar.h @@ -493,21 +493,14 @@ Scalar::scale() } // --- Compare operators -// These optimize nicely due to dead code elimination. +// These optimize nicely because if R::num or R::den is 1 the compiler will drop it. template bool operator<(Scalar const &lhs, Scalar const &rhs) { typedef std::ratio R; - if (N == S) - return lhs.count() < rhs.count(); - else if (R::den == 1) - return lhs.count() * R::num < rhs.count(); - else if (R::num == 1) - return lhs.count() < rhs.count() * R::den; - else - return lhs.value() < rhs.value(); + return lhs.count() * R::num < rhs.count() * R::den; } template @@ -515,14 +508,7 @@ bool operator==(Scalar const &lhs, Scalar const &rhs) { typedef std::ratio R; - if (N == S) - return lhs.count() == rhs.count(); - else if (R::den == 1) - return lhs.count() * R::num == rhs.count(); - else if (R::num == 1) - return lhs.count() == rhs.count() * R::den; - else - return lhs.value() == rhs.value(); + return lhs.count() * R::num == rhs.count() * R::den; } template @@ -530,222 +516,24 @@ bool operator<=(Scalar const &lhs, Scalar const &rhs) { typedef std::ratio R; - if (N == S) - return lhs.count() <= rhs.count(); - else if (R::den == 1) - return lhs.count() * R::num <= rhs.count(); - else if (R::num == 1) - return lhs.count() <= rhs.count() * R::den; - else - return lhs.value() <= rhs.value(); + return lhs.count() * R::num <= rhs.count() * R::den; } // Derived compares. - -template +template bool -operator>(Scalar const &lhs, Scalar const &rhs) +operator>(Scalar const &lhs, Scalar const &rhs) { return rhs < lhs; } -template +template bool -operator>=(Scalar const &lhs, Scalar const &rhs) +operator>=(Scalar const &lhs, Scalar const &rhs) { return rhs <= lhs; } -// Do the integer compares. -// A bit ugly to handle the issue that integers without explicit type are . Therefore suppport -// must be provided for comparison not just to the counter type C but also explicitly , otherwise -// function template argument deduction may fail (because it can't figure out what to use for ). - -template -bool -operator<(Scalar const &lhs, C n) -{ - return lhs.value() < n; -} -template -bool -operator<(C n, Scalar const &rhs) -{ - return n < rhs.value(); -} -template -bool -operator<(Scalar const &lhs, int n) -{ - return lhs.value() < static_cast(n); -} -template -bool -operator<(int n, Scalar const &rhs) -{ - return static_cast(n) < rhs.value(); -} -template -bool -operator<(Scalar const &lhs, int n) -{ - return lhs.value() < n; -} -template -bool -operator<(int n, Scalar const &rhs) -{ - return n < rhs.value(); -} - -template -bool -operator==(Scalar const &lhs, C n) -{ - return lhs.value() == n; -} -template -bool -operator==(C n, Scalar const &rhs) -{ - return n == rhs.value(); -} -template -bool -operator==(Scalar const &lhs, int n) -{ - return lhs.value() == static_cast(n); -} -template -bool -operator==(int n, Scalar const &rhs) -{ - return static_cast(n) == rhs.value(); -} -template -bool -operator==(Scalar const &lhs, int n) -{ - return lhs.value() == n; -} -template -bool -operator==(int n, Scalar const &rhs) -{ - return n == rhs.value(); -} - -template -bool -operator>(Scalar const &lhs, C n) -{ - return lhs.value() > n; -} -template -bool -operator>(C n, Scalar const &rhs) -{ - return n > rhs.value(); -} -template -bool -operator>(Scalar const &lhs, int n) -{ - return lhs.value() > static_cast(n); -} -template -bool -operator>(int n, Scalar const &rhs) -{ - return static_cast(n) > rhs.value(); -} -template -bool -operator>(Scalar const &lhs, int n) -{ - return lhs.value() > n; -} -template -bool -operator>(int n, Scalar const &rhs) -{ - return n > rhs.value(); -} - -template -bool -operator<=(Scalar const &lhs, C n) -{ - return lhs.value() <= n; -} -template -bool -operator<=(C n, Scalar const &rhs) -{ - return n <= rhs.value(); -} -template -bool -operator<=(Scalar const &lhs, int n) -{ - return lhs.value() <= static_cast(n); -} -template -bool -operator<=(int n, Scalar const &rhs) -{ - return static_cast(n) <= rhs.value(); -} -template -bool -operator<=(Scalar const &lhs, int n) -{ - return lhs.value() <= n; -} -template -bool -operator<=(int n, Scalar const &rhs) -{ - return n <= rhs.value(); -} - -template -bool -operator>=(Scalar const &lhs, C n) -{ - return lhs.value() >= n; -} -template -bool -operator>=(C n, Scalar const &rhs) -{ - return n >= rhs.value(); -} -template -bool -operator>=(Scalar const &lhs, int n) -{ - return lhs.value() >= static_cast(n); -} -template -bool -operator>=(int n, Scalar const &rhs) -{ - return static_cast(n) >= rhs.value(); -} -template -bool -operator>=(Scalar const &lhs, int n) -{ - return lhs.value() >= n; -} -template -bool -operator>=(int n, Scalar const &rhs) -{ - return n >= rhs.value(); -} - // Arithmetic operators template auto @@ -1066,6 +854,14 @@ Scalar::operator/=(C n) -> self & return *this; } +template +auto +operator/(Scalar lhs, Scalar rhs) -> typename std::common_type::type +{ + using R = std::ratio; + return (lhs.count() * R::num) / (rhs.count() * R::den); +} + template Scalar operator/(Scalar lhs, I n) diff --git a/lib/ts/test_Scalar.cc b/lib/ts/test_Scalar.cc index 369610325b9..0aa364eae81 100644 --- a/lib/ts/test_Scalar.cc +++ b/lib/ts/test_Scalar.cc @@ -343,6 +343,31 @@ struct KBytes_tag { }; std::string const KBytes_tag::label(" bytes"); +void +Test_8() +{ + using ts::Scalar; + using S16 = Scalar<16>; + using S48 = Scalar<48>; + using S64 = Scalar<64>; + using S91 = Scalar<91>; + + TestBox test("TS.Scalar: division tests"); + + S16 s16(9); + S48 s48(27); + S64 s64(54); + S91 s91(17); + + test.equal(s16 / 9, S16::scale()); + test.equal(s64 / s16, 24); + test.equal(s91 / 16, S91::scale()); + test.equal(s48 / 24, 48); // correct because of rounding. + test.equal(s48 / 12, 96); + test.equal(s48 / 3, 432); + test.equal(s91 / s16, 10); +} + void Test_IO() { @@ -401,6 +426,7 @@ main(int, char **) Test_5(); Test_6(); Test_7(); + Test_8(); Test_IO(); TestBox::print_summary(); return 0;