5#ifndef LINE_API_PFQN_INFRADIUS_H_H
6#define LINE_API_PFQN_INFRADIUS_H_H
67Cx<T> gldsingle_complex(
const std::vector<Cx<T>>& L,
int N,
const Matrix<T>& mu) {
68 const std::size_t M = L.size();
69 if (M == 0)
throw InputError(
"gldsingle_complex: empty demand vector");
70 if (N < 0)
throw InputError(
"gldsingle_complex: negative population");
71 if (mu.rows() != M)
throw InputError(
"gldsingle_complex: mu has the wrong station count");
72 if (N > 0 && mu.cols() <
static_cast<std::size_t
>(N))
73 throw InputError(
"gldsingle_complex: mu has fewer rate columns than the population");
74 const T zero = num_traits<T>::from_int(0), one = num_traits<T>::from_int(1);
75 const std::size_t Nn =
static_cast<std::size_t
>(N);
77 std::vector<std::vector<std::vector<Cx<T>>>> g(
78 M + 1, std::vector<std::vector<Cx<T>>>(Nn + 1, std::vector<Cx<T>>(Nn + 2, Cx<T>())));
79 for (std::size_t m = 1; m <= M; ++m) {
80 for (std::size_t tm = 0; tm <= Nn; ++tm) g[m][0][tm] = Cx<T>(one);
81 for (std::size_t n = 1; n <= Nn; ++n)
82 for (std::size_t tm = 0; tm + n <= Nn; ++tm) {
83 const T rate = mu(m - 1, tm);
85 throw NumericError(
"gldsingle_complex: a load-dependent rate is zero");
86 const Cx<T> term = cx_scale(cx_mul(L[m - 1], g[m][n - 1][tm + 1]), T(one / rate));
87 g[m][n][tm] = cx_add(g[m - 1][n][0], term);
107 "infradius_h requires transcendental arithmetic (logistic map and e^{2 pi i t})");
109 const std::size_t M = L.
rows(), R = L.
cols();
110 if (N.size() != R || x.size() != R)
111 throw InputError(
"infradius_h: x, L and N disagree on the class count");
114 for (
const T& v : N) Nt += v;
118 for (std::size_t r = 0; r < R; ++r) {
119 const T e = exp(x[r]);
120 t[r] = T(e / T(one + e));
121 tb += T(N[r] / Nt) * t[r];
122 jac *= T(e / T(T(one + e) * T(one + e)));
126 std::vector<detail::Cx<T>>
Lc(M);
127 for (std::size_t m = 0; m < M; ++m) {
129 for (std::size_t r = 0; r < R; ++r)
130 acc = detail::cx_add(acc, detail::cx_scale(detail::cx_expi(T(twopi * T(t[r] - tb))),
134 const detail::Cx<T> G =
136 return T(G.re * jac);
147 "infradius_hnorm requires transcendental arithmetic (normal CDF and density)");
149 const std::size_t M = L.
rows(), R = L.
cols();
150 if (N.size() != R || x.size() != R)
151 throw InputError(
"infradius_hnorm: x, L and N disagree on the class count");
153 for (
const T& v : N) Nt += v;
155 const double invsqrt2pi = 0.39894228040143267793994605993438;
158 for (std::size_t r = 0; r < R; ++r) {
161 tb += T(N[r] / Nt) * t[r];
166 std::vector<detail::Cx<T>>
Lc(M);
167 for (std::size_t m = 0; m < M; ++m) {
169 for (std::size_t r = 0; r < R; ++r)
170 acc = detail::cx_add(acc, detail::cx_scale(detail::cx_expi(T(twopi * T(t[r] - tb))),
174 const detail::Cx<T> G =
176 return T(G.re * jac);
NumericError(const std::string &what)
The exception types the port throws.
Dense matrix and non-owning view.
@ Lc
Birman-Kogan Algorithm 2, single chain subproblems by MVA.
T infradius_h(const std::vector< T > &x, const Matrix< T > &L, const std::vector< T > &N, const Matrix< T > &alpha)
Logistic-substitution integrand (matlab/src/api/pfqn/infradius_h.m).
T infradius_hnorm(const std::vector< T > &x, const Matrix< T > &L, const std::vector< T > &N, const Matrix< T > &alpha)
Normal-CDF substitution integrand (matlab/src/api/pfqn/infradius_hnorm.m).
Number-type abstraction for the templated API port.
Shared scalar machinery for the integration / asymptotic members of the pfqn family (pfqn_le,...