10 const Eigen::ArrayXd lambdas,
16 const double abs_x = std::abs(x);
17 const int sign_x =
sign(x);
18 const size_t n_lambda = lambdas.size();
22 std::vector<double> cum(n_lambda + 1, 0.0);
26 auto getCum = [&](
size_t i) ->
double {
27 i = std::min(i, n_lambda);
28 while (computed < i) {
30 cum[computed] = cum[computed - 1] + lambdas(computed - 1);
36 auto getLambdaSum = [&](
size_t start,
size_t len) ->
double {
37 return getCum(start + len) - getCum(start);
41 int ptr_j = clusters.
pointer(j);
42 size_t len_j = std::min(n_lambda - ptr_j, cluster_size);
43 const bool direction_up =
44 abs_x - getLambdaSum(ptr_j, len_j) > clusters.
coeff(j);
48 size_t start = clusters.
pointer(j + 1);
49 size_t len = std::min(n_lambda - start, cluster_size);
50 double lo = start < n_lambda ? getLambdaSum(start, len) : 0.0;
52 for (
int k = j; k >= 0; --k) {
54 len = std::min(n_lambda - start, cluster_size);
55 double hi = getLambdaSum(start, len);
56 double c_k = clusters.
coeff(k);
58 if (abs_x < lo + c_k) {
59 return { x - sign_x * lo, k + 1 };
60 }
else if (abs_x <= hi + c_k) {
61 return { sign_x * c_k, k };
66 return { x - sign_x * lo, 0 };
69 int end = clusters.
pointer(j + 1);
70 double hi = getLambdaSum(end - cluster_size, cluster_size);
72 for (
int k = j + 1; k < clusters.
n_clusters(); ++k) {
74 double lo = getLambdaSum(end - cluster_size, cluster_size);
75 double c_k = clusters.
coeff(k);
77 if (abs_x > hi + c_k) {
78 return { x - sign_x * hi, k - 1 };
79 }
else if (abs_x >= lo + c_k) {
80 return { sign_x * c_k, k };
86 return { x - sign_x * hi, clusters.
n_clusters() - 1 };