BucketedTimeSeries: fix type converison issues computing avg()
[folly.git] / folly / detail / Stats.h
index 1b74aa4d7aad0be3dfb3d92760c5c8308a85c33d..b3fa7e68ea7300d39876871349895f49cef50817 100644 (file)
 
 namespace folly { namespace detail {
 
+/*
+ * Helper functions for how to perform division based on the desired
+ * return type.
+ */
+
+// For floating point input types, do floating point division
+template <typename ReturnType, typename ValueType>
+typename std::enable_if<std::is_floating_point<ValueType>::value,
+                        ReturnType>::type
+avgHelper(ValueType sum, uint64_t count) {
+  if (count == 0) { return ReturnType(0); }
+  return static_cast<ReturnType>(sum / count);
+}
+
+// For floating point return types, do floating point division
+template <typename ReturnType, typename ValueType>
+typename std::enable_if<std::is_floating_point<ReturnType>::value &&
+                        !std::is_floating_point<ValueType>::value,
+                        ReturnType>::type
+avgHelper(ValueType sum, uint64_t count) {
+  if (count == 0) { return ReturnType(0); }
+  return static_cast<ReturnType>(sum) / count;
+}
+
+// For signed integer input types, do signed division
+template <typename ReturnType, typename ValueType>
+typename std::enable_if<!std::is_floating_point<ReturnType>::value &&
+                        !std::is_floating_point<ValueType>::value &&
+                        std::is_signed<ValueType>::value,
+                        ReturnType>::type
+avgHelper(ValueType sum, uint64_t count) {
+  if (count == 0) { return ReturnType(0); }
+  return sum / static_cast<int64_t>(count);
+}
+
+// For unsigned integer input types, do unsigned division
+template <typename ReturnType, typename ValueType>
+typename std::enable_if<!std::is_floating_point<ReturnType>::value &&
+                        !std::is_floating_point<ValueType>::value &&
+                        std::is_unsigned<ValueType>::value,
+                        ReturnType>::type
+avgHelper(ValueType sum, uint64_t count) {
+  if (count == 0) { return ReturnType(0); }
+  return sum / count;
+}
+
+
 template<typename T>
 struct Bucket {
  public:
@@ -55,9 +102,7 @@ struct Bucket {
 
   template <typename ReturnType>
   ReturnType avg() const {
-    return (count ?
-            static_cast<ReturnType>(sum) / count :
-            ReturnType(0));
+    return avgHelper<ReturnType>(sum, count);
   }
 
   ValueType sum;