rippled
DecayingSample.h
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012, 2013 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #ifndef RIPPLE_BASICS_DECAYINGSAMPLE_H_INCLUDED
21 #define RIPPLE_BASICS_DECAYINGSAMPLE_H_INCLUDED
22 
23 #include <chrono>
24 #include <cmath>
25 
26 namespace ripple {
27 
31 template <int Window, typename Clock>
33 {
34 public:
35  using value_type = typename Clock::duration::rep;
36  using time_point = typename Clock::time_point;
37 
38  DecayingSample() = delete;
39 
44  {
45  }
46 
52  {
53  decay(now);
54  m_value += value;
55  return m_value / Window;
56  }
57 
63  {
64  decay(now);
65  return m_value / Window;
66  }
67 
68 private:
69  // Apply exponential decay based on the specified time.
70  void
72  {
73  if (now == m_when)
74  return;
75 
76  if (m_value != value_type())
77  {
78  std::size_t elapsed =
79  std::chrono::duration_cast<std::chrono::seconds>(now - m_when)
80  .count();
81 
82  // A span larger than four times the window decays the
83  // value to an insignificant amount so just reset it.
84  //
85  if (elapsed > 4 * Window)
86  {
87  m_value = value_type();
88  }
89  else
90  {
91  while (elapsed--)
92  m_value -= (m_value + Window - 1) / Window;
93  }
94  }
95 
96  m_when = now;
97  }
98 
99  // Current value in exponential units
101 
102  // Last time the aging function was applied
104 };
105 
106 //------------------------------------------------------------------------------
107 
111 template <int HalfLife, class Clock>
113 {
114 public:
115  using time_point = typename Clock::time_point;
116 
117  explicit DecayWindow(time_point now) : value_(0), when_(now)
118  {
119  }
120 
121  void
122  add(double value, time_point now)
123  {
124  decay(now);
125  value_ += value;
126  }
127 
128  double
130  {
131  decay(now);
132  return value_ / HalfLife;
133  }
134 
135 private:
136  static_assert(HalfLife > 0, "half life must be positive");
137 
138  void
140  {
141  if (now <= when_)
142  return;
143  using namespace std::chrono;
144  auto const elapsed = duration<double>(now - when_).count();
145  value_ *= std::pow(2.0, -elapsed / HalfLife);
146  when_ = now;
147  }
148 
149  double value_;
151 };
152 
153 } // namespace ripple
154 
155 #endif
ripple::DecayWindow::decay
void decay(time_point now)
Definition: DecayingSample.h:139
ripple::DecayingSample< decayWindowSeconds, abstract_clock< std::chrono::steady_clock > >::value_type
typename abstract_clock< std::chrono::steady_clock > ::duration::rep value_type
Definition: DecayingSample.h:35
ripple::DecayingSample::m_value
value_type m_value
Definition: DecayingSample.h:100
ripple::DecayingSample::value
value_type value(time_point now)
Retrieve the current value in normalized units.
Definition: DecayingSample.h:62
std::chrono::duration
ripple::DecayWindow
Sampling function using exponential decay to provide a continuous value.
Definition: DecayingSample.h:112
ripple::DecayingSample::m_when
time_point m_when
Definition: DecayingSample.h:103
ripple::DecayingSample< decayWindowSeconds, abstract_clock< std::chrono::steady_clock > >::time_point
typename abstract_clock< std::chrono::steady_clock > ::time_point time_point
Definition: DecayingSample.h:36
cmath
ripple::DecayingSample::DecayingSample
DecayingSample(time_point now)
Definition: DecayingSample.h:43
chrono
ripple::DecayWindow::time_point
typename Clock::time_point time_point
Definition: DecayingSample.h:115
ripple::DecayingSample::add
value_type add(value_type value, time_point now)
Add a new sample.
Definition: DecayingSample.h:51
ripple::DecayWindow::DecayWindow
DecayWindow(time_point now)
Definition: DecayingSample.h:117
ripple::DecayingSample::DecayingSample
DecayingSample()=delete
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::DecayWindow::value
double value(time_point now)
Definition: DecayingSample.h:129
ripple::DecayWindow::value_
double value_
Definition: DecayingSample.h:149
ripple::DecayWindow::add
void add(double value, time_point now)
Definition: DecayingSample.h:122
std::chrono::duration::count
T count(T... args)
std::size_t
ripple::DecayingSample
Sampling function using exponential decay to provide a continuous value.
Definition: DecayingSample.h:32
ripple::DecayWindow::when_
time_point when_
Definition: DecayingSample.h:150
ripple::DecayingSample::decay
void decay(time_point now)
Definition: DecayingSample.h:71
std::pow
T pow(T... args)
std::chrono