Merge remote-tracking branch 'origin/master' into windows
[scilab.git] / scilab / modules / ast / src / cpp / analysis / MultivariateMonomial.cpp
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2015 - Scilab Enterprises - Calixte DENIZET
4  *
5  * Copyright (C) 2012 - 2016 - Scilab Enterprises
6  *
7  * This file is hereby licensed under the terms of the GNU GPL v2.0,
8  * pursuant to article 5.3.4 of the CeCILL v.2.1.
9  * This file was originally licensed under the terms of the CeCILL v2.1,
10  * and continues to be available under such terms.
11  * For more information, see the COPYING file which you should have received
12  * along with this program.
13  *
14  */
15
16 #include <cmath>
17 #include <functional>
18
19 #include "gvn/MultivariateMonomial.hxx"
20
21 namespace analysis
22 {
23
24 bool MultivariateMonomial::contains(const uint64_t var) const
25 {
26     return monomial.find(var) != monomial.end();
27 }
28
29 bool MultivariateMonomial::checkVariable(const uint64_t max) const
30 {
31     return std::prev(monomial.end())->var <= max;
32 }
33
34 unsigned int MultivariateMonomial::exponent() const
35 {
36     unsigned int exp = 0;
37     for (const auto & ve : monomial)
38     {
39         exp += ve.exp;
40     }
41     return exp;
42 }
43
44 MultivariateMonomial & MultivariateMonomial::add(const VarExp & ve)
45 {
46     Monomial::iterator i = monomial.find(ve);
47     if (i == monomial.end())
48     {
49         monomial.insert(ve);
50     }
51     else
52     {
53         i->exp += ve.exp;
54     }
55     return *this;
56 }
57
58 MultivariateMonomial & MultivariateMonomial::add(VarExp && ve)
59 {
60     Monomial::iterator i = monomial.find(ve);
61     if (i == monomial.end())
62     {
63         monomial.emplace(std::move(ve));
64     }
65     else
66     {
67         i->exp += ve.exp;
68     }
69     return *this;
70 }
71
72 MultivariateMonomial MultivariateMonomial::operator*(const MultivariateMonomial & R) const
73 {
74     MultivariateMonomial res(*this);
75     res.coeff *= R.coeff;
76     for (const auto & ve : R.monomial)
77     {
78         res.add(ve);
79     }
80     return res;
81 }
82
83 MultivariateMonomial & MultivariateMonomial::operator*=(const MultivariateMonomial & R)
84 {
85     coeff *= R.coeff;
86     for (const auto & ve : R.monomial)
87     {
88         add(ve);
89     }
90     return *this;
91 }
92
93 MultivariateMonomial operator*(const int64_t L, const MultivariateMonomial & R)
94 {
95     return R * L;
96 }
97
98 MultivariateMonomial MultivariateMonomial::operator*(const int64_t R) const
99 {
100     MultivariateMonomial res(*this);
101     res.coeff *= R;
102     return res;
103 }
104
105 MultivariateMonomial & MultivariateMonomial::operator*=(const int64_t R)
106 {
107     coeff *= R;
108     return *this;
109 }
110
111 MultivariateMonomial MultivariateMonomial::operator/(const int64_t R) const
112 {
113     MultivariateMonomial res(*this);
114     res.coeff /= R;
115     return res;
116 }
117
118 MultivariateMonomial & MultivariateMonomial::operator/=(const int64_t R)
119 {
120     coeff /= R;
121     return *this;
122 }
123
124 MultivariateMonomial MultivariateMonomial::operator^(unsigned int R) const
125 {
126     MultivariateMonomial res(*this);
127     if (R > 1)
128     {
129         coeff = std::pow(coeff, R);
130         for (auto & ve : res.monomial)
131         {
132             ve.exp *= R;
133         }
134     }
135     return res;
136 }
137
138 bool MultivariateMonomial::operator==(const MultivariateMonomial & R) const
139 {
140     return coeff == R.coeff && monomial == R.monomial;
141 }
142
143 const std::string MultivariateMonomial::print(const std::map<uint64_t, std::string> & vars) const
144 {
145     std::ostringstream os;
146     if (coeff == -1 || coeff == 1)
147     {
148         if (coeff == -1)
149         {
150             os << L'-';
151         }
152         if (!monomial.empty())
153         {
154             os << monomial.begin()->print(vars);
155             for (auto i = std::next(monomial.begin()), e = monomial.end(); i != e; ++i)
156             {
157                 os << "*" << i->print(vars);
158             }
159         }
160     }
161     else
162     {
163         os << coeff;
164         for (const auto & ve : monomial)
165         {
166             os << "*" << ve.print(vars);
167         }
168     }
169     return os.str();
170 }
171
172 std::ostream & operator<<(std::ostream & out, const MultivariateMonomial & m)
173 {
174     const std::map<uint64_t, std::string> vars;
175     out << m.print(vars);
176
177     return out;
178 }
179
180 bool MultivariateMonomial::Compare::operator()(const MultivariateMonomial & L, const MultivariateMonomial & R) const
181 {
182     const unsigned int le = L.exponent();
183     const unsigned int re = R.exponent();
184     if (le < re)
185     {
186         return true;
187     }
188     else if (le == re)
189     {
190         const unsigned int ls = static_cast<unsigned int>(L.monomial.size());
191         const unsigned int rs = static_cast<unsigned int>(R.monomial.size());
192         if (ls > rs)
193         {
194             return true;
195         }
196         else if (ls == rs)
197         {
198             for (Monomial::const_iterator i = L.monomial.begin(), j = R.monomial.begin(), e = L.monomial.end(); i != e; ++i, ++j)
199             {
200                 if (VarExp::Compare()(*i, *j))
201                 {
202                     return true;
203                 }
204                 else if (!VarExp::Eq()(*i, *j))
205                 {
206                     return false;
207                 }
208             }
209
210             for (Monomial::const_iterator i = L.monomial.begin(), j = R.monomial.begin(), e = L.monomial.end(); i != e; ++i, ++j)
211             {
212                 if (i->exp < j->exp)
213                 {
214                     return true;
215                 }
216                 else if (i->exp > j->exp)
217                 {
218                     return false;
219                 }
220             }
221
222         }
223     }
224     return false;
225 }
226
227 } // namespace analysis