File indexing completed on 2026-06-02 08:17:11
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #ifndef LIBOME_LAURENT_POLYNOMIAL_H
0013 #define LIBOME_LAURENT_POLYNOMIAL_H
0014
0015 #include <utility>
0016 #include <type_traits>
0017 #include <initializer_list>
0018 #include <iterator>
0019 #include <vector>
0020 #include <cmath>
0021 #include <numeric>
0022 #include <apfel/ome/traits.h>
0023
0024 namespace apfel
0025 {
0026 namespace ome
0027 {
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047 template<typename Tnum, typename Tcoeff, typename... Tcoeffargs>
0048 class laurent_polynomial_view
0049 {
0050 public:
0051
0052 using numeric_type = Tnum;
0053
0054 using coefficient_type = Tcoeff;
0055
0056 using coefficient_has_view = has_view<coefficient_type>;
0057
0058 using has_eval_plus_int = std::true_type;
0059
0060 using coefficient_view_type = typename get_view_type<coefficient_type>::type;
0061
0062 using const_reverse_iterator = typename std::vector<coefficient_type>::const_reverse_iterator;
0063
0064
0065
0066
0067
0068
0069
0070
0071 laurent_polynomial_view(
0072 const_reverse_iterator crbegin,
0073 const_reverse_iterator crend,
0074 int min_power = 0)
0075 : coeffs_crbegin_(crbegin),
0076 coeffs_crend_(crend),
0077 min_power_(min_power) {};
0078
0079
0080
0081
0082 friend
0083 void swap(laurent_polynomial_view& first, laurent_polynomial_view& second)
0084 {
0085 using std::swap;
0086 swap(first.coeffs_crbegin_,second.coeffs_crbegin_);
0087 swap(first.coeffs_crend_,second.coeffs_crend_);
0088 swap(first.min_power_,second.min_power_);
0089 };
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106 numeric_type operator()(numeric_type x, Tcoeffargs... rest) const
0107 {
0108 using std::pow;
0109 const numeric_type prefactor = (min_power_ != 0) ? pow(x, min_power_) : static_cast<numeric_type>(1);
0110
0111 if constexpr(sizeof...(rest) > 0)
0112 {
0113 if(std::next(coeffs_crbegin_) == coeffs_crend_)
0114 {
0115 return(prefactor*(*coeffs_crbegin_)(rest...));
0116 }
0117 else
0118 {
0119 return(prefactor*std::accumulate(
0120 coeffs_crbegin_,
0121 coeffs_crend_,
0122 static_cast<numeric_type>(0),
0123 [&x, &rest...] (const numeric_type& acc, const coefficient_type& next)
0124 {
0125 return(x*acc + next(rest...));
0126 }
0127 ));
0128 }
0129 }
0130 else
0131 {
0132 if(std::next(coeffs_crbegin_) == coeffs_crend_)
0133 {
0134 return(prefactor*(*coeffs_crbegin_));
0135 }
0136 else
0137 {
0138 return(prefactor*std::accumulate(
0139 coeffs_crbegin_,
0140 coeffs_crend_,
0141 static_cast<numeric_type>(0),
0142 [&x] (const numeric_type& acc, const coefficient_type& next)
0143 {
0144 return(x*acc + next);
0145 }
0146 ));
0147 }
0148 }
0149 };
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167 numeric_type eval_subst(const std::vector<numeric_type>& subst, Tcoeffargs... rest) const
0168 {
0169 if constexpr(sizeof...(rest) > 0)
0170 {
0171 return(std::transform_reduce(
0172 coeffs_crbegin_,
0173 coeffs_crend_,
0174 subst.crbegin(),
0175 static_cast<numeric_type>(0),
0176 std::plus<>(),
0177 [&rest...] (const coefficient_type& c, const numeric_type& s)
0178 {
0179 return(c(rest...) * s);
0180 }
0181 ));
0182 }
0183 else
0184 {
0185 return(std::transform_reduce(
0186 coeffs_crbegin_,
0187 coeffs_crend_,
0188 subst.crbegin(),
0189 static_cast<numeric_type>(0)
0190 ));
0191 }
0192 };
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211 numeric_type eval_plus_int(numeric_type x, Tcoeffargs... rest) const
0212 {
0213 using std::pow;
0214 const numeric_type prefactor = (min_power_ != 0) ? pow(x, min_power_) : static_cast<numeric_type>(1);
0215
0216 if(std::next(coeffs_crbegin_) == coeffs_crend_)
0217 {
0218 return(prefactor * coeffs_crbegin_->eval_plus_int(rest...));
0219 }
0220 else
0221 {
0222 return(prefactor*std::accumulate(
0223 coeffs_crbegin_,
0224 coeffs_crend_,
0225 static_cast<numeric_type>(0),
0226 [&x, &rest...] (const numeric_type& acc, const coefficient_type& next)
0227 {
0228 return(x*acc + next.eval_plus_int(rest...));
0229 }
0230 ));
0231 }
0232 };
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249 laurent_polynomial_view truncate(int truncation_order) const
0250 {
0251 const int requested_orders = truncation_order - min_power_ + 1;
0252 const int available_orders = coeffs_crend_ - coeffs_crbegin_;
0253
0254 if(requested_orders <= 0)
0255 {
0256 return(laurent_polynomial_view(coeffs_crbegin_,
0257 coeffs_crbegin_, min_power_));
0258 }
0259 else if(requested_orders > available_orders)
0260 {
0261 return(laurent_polynomial_view(coeffs_crbegin_,
0262 coeffs_crend_, min_power_));
0263 }
0264 else
0265 {
0266 return(laurent_polynomial_view(
0267 coeffs_crbegin_ + (available_orders - requested_orders),
0268 coeffs_crend_,
0269 min_power_
0270 ));
0271 }
0272 };
0273
0274
0275
0276
0277
0278
0279 laurent_polynomial_view get_view() const
0280 {
0281 return(laurent_polynomial_view(*this));
0282 };
0283
0284
0285
0286
0287
0288
0289 int min_power() const
0290 {
0291 return(min_power_);
0292 };
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303 int max_power() const
0304 {
0305 return(min_power_ + (coeffs_crend_ - coeffs_crbegin_ - 1));
0306 };
0307
0308
0309
0310
0311
0312
0313
0314
0315 const coefficient_type& operator[](int pow) const
0316 {
0317 const int requested_position = pow - min_power_;
0318 const int size = coeffs_crend_ - coeffs_crbegin_;
0319 if(requested_position < 0 || requested_position >= size)
0320 return zero_value_;
0321 else
0322 return *(coeffs_crbegin_ + ((size-1) - requested_position));
0323 };
0324
0325 protected:
0326
0327 const_reverse_iterator coeffs_crbegin_;
0328
0329 const_reverse_iterator coeffs_crend_;
0330
0331
0332
0333
0334 laurent_polynomial_view(int min_power = 0)
0335 : min_power_(min_power) {};
0336
0337 private:
0338 int min_power_;
0339
0340 inline const static coefficient_type zero_value_{};
0341 };
0342
0343
0344
0345
0346
0347
0348
0349
0350
0351
0352
0353
0354
0355
0356
0357
0358
0359
0360
0361
0362
0363
0364
0365
0366
0367
0368 template<typename Tnum, typename Tcoeff, typename... Tcoeffargs>
0369 class laurent_polynomial
0370 : public laurent_polynomial_view<Tnum, Tcoeff, Tcoeffargs...>
0371 {
0372 public:
0373
0374 using view_type = laurent_polynomial_view<Tnum, Tcoeff, Tcoeffargs...>;
0375
0376 using typename view_type::numeric_type;
0377 using typename view_type::coefficient_type;
0378
0379
0380
0381
0382
0383 laurent_polynomial()
0384 : view_type(0),
0385 coefficients_()
0386 {
0387 this->coeffs_crbegin_ = coefficients_.crbegin();
0388 this->coeffs_crend_ = coefficients_.crend();
0389 };
0390
0391
0392
0393
0394
0395
0396
0397
0398
0399
0400 laurent_polynomial(const std::vector<coefficient_type>& coefficients,
0401 int min_power = 0)
0402 : view_type(min_power),
0403 coefficients_(coefficients)
0404 {
0405 this->coeffs_crbegin_ = coefficients_.crbegin();
0406 this->coeffs_crend_ = coefficients_.crend();
0407 };
0408
0409
0410
0411
0412
0413
0414
0415
0416 laurent_polynomial(std::initializer_list<coefficient_type> coefficients,
0417 int min_power = 0)
0418 : view_type(min_power),
0419 coefficients_(coefficients)
0420 {
0421 this->coeffs_crbegin_ = coefficients_.crbegin();
0422 this->coeffs_crend_ = coefficients_.crend();
0423 };
0424
0425
0426
0427
0428 laurent_polynomial(const laurent_polynomial& other)
0429 : view_type(other),
0430 coefficients_(other.coefficients_)
0431 {
0432 this->coeffs_crbegin_ = coefficients_.crbegin();
0433 this->coeffs_crend_ = coefficients_.crend();
0434 };
0435
0436
0437
0438
0439 friend
0440 void swap(laurent_polynomial& first, laurent_polynomial& second)
0441 {
0442
0443 using std::swap;
0444
0445
0446 swap(static_cast<view_type&>(first),static_cast<view_type&>(second));
0447
0448
0449 swap(first.coefficients_,second.coefficients_);
0450
0451
0452 first.coeffs_crbegin_ = first.coefficients_.crbegin();
0453 first.coeffs_crend_ = first.coefficients_.crend();
0454 second.coeffs_crbegin_ = second.coefficients_.crbegin();
0455 second.coeffs_crend_ = second.coefficients_.crend();
0456 };
0457
0458
0459
0460
0461 laurent_polynomial& operator=(laurent_polynomial other)
0462 {
0463 swap(*this, other);
0464 return(*this);
0465 };
0466
0467
0468
0469
0470 laurent_polynomial(laurent_polynomial&& other)
0471 : laurent_polynomial()
0472 {
0473 swap(*this, other);
0474 };
0475
0476 private:
0477 std::vector<coefficient_type> coefficients_;
0478 };
0479
0480 }
0481 }
0482
0483 #endif