5#ifndef LINE_API_MOMENT_MOMENT_TENSOR_H
6#define LINE_API_MOMENT_MOMENT_TENSOR_H
43 std::vector<std::size_t>
sz;
52 explicit MomentTensor(
const std::vector<std::size_t>& extents) :
sz(extents) {
57 std::size_t
order()
const {
return sz.size(); }
61 for (std::size_t l = 0; l <
sz.size(); ++l) n *=
sz[l];
66 std::size_t
stride(std::size_t l)
const {
68 for (std::size_t k = 0; k < l; ++k) s *=
sz[k];
73 std::size_t
index(
const std::vector<std::size_t>& ord)
const {
74 if (ord.size() !=
sz.size())
throw InputError(
"MomentTensor: wrong multi-index length");
75 std::size_t ia = 0, s = 1;
76 for (std::size_t l = 0; l <
sz.size(); ++l) {
77 if (ord[l] >=
sz[l])
throw InputError(
"MomentTensor: multi-index out of range");
84 const T&
at(
const std::vector<std::size_t>& ord)
const {
return data[
index(ord)]; }
85 T&
at(
const std::vector<std::size_t>& ord) {
return data[
index(ord)]; }
89 while (
sz.size() > 1 &&
sz.back() == 1)
sz.pop_back();
90 if (
sz.empty())
sz.assign(1, 0);
104 if (mode >= A.
order())
105 throw InputError(
"moment_tensortrans: the mode must be a dimension index of A");
106 const std::size_t n = A.
sz[mode];
107 if (Tm.
cols() != n || Tm.
rows() != n)
109 "moment_tensortrans: T must be square with as many columns as the extent of the "
110 "transformed dimension");
111 const std::size_t inner = A.
stride(mode);
112 const std::size_t outer = A.
numel() / (inner * n);
114 std::vector<T> fibre(n);
115 for (std::size_t o = 0; o < outer; ++o)
116 for (std::size_t i = 0; i < inner; ++i) {
117 const std::size_t base = o * inner * n + i;
118 for (std::size_t k = 0; k < n; ++k) fibre[k] = A.
data[base + k * inner];
119 for (std::size_t r = 0; r < n; ++r) {
121 for (std::size_t k = 0; k < n; ++k) acc += Tm(r, k) * fibre[k];
122 B.
data[base + r * inner] = acc;
132 for (std::size_t mode = 0; mode < A.
order(); ++mode)
The exception types the port throws.
Dense matrix and non-owning view.
Conversion matrix of one edge of the house of moments.
std::vector< std::size_t > moment_tensorsize(const MomentTensor< T > &A)
Extents with the trailing singleton dimensions removed.
Matrix< T > moment_housematrix(MomentEdge edge, int n)
(n+1)x(n+1) conversion table of the given edge.
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_jointtrans(const MomentTensor< T > &A, MomentEdge edge)
Applies the conversion matrix of one edge along every dimension of A.
MomentEdge
Edge labels of the house of moments, one per MATLAB edge string.
MomentEdge moment_edge_from_string(const std::string &edge)
Parses the MATLAB edge string into its label.
Number-type abstraction for the templated API port.
Joint moment array of size (n_1+1)x...x(n_d+1), stored column major.
T & at(const std::vector< std::size_t > &ord)
std::size_t order() const
MomentTensor(const std::vector< T > &v)
A plain moment vector, i.e.
std::vector< std::size_t > sz
std::size_t stride(std::size_t l) const
Stride of dimension l in the column-major layout.
MomentTensor(const std::vector< std::size_t > &extents)
A zero-filled array of the given extents, with trailing singletons dropped.
const T & at(const std::vector< std::size_t > &ord) const
std::size_t numel() const
std::size_t index(const std::vector< std::size_t > &ord) const
Linear index of the multi-index ord, whose entries are the moment orders.
void normalize()
Drops the trailing singleton dimensions, keeping at least one.