carl  23.05
Computer ARithmetic Library
Conversion.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <carl-common/config.h>
4 
8 
9 namespace carl {
10 
11 namespace convert_poly {
12 template<typename T, typename S>
13 struct ConvertHelper {};
14 
15 template<typename A, typename B, typename C>
18  return ContextPolynomial<A, B, C>(context, p);
19  }
20 };
21 
22 template<typename A, typename B, typename C>
25  return p.as_multivariate();
26  }
27 };
28 
29 #ifdef USE_LIBPOLY
30 template<typename A, typename B, typename C>
31 struct ConvertHelper<LPPolynomial, MultivariatePolynomial<A, B, C>> {
32  static LPPolynomial convert(const LPContext& context, const MultivariatePolynomial<A, B, C>& p) {
33  CARL_LOG_DEBUG("carl.converter", "Converting Carl Multivariate Poly " << p << " with LPContext " << context);
34 
35  // Problem: LPPolynomials must have mpz_class as coefficient type -> might loose information when converting mpq_class to mpz_class
36 
37  if (carl::is_constant(p)) {
38  CARL_LOG_DEBUG("carl.converter", "Poly is constant");
39  return LPPolynomial(context, carl::get_num(p.constant_part()));
40  }
41 
42  auto denominator = p.coprime_factor();
43  if (denominator < 0) {
44  denominator *= -1;
45  }
46  /*
47  // LPPolynomial can only have integer coefficients -> so we have to store the lcm of the coefficients of every term
48  auto coprimeFactor = p.main_denom();
49  mpz_class denominator;
50  if (carl::get_denom(coprimeFactor) != 1) {
51  // if coprime factor is not an integer
52  denominator = coprimeFactor > 0 ? mpz_class(1) : mpz_class(-1);
53  } else {
54  denominator = mpz_class(coprimeFactor);
55  }
56  */
57  CARL_LOG_DEBUG("carl.converter", "Coprime Factor/ Denominator: " << denominator);
58  LPPolynomial res(context);
59  // iterate over terms
60  for (const auto& term : p) {
61  // Multiply by denominator to make the coefficient an integer
62  assert(carl::get_denom(term.coeff() * denominator) == 1);
63  LPPolynomial t(context, mpz_class(term.coeff() * denominator));
64  // iterate over monomial
65  if (term.monomial()) {
66  // A monomial is a vector of pairs <variable, power>
67  for (const std::pair<carl::Variable, std::size_t>& var_pow : (*term.monomial()).exponents()) {
68  // multiply 1*var^pow
69  t *=LPPolynomial(context, var_pow.first, mpz_class(1), (unsigned)var_pow.second);
70  }
71  }
72  CARL_LOG_TRACE("carl.converter", "converted term: " << term << " -> " << t);
73  res += t;
74  }
75  CARL_LOG_DEBUG("carl.converter", "Got Polynomial: " << res);
76  return res;
77  }
78 };
79 
80 namespace conversion_private {
81 template<typename T>
82 struct CollectTermData {
83  std::vector<carl::Term<T>> terms;
84  const LPContext& context;
85  CollectTermData(const LPContext& c) : context(c) {}
86 };
87 
88 template<typename T>
89 void collectTermDataFunction(const lp_polynomial_context_t* /*ctx*/, lp_monomial_t* m, void* d) {
90  CollectTermData<T>* data = static_cast<CollectTermData<T>*>(d);
91  carl::Term<T> term(mpz_class(&m->a)); // m->a is the integer coefficient
92  for (size_t i = 0; i < m->n; i++) { // m->n is the capacity of the power array
93  auto carl_var = data->context.carl_variable(m->p[i].x);
94  assert(carl_var.has_value());
95  term *= carl::Term<T>(1, *carl_var, m->p[i].d); // p[i].x is the variable, p[i].d is the power
96  }
97  data->terms.emplace_back(term);
98 }
99 } // namespace conversion_private
100 
101 template<typename A, typename B, typename C>
102 struct ConvertHelper<MultivariatePolynomial<A, B, C>, LPPolynomial> {
103  static MultivariatePolynomial<A, B, C> convert(const LPPolynomial& p) {
104  conversion_private::CollectTermData<A> termdata(p.context());
105  CARL_LOG_DEBUG("carl.converter", "Converting LPPolynomial " << p);
106  lp_polynomial_traverse(p.get_internal(), conversion_private::collectTermDataFunction<A>, &termdata);
107 
108  if (termdata.terms.empty()) {
109  return MultivariatePolynomial<A, B, C>();
110  }
111  return MultivariatePolynomial<A, B, C>(termdata.terms);
112  }
113 };
114 #endif
115 
116 }
117 
118 template<typename T, typename S, std::enable_if_t<is_polynomial_type<T>::value && is_polynomial_type<S>::value && !needs_context_type<T>::value, int> = 0>
119 inline T convert(const S& r) {
121 }
122 
123 template<typename T, typename S, std::enable_if_t<is_polynomial_type<T>::value && is_polynomial_type<S>::value && needs_context_type<T>::value, int> = 0>
124 inline T convert(const typename T::ContextType& c, const S& r) {
126 }
127 
128 } // namespace carl
#define CARL_LOG_TRACE(channel, msg)
Definition: carl-logging.h:44
#define CARL_LOG_DEBUG(channel, msg)
Definition: carl-logging.h:43
carl is the main namespace for the library.
bool is_constant(const ContextPolynomial< Coeff, Ordering, Policies > &p)
cln::cl_I get_num(const cln::cl_RA &n)
Extract the numerator from a fraction.
Definition: operations.h:60
BasicConstraint< ToPoly > convert(const typename ToPoly::ContextType &context, const BasicConstraint< FromPoly > &c)
Definition: Conversion.h:9
T convert(const T &r)
Definition: Conversion.h:8
cln::cl_I get_denom(const cln::cl_RA &n)
Extract the denominator from a fraction.
Definition: operations.h:69
The general-purpose multivariate polynomial class.
const Coeff & constant_part() const
Retrieve the constant term of this polynomial or zero, if there is no constant term.
static ContextPolynomial< A, B, C > convert(const Context &context, const MultivariatePolynomial< A, B, C > &p)
Definition: Conversion.h:17
static MultivariatePolynomial< A, B, C > convert(const ContextPolynomial< A, B, C > &p)
Definition: Conversion.h:24
MultivariatePolynomial< Coeff, Ordering, Policies > as_multivariate() const
Represents a single term, that is a numeric coefficient and a monomial.
Definition: Term.h:23