5#ifndef LINE_API_CACHE_T_HLRU_H
6#define LINE_API_CACHE_T_HLRU_H
52 return num_traits<T>::from_double(1e-14);
56 return num_traits<T>::from_double(1e-8);
64Matrix<T> hlru_levelprobs(
const std::vector<T>& lam,
const std::vector<T>& T_) {
66 const std::size_t n = lam.size();
67 const std::size_t h = T_.size();
68 const T one = num_traits<T>::from_int(1);
69 const T zeroTol = hlru_zero<T>();
70 Matrix<T> P(n, h + 1, num_traits<T>::from_int(0));
71 for (std::size_t k = 0; k < n; ++k) {
72 std::vector<T> w(h + 1, one);
73 for (std::size_t l = 0; l < h; ++l) {
74 const T e = exp(T(-lam[k] * T_[l]));
75 const T den = e > zeroTol ? e : zeroTol;
76 w[l + 1] = w[l] * (one - e) / den;
78 T s = num_traits<T>::from_int(0);
79 for (std::size_t l = 0; l <= h; ++l) s += w[l];
80 for (std::size_t l = 0; l <= h; ++l) P(k, l) = w[l] / s;
87T hlru_occ(
const std::vector<T>& lam, std::vector<T> T_, std::size_t l,
const T& Tl) {
89 const Matrix<T> P = hlru_levelprobs(lam, T_);
90 T occ = num_traits<T>::from_int(0);
91 for (std::size_t k = 0; k < lam.size(); ++k) occ += P(k, l + 1);
97std::vector<T> hlru_solve_times(
const std::vector<T>& lam,
const std::vector<int>& m) {
98 const std::size_t n = lam.size();
99 const std::size_t h = m.size();
100 if (n == 0)
throw InputError(
"cache_t_hlru: no items");
101 const T zero = num_traits<T>::from_int(0);
102 const T two = num_traits<T>::from_int(2);
105 for (std::size_t k = 0; k < n; ++k) mean += lam[k];
106 mean /= num_traits<T>::from_int(
static_cast<long>(n));
107 const T scale = mean > hlru_finetol<T>() ? mean : hlru_finetol<T>();
108 const T T0 = num_traits<T>::from_int(1) / scale;
109 const T hicap = num_traits<T>::from_double(1e12);
111 std::vector<T> Tv(h, T0);
112 for (
int sweep = 0; sweep < 200; ++sweep) {
113 const std::vector<T> Told = Tv;
114 for (std::size_t l = 0; l < h; ++l) {
115 const T ml = num_traits<T>::from_int(
static_cast<long>(m[l]));
117 T hi = Tv[l] > T0 ? Tv[l] : T0;
118 while (hlru_occ(lam, Tv, l, hi) < ml && hi < hicap) hi = two * hi;
119 for (
int b = 0; b < 100; ++b) {
120 const T mid = (lo + hi) / two;
121 if (hlru_occ(lam, Tv, l, mid) < ml)
126 Tv[l] = (lo + hi) / two;
129 for (std::size_t l = 0; l < h; ++l) {
130 const T den = Told[l] > hlru_zero<T>() ? Told[l] : hlru_zero<T>();
131 const T d =
num_abs(T(Tv[l] - Told[l])) / den;
132 if (d > rel) rel = d;
134 if (rel < hlru_finetol<T>())
break;
153 "cache_t_hlru requires transcendental arithmetic");
154 if (gamma.
cols() == 0)
throw InputError(
"cache_t_hlru: empty rate matrix");
155 std::vector<T> lam(gamma.
rows());
156 for (std::size_t k = 0; k < gamma.
rows(); ++k) lam[k] = gamma(k, 0);
157 return detail::hlru_solve_times(lam, m);
The exception types the port throws.
Dense matrix and non-owning view.
std::vector< T > cache_t_hlru(const Matrix< T > &gamma, const std::vector< int > &m)
Characteristic times of the h-LRU / LRU(m) TTL approximation.
Number-type abstraction for the templated API port.