You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by am...@apache.org on 2019/02/12 19:16:14 UTC
[trafficserver] branch master updated: Scalar: add generic rounding.
This is an automated email from the ASF dual-hosted git repository.
amc pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/master by this push:
new 840f4b8 Scalar: add generic rounding.
840f4b8 is described below
commit 840f4b8412d3ac55d47e5f1b3a5836e37810a730
Author: Alan M. Carroll <am...@apache.org>
AuthorDate: Fri Feb 8 09:16:42 2019 -0600
Scalar: add generic rounding.
---
include/tscore/Scalar.h | 38 ++++++++++++++++++++++++++----------
src/tscore/unit_tests/test_Scalar.cc | 18 +++++++++++++++++
2 files changed, 46 insertions(+), 10 deletions(-)
diff --git a/include/tscore/Scalar.h b/include/tscore/Scalar.h
index e71a082..06c3398 100644
--- a/include/tscore/Scalar.h
+++ b/include/tscore/Scalar.h
@@ -44,19 +44,19 @@ template <intmax_t N, typename C, typename T> class Scalar;
namespace detail
{
- // @internal - althought these conversion methods look bulky, in practice they compile down to
- // very small amounts of code due to dead code elimination and that all of the conditions are
- // compile time constants.
+ // @internal - although these conversion methods look bulky, in practice they compile down to
+ // very small amounts of code due to the conditions being compile time constant - the non-taken
+ // clauses are dead code and eliminated by the compiler.
// The general case where neither N nor S are a multiple of the other seems a bit long but this
// minimizes the risk of integer overflow. I need to validate that under -O2 the compiler will
// only do 1 division to get both the quotient and remainder for (n/N) and (n%N). In cases where
// N,S are powers of 2 I have verified recent GNU compilers will optimize to bit operations.
- /// Convert a count @a c that is scale @s S to scale @c N
- template <intmax_t N, intmax_t S>
- intmax_t
- scale_conversion_round_up(intmax_t c)
+ /// Convert a count @a c that is scale @s S to the corresponding count for scale @c N
+ template <intmax_t N, intmax_t S, typename C>
+ C
+ scale_conversion_round_up(C c)
{
typedef std::ratio<N, S> R;
if (N == S) {
@@ -71,9 +71,9 @@ namespace detail
}
/// Convert a count @a c that is scale @s S to scale @c N
- template <intmax_t N, intmax_t S>
- intmax_t
- scale_conversion_round_down(intmax_t c)
+ template <intmax_t N, intmax_t S, typename C>
+ C
+ scale_conversion_round_down(C c)
{
typedef std::ratio<N, S> R;
if (N == S) {
@@ -108,6 +108,10 @@ namespace detail
Much of this is driven by the fact that the assignment operator, in some cases, can not be
templated and therefore to have a nice interface for assignment this split is needed.
+
+ Note - the key point is the actual conversion is not done when the wrapper instance is created
+ but when the wrapper instance is assigned. That is what enables the conversion to be done in
+ the context of the destination, which is not otherwise possible.
*/
// Unit value, to be rounded up.
@@ -893,6 +897,20 @@ Scalar<N, C, T>::minus(Counter n) const -> self
return {_n - n};
}
+template <intmax_t N, typename C>
+C
+round_up(C value)
+{
+ return N * detail::scale_conversion_round_up<N, 1>(value);
+}
+
+template <intmax_t N, typename C>
+C
+round_down(C value)
+{
+ return N * detail::scale_conversion_round_down<N, 1>(value);
+}
+
namespace detail
{
// These classes exist only to create distinguishable overloads.
diff --git a/src/tscore/unit_tests/test_Scalar.cc b/src/tscore/unit_tests/test_Scalar.cc
index 3f8ac69..6e89560 100644
--- a/src/tscore/unit_tests/test_Scalar.cc
+++ b/src/tscore/unit_tests/test_Scalar.cc
@@ -76,6 +76,24 @@ TEST_CASE("Scalar", "[libts][Scalar]")
sz_b = sz; // Should be OK because SCALE_1 is an integer multiple of SCALE_2
// sz = sz_b; // Should not compile.
REQUIRE(sz_b.count() == 119 * (SCALE_1 / SCALE_2));
+
+ // Test generic rounding.
+ REQUIRE(120 == ts::round_up<10>(118));
+ REQUIRE(120 == ts::round_up<10>(120));
+ REQUIRE(130 == ts::round_up<10>(121));
+
+ REQUIRE(110 == ts::round_down<10>(118));
+ REQUIRE(120 == ts::round_down<10>(120));
+ REQUIRE(120 == ts::round_down<10>(121));
+
+ REQUIRE(1200 == ts::round_up<100>(1108));
+ REQUIRE(1200 == ts::round_up<100>(1200));
+ REQUIRE(1300 == ts::round_up<100>(1201));
+
+ REQUIRE(100 == ts::round_down<100>(118));
+ REQUIRE(1100 == ts::round_down<100>(1108));
+ REQUIRE(1200 == ts::round_down<100>(1200));
+ REQUIRE(1200 == ts::round_down<100>(1208));
}
TEST_CASE("Scalar Factors", "[libts][Scalar][factors]")