5#ifndef LINE_API_MOMENT_MOMENT_JOINT_H
6#define LINE_API_MOMENT_MOMENT_JOINT_H
130inline void moment_odometer(std::vector<std::size_t>& ord,
const std::vector<std::size_t>& sz) {
131 for (std::size_t l = 0; l < ord.size(); ++l) {
133 if (ord[l] < sz[l])
return;
144std::vector<T> moment_joint_cumulant_body(
const std::vector<std::size_t>& sz,
145 const std::vector<T>& src,
bool cumulant_from_raw) {
146 const std::size_t d = sz.size();
148 for (std::size_t l = 0; l < d; ++l) nel *= sz[l];
149 std::vector<std::size_t> stride(d, 1);
150 for (std::size_t l = 1; l < d; ++l) stride[l] = stride[l - 1] * sz[l - 1];
151 std::vector<T> dst(nel, num_traits<T>::from_int(0));
152 if (!cumulant_from_raw) dst[0] = num_traits<T>::from_int(1);
153 std::vector<std::size_t> ord(d, 0), bord(d, 0);
154 for (std::size_t ia = 0; ia < nel; ++ia) {
156 for (std::size_t l = 0; l < d; ++l)
162 T acc = num_traits<T>::from_int(0);
164 for (std::size_t l = 0; l < d; ++l) nb *= ord[l] + 1;
165 std::fill(bord.begin(), bord.end(),
static_cast<std::size_t
>(0));
166 for (std::size_t ib = 0; ib < nb; ++ib) {
167 bool any_pos =
false, equal_a =
true;
168 for (std::size_t l = 0; l < d; ++l) {
169 if (bord[l] > 0) any_pos =
true;
170 if (bord[l] != ord[l]) equal_a =
false;
173 any_pos && bord[j] > 0 && (!cumulant_from_raw || !equal_a);
175 T c = num_traits<T>::from_int(1);
176 for (std::size_t l = 0; l < d; ++l) {
177 const int alpha =
static_cast<int>(ord[l]) - (l == j ? 1 : 0);
178 const int beta =
static_cast<int>(bord[l]) - (l == j ? 1 : 0);
181 std::size_t ib_lin = 0, ic_lin = 0;
182 for (std::size_t l = 0; l < d; ++l) {
183 ib_lin += bord[l] * stride[l];
184 ic_lin += (ord[l] - bord[l]) * stride[l];
187 acc += cumulant_from_raw ? c * dst[ib_lin] * src[ic_lin]
188 : c * src[ib_lin] * dst[ic_lin];
191 for (std::size_t l = 0; l < d; ++l) {
193 if (bord[l] <= ord[l])
break;
197 dst[ia] = cumulant_from_raw ? src[ia] - acc : acc;
199 moment_odometer(ord, sz);
210 kappa.
data = detail::moment_joint_cumulant_body<T>(m.
sz, m.
data,
true);
218 m.
data = detail::moment_joint_cumulant_body<T>(kappa.
sz, kappa.
data,
false);
237 const std::vector<T>& mu) {
238 const std::size_t d = m.
order();
241 "moment_joint_central_from_raw_mean: mu must have one entry per dimension of m");
243 for (std::size_t mode = 0; mode < d; ++mode) {
244 const int n =
static_cast<int>(m.
sz[mode]) - 1;
245 Matrix<T> Tm(
static_cast<std::size_t
>(n) + 1,
static_cast<std::size_t
>(n) + 1,
247 const T negmu = -mu[mode];
248 for (
int i = 0; i <= n; ++i)
249 for (
int k = 0; k <= i; ++k)
259 const std::size_t d = m.
order();
260 for (std::size_t l = 0; l < d; ++l)
263 "moment_joint_central_from_raw: the means m_(e_j) are required, hence every "
264 "dimension of m must have at least 2 elements");
265 std::vector<T> mu(d);
266 for (std::size_t l = 0; l < d; ++l) mu[l] = m.
data[m.
stride(l)];
273 const std::vector<T>& mu) {
274 const std::size_t d =
mc.order();
277 "moment_joint_raw_from_central: mu must have one entry per dimension of mc");
279 for (std::size_t mode = 0; mode < d; ++mode) {
280 const int n =
static_cast<int>(
mc.sz[mode]) - 1;
281 Matrix<T> Tm(
static_cast<std::size_t
>(n) + 1,
static_cast<std::size_t
>(n) + 1,
283 for (
int i = 0; i <= n; ++i)
284 for (
int k = 0; k <= i; ++k)
302 const std::size_t d = F.
order();
303 std::size_t nmax = F.
sz[0];
304 for (std::size_t l = 1; l < d; ++l) nmax = F.
sz[l] < nmax ? F.
sz[l] : nmax;
305 if (nmax == 0)
throw InputError(
"moment_joint_aggregate: F must be nonempty");
308 std::vector<std::size_t> ord(d, 0);
309 const std::size_t nel = F.
numel();
310 for (std::size_t ia = 0; ia < nel; ++ia) {
312 for (std::size_t l = 0; l < d; ++l) n += ord[l];
315 for (std::size_t l = 0; l < d; ++l)
317 f[n] += c * F.
data[ia];
319 detail::moment_odometer(ord, F.
sz);
327 const std::vector<std::size_t>& dims) {
328 const std::size_t d = p.size();
329 if (dims.size() != d)
330 throw InputError(
"moment_joint_marking: p and dims must have the same length");
331 std::size_t total = 0;
332 for (std::size_t l = 0; l < d; ++l) total += dims[l];
333 if (f.empty() || total > f.size() - 1)
335 "moment_joint_marking: the aggregate factorial moments must reach order sum(dims)");
336 std::vector<std::size_t> sz(d);
337 for (std::size_t l = 0; l < d; ++l) sz[l] = dims[l] + 1;
339 std::vector<std::size_t> ord(d, 0);
340 const std::size_t nel = F.
numel();
341 for (std::size_t ia = 0; ia < nel; ++ia) {
344 for (std::size_t l = 0; l < d; ++l) {
345 c *=
num_pow_int(p[l],
static_cast<unsigned>(ord[l]));
348 F.
data[ia] = c * f[n];
349 detail::moment_odometer(ord, sz);
The exception types the port throws.
Dense matrix and non-owning view.
Conversion matrix of one edge of the house of moments.
Joint moment arrays and the mode products used by every joint conversion.
std::vector< T > moment_joint_aggregate(const MomentTensor< T > &F)
Factorial moments of a total count from the joint factorial moments of its parts.
MomentTensor< T > moment_joint_marking(const std::vector< T > &f, const std::vector< T > &p, const std::vector< std::size_t > &dims)
Joint factorial moments of a multinomially marked count from the aggregate ones.
MomentTensor< T > moment_joint_negbinomial_from_binomial(const MomentTensor< T > &b)
Joint negative-binomial moments from joint binomial moments.
MomentTensor< T > moment_joint_binomial_from_negbinomial(const MomentTensor< T > &bm)
Joint binomial moments from joint negative-binomial moments.
MomentTensor< T > moment_joint_binomial_from_factorial(const MomentTensor< T > &f)
Joint binomial moments from joint factorial moments.
MomentTensor< T > moment_joint_central_from_tail(const MomentTensor< T > &t)
Joint central moments from joint tail moments.
MomentTensor< T > moment_joint_central_from_raw(const MomentTensor< T > &m)
Joint central moments from joint raw moments, reading the means off m.
MomentTensor< T > moment_tensortrans(const MomentTensor< T > &A, const Matrix< T > &Tm, std::size_t mode)
Mode product: every fibre of A along dimension mode is replaced by Tm times that fibre.
MomentTensor< T > moment_joint_central_from_raw_mean(const MomentTensor< T > &m, const std::vector< T > &mu)
Joint central moments from joint raw moments about a given mean vector.
MomentTensor< T > moment_joint_factorial_from_factcumulant(const MomentTensor< T > &kappa)
Joint factorial moments from joint factorial cumulants.
MomentTensor< T > moment_joint_upfactorial_from_raw(const MomentTensor< T > &m)
Joint upper-factorial moments from joint raw moments.
MomentTensor< T > moment_joint_factorial_from_raw(const MomentTensor< T > &m)
Joint factorial moments from joint raw moments.
MomentTensor< T > moment_joint_upfactorial_from_negbinomial(const MomentTensor< T > &bm)
Joint upper-factorial moments from joint negative-binomial moments.
MomentTensor< T > moment_joint_factorial_from_binomial(const MomentTensor< T > &b)
Joint factorial moments from joint binomial moments.
MomentTensor< T > moment_joint_factorial_from_upfactorial(const MomentTensor< T > &fp)
Joint factorial moments from joint upper-factorial moments.
MomentTensor< T > moment_jointtrans(const MomentTensor< T > &A, MomentEdge edge)
Applies the conversion matrix of one edge along every dimension of A.
MomentTensor< T > moment_joint_raw_from_cumulant(const MomentTensor< T > &kappa)
Joint raw moments from joint cumulants.
MomentTensor< T > moment_joint_upfactorial_from_factorial(const MomentTensor< T > &f)
Joint upper-factorial moments from joint factorial moments.
MomentTensor< T > moment_joint_raw_from_upfactorial(const MomentTensor< T > &fp)
Joint raw moments from joint upper-factorial moments.
MomentTensor< T > moment_joint_raw_from_factorial(const MomentTensor< T > &f)
Joint raw moments from joint factorial moments.
@ UpfactorialFromFactorial
@ FactorialFromUpfactorial
@ BinomialFromNegbinomial
@ NegbinomialFromBinomial
@ UpfactorialFromNegbinomial
@ NegbinomialFromUpfactorial
MomentTensor< T > moment_joint_tail_from_binomial(const MomentTensor< T > &b)
Joint tail moments from joint binomial moments.
MomentTensor< T > moment_joint_factcumulant_from_factorial(const MomentTensor< T > &f)
Joint factorial cumulants from joint factorial moments.
MomentTensor< T > moment_joint_cumulant_from_raw(const MomentTensor< T > &m)
Joint cumulants from joint raw moments.
MomentTensor< T > moment_joint_raw_from_central(const MomentTensor< T > &mc, const std::vector< T > &mu)
Joint raw moments from joint central moments about a given mean vector.
MomentTensor< T > moment_joint_binomial_from_tail(const MomentTensor< T > &t)
Joint binomial moments from joint tail moments.
MomentTensor< T > moment_joint_negbinomial_from_upfactorial(const MomentTensor< T > &fp)
Joint negative-binomial moments from joint upper-factorial moments.
T num_factorial(unsigned n)
Factorial as a value of T.
T num_pow_int(const T &base, unsigned e)
Integer power, valid in any field (no transcendental requirement).
T num_nck(int n, int k)
Binomial coefficient as a value of T, by the Pascal recurrence.
Number-type abstraction for the templated API port.
Population-vector enumeration and combinatorics.
Joint moment array of size (n_1+1)x...x(n_d+1), stored column major.
std::size_t order() const
std::vector< std::size_t > sz
std::size_t stride(std::size_t l) const
Stride of dimension l in the column-major layout.
std::size_t numel() const