1 #ifndef MEDUSA_BITS_APPROXIMATIONS_MONOMIALS_HPP_
2 #define MEDUSA_BITS_APPROXIMATIONS_MONOMIALS_HPP_
17 template <
class vec_t>
19 assert_msg(-1 <= order,
"Requested monomials of negative order %d.", order);
20 setFromPowers(generatePowers(order,
dim));
23 template <
class vec_t>
25 if (max_order < 0)
return {};
26 if (
dim == 0)
return {{}};
27 std::vector<std::vector<int>> powers;
28 for (
int i = 0; i <= max_order; ++i) {
29 auto other = generatePowers(max_order - i,
dim-1);
30 for (
const auto& p : other) {
31 powers.push_back({i});
33 powers.back().push_back(o);
40 template <
class vec_t>
42 assert_msg(-1 <= order,
"Requested monomials of negative order %d.", order);
44 std::vector<std::vector<int>> powers;
48 powers.push_back(std::vector<int>(counter.begin(), counter.end()));
53 template <
class vec_t>
55 powers_.resize(
dim, powers.size());
56 int size = powers.size();
57 for (
int i = 0; i < size; ++i) {
58 const std::vector<int>& p = powers[i];
59 assert_msg(p.size() ==
dim,
"Monomial size %s does not match dimension %d", p.size(),
dim);
60 for (
int j = 0; j <
dim; ++j) {
66 template <
class vec_t>
68 int index,
const vec_t& point,
const std::vector<vector_t>& )
const {
69 assert_msg(0 <= index && index < size(),
"Monomial at index %d does not exist. "
70 "Index must be in range [0, %d).", index, size());
72 for (
int i = 0; i <
dim; i++) {
73 result *=
ipow(point[i], powers_(i, index));
78 template <
class vec_t>
83 for (
int d = 0; d <
dim; ++d) {
84 if (powers_(d, index) <= 1)
continue;
86 for (
int i = 0; i < d; i++) {
87 der2 *=
ipow(point[i], powers_(i, index));
89 der2 *= powers_(d, index) * (powers_(d, index) - 1) *
ipow(point[d], powers_(d, index)-2);
90 for (
int i = d+1; i <
dim; i++) {
91 der2 *=
ipow(point[i], powers_(i, index));
95 return result/scale/scale;
98 template <
class vec_t>
102 if (powers_(op.
var, index) == 0)
return 0;
104 for (
int i = 0; i < op.
var; i++) {
105 result *=
ipow(point[i], powers_(i, index));
107 result *= powers_(op.
var, index)*
ipow(point[op.
var], powers_(op.
var, index)-1);
108 for (
int i = op.
var+1; i <
dim; i++) {
109 result *=
ipow(point[i], powers_(i, index));
114 template <
class vec_t>
119 if (powers_(op.
var1, index) <= 1)
return 0;
121 for (
int i = 0; i < op.
var1; i++) {
122 result *=
ipow(point[i], powers_(i, index));
124 result *= powers_(op.
var1, index) * (powers_(op.
var1, index)-1) *
126 for (
int i = op.
var1+1; i <
dim; i++) {
127 result *=
ipow(point[i], powers_(i, index));
129 return result/scale/scale;
131 if (powers_(op.
var1, index) == 0 || powers_(op.
var2, index) == 0 )
return 0;
133 for (
int i = 0; i < op.
var1; i++) {
134 result *=
ipow(point[i], powers_(i, index));
136 result *= powers_(op.
var1, index)*
ipow(point[op.
var1], powers_(op.
var1, index)-1);
137 for (
int i = op.
var1+1; i < op.
var2; i++) {
138 result *=
ipow(point[i], powers_(i, index));
140 result *= powers_(op.
var2, index)*
ipow(point[op.
var2], powers_(op.
var2, index)-1);
141 for (
int i = op.
var2+1; i <
dim; i++) {
142 result *=
ipow(point[i], powers_(i, index));
144 return result/scale/scale;
148 template <
class vec_t>
151 assert_msg(0 <= index && index < size(),
"Monomial at index %d does not exist. "
152 "Index must be in range [0, %d).", index, size());
155 assert_msg(x >= 0,
"Derivative of negative order %d requested.", x);
159 for (
int i = 0; i <
dim; i++) {
160 if (d.
orders[i] > powers_(i, index)) {
164 result *=
ipow(point[i], powers_(i, index) - d.
orders[i]);
165 for (
int j = powers_(i, index); j > powers_(i, index) - d.
orders[i]; j--) {
169 return result /
ipow(scale, totaldeg);
172 template <
class vec_t>
174 assert_msg(0 <= index && index < size(),
"Monomial at index %d does not exist. "
175 "Index must be in range [0, %d).", index, size());
176 return powers_.col(index).sum() == 0;
180 template <
class vec_t>
181 template <
typename operator_t>
183 const std::vector<vector_t>& support,
scalar_t scale)
const {
184 return op.apply(*
this, index, point, support, scale);
188 template <
class vec_t>
190 const std::vector<vector_t>&,
scalar_t scale)
const {
191 assert_msg(0 <= index && index < size(),
"Monomial at index %d does not exist. "
192 "Index must be in range [0, %d).", index, size());
195 if (powers()(d, index) != 2)
continue;
198 int p = powers()(i, index);
199 if (i != d && p != 0) { r = 0;
break; }
203 return result / (scale*scale);
206 template <
class vec_t>
208 const std::vector<vector_t>& ,
scalar_t scale)
const {
209 assert_msg(der1.
var >= 0,
"Index of derived variable %d should be higher or equal to 0.",
212 " than the number of dimensions %d", der1.
var,
dim);
213 assert_msg(0 <= index && index < size(),
"Monomial at index %d does not exist. "
214 "Index must be in range [0, %d).", index, size());
217 if (powers()(d, index) == 1) {
220 int p = powers()(i, index);
221 if (i != d && p != 0) r=0;
227 template <
class vec_t>
229 const std::vector<vector_t>& ,
scalar_t scale)
const {
230 assert_msg(der2.
var1 >= 0 && der2.
var2 >=0,
"Index of derived variables %d and %d should"
231 " be both higher or equal to 0.",
234 " both be lower than the number of dimensions %d", der2.
var1, der2.
var2,
dim);
235 assert_msg(0 <= index && index < size(),
"Monomial at index %d does not exist. "
236 "Index must be in range [0, %d).", index, size());
242 if (powers()(
d1, index) == 2) {
245 int p = powers()(i, index);
246 if (i !=
d1 && p != 0) r = 0;
250 if (powers()(
d1, index) == 1 && powers()(
d2, index) == 1) {
253 int p = powers()(i, index);
254 if (i !=
d1 && i !=
d2 && p != 0) r = 0;
258 return r / (scale * scale);
261 template <
class vec_t>
263 const std::vector<vector_t>& support,
scalar_t scale)
const {
264 return evalOp(index, 0.0, der, support, scale);
270 return os <<
"Monomials " << m.
dim <<
"D: "
271 << m.
powers_.transpose() <<
", number of functions = " << m.
size();
276 #endif // MEDUSA_BITS_APPROXIMATIONS_MONOMIALS_HPP_