rippled
Loading...
Searching...
No Matches
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
26namespace ripple {
27
31template <int Window, typename Clock>
33{
34public:
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
68private:
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 {
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
111template <int HalfLife, class Clock>
113{
114public:
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
135private:
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
Sampling function using exponential decay to provide a continuous value.
void decay(time_point now)
double value(time_point now)
DecayWindow(time_point now)
typename Clock::time_point time_point
void add(double value, time_point now)
Sampling function using exponential decay to provide a continuous value.
typename Clock::duration::rep value_type
void decay(time_point now)
DecayingSample(time_point now)
value_type add(value_type value, time_point now)
Add a new sample.
typename Clock::time_point time_point
value_type value(time_point now)
Retrieve the current value in normalized units.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: algorithm.h:25
T pow(T... args)