BucketedTimeSeries: fix type converison issues computing avg()
[folly.git] / folly / detail / Stats.h
1 /*
2  * Copyright 2012 Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #ifndef FOLLY_DETAIL_STATS_H_
18 #define FOLLY_DETAIL_STATS_H_
19
20 #include <cstdint>
21
22 namespace folly { namespace detail {
23
24 /*
25  * Helper functions for how to perform division based on the desired
26  * return type.
27  */
28
29 // For floating point input types, do floating point division
30 template <typename ReturnType, typename ValueType>
31 typename std::enable_if<std::is_floating_point<ValueType>::value,
32                         ReturnType>::type
33 avgHelper(ValueType sum, uint64_t count) {
34   if (count == 0) { return ReturnType(0); }
35   return static_cast<ReturnType>(sum / count);
36 }
37
38 // For floating point return types, do floating point division
39 template <typename ReturnType, typename ValueType>
40 typename std::enable_if<std::is_floating_point<ReturnType>::value &&
41                         !std::is_floating_point<ValueType>::value,
42                         ReturnType>::type
43 avgHelper(ValueType sum, uint64_t count) {
44   if (count == 0) { return ReturnType(0); }
45   return static_cast<ReturnType>(sum) / count;
46 }
47
48 // For signed integer input types, do signed division
49 template <typename ReturnType, typename ValueType>
50 typename std::enable_if<!std::is_floating_point<ReturnType>::value &&
51                         !std::is_floating_point<ValueType>::value &&
52                         std::is_signed<ValueType>::value,
53                         ReturnType>::type
54 avgHelper(ValueType sum, uint64_t count) {
55   if (count == 0) { return ReturnType(0); }
56   return sum / static_cast<int64_t>(count);
57 }
58
59 // For unsigned integer input types, do unsigned division
60 template <typename ReturnType, typename ValueType>
61 typename std::enable_if<!std::is_floating_point<ReturnType>::value &&
62                         !std::is_floating_point<ValueType>::value &&
63                         std::is_unsigned<ValueType>::value,
64                         ReturnType>::type
65 avgHelper(ValueType sum, uint64_t count) {
66   if (count == 0) { return ReturnType(0); }
67   return sum / count;
68 }
69
70
71 template<typename T>
72 struct Bucket {
73  public:
74   typedef T ValueType;
75
76   Bucket()
77     : sum(ValueType()),
78       count(0) {}
79
80   void clear() {
81     sum = ValueType();
82     count = 0;
83   }
84
85   void add(const ValueType& s, uint64_t c) {
86     // TODO: It would be nice to handle overflow here.
87     sum += s;
88     count += c;
89   }
90
91   Bucket& operator+=(const Bucket& o) {
92     add(o.sum, o.count);
93     return *this;
94   }
95
96   Bucket& operator-=(const Bucket& o) {
97     // TODO: It would be nice to handle overflow here.
98     sum -= o.sum;
99     count -= o.count;
100     return *this;
101   }
102
103   template <typename ReturnType>
104   ReturnType avg() const {
105     return avgHelper<ReturnType>(sum, count);
106   }
107
108   ValueType sum;
109   uint64_t count;
110 };
111
112 }} // folly::detail
113
114 #endif // FOLLY_DETAIL_STATS_H_