GPL + CeCILL Header change
[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  * === LICENSE_END ===
14  *
15  */
16
17 #include <cmath>
18 #include <functional>
19
20 #include "gvn/MultivariateMonomial.hxx"
21
22 namespace analysis
23 {
24
25 bool MultivariateMonomial::contains(const uint64_t var) const
26 {
27     return monomial.find(var) != monomial.end();
28 }
29
30 bool MultivariateMonomial::checkVariable(const uint64_t max) const
31 {
32     return std::prev(monomial.end())->var <= max;
33 }
34
35 unsigned int MultivariateMonomial::exponent() const
36 {
37     unsigned int exp = 0;
38     for (const auto & ve : monomial)
39     {
40         exp += ve.exp;
41     }
42     return exp;
43 }
44
45 MultivariateMonomial & MultivariateMonomial::add(const VarExp & ve)
46 {
47     Monomial::iterator i = monomial.find(ve);
48     if (i == monomial.end())
49     {
50         monomial.insert(ve);
51     }
52     else
53     {
54         i->exp += ve.exp;
55     }
56     return *this;
57 }
58
59 MultivariateMonomial & MultivariateMonomial::add(VarExp && ve)
60 {
61     Monomial::iterator i = monomial.find(ve);
62     if (i == monomial.end())
63     {
64         monomial.emplace(std::move(ve));
65     }
66     else
67     {
68         i->exp += ve.exp;
69     }
70     return *this;
71 }
72
73 MultivariateMonomial MultivariateMonomial::operator*(const MultivariateMonomial & R) const
74 {
75     MultivariateMonomial res(*this);
76     res.coeff *= R.coeff;
77     for (const auto & ve : R.monomial)
78     {
79         res.add(ve);
80     }
81     return res;
82 }
83
84 MultivariateMonomial & MultivariateMonomial::operator*=(const MultivariateMonomial & R)
85 {
86     coeff *= R.coeff;
87     for (const auto & ve : R.monomial)
88     {
89         add(ve);
90     }
91     return *this;
92 }
93
94 MultivariateMonomial operator*(const int64_t L, const MultivariateMonomial & R)
95 {
96     return R * L;
97 }
98
99 MultivariateMonomial MultivariateMonomial::operator*(const int64_t R) const
100 {
101     MultivariateMonomial res(*this);
102     res.coeff *= R;
103     return res;
104 }
105
106 MultivariateMonomial & MultivariateMonomial::operator*=(const int64_t R)
107 {
108     coeff *= R;
109     return *this;
110 }
111
112 MultivariateMonomial MultivariateMonomial::operator/(const int64_t R) const
113 {
114     MultivariateMonomial res(*this);
115     res.coeff /= R;
116     return res;
117 }
118
119 MultivariateMonomial & MultivariateMonomial::operator/=(const int64_t R)
120 {
121     coeff /= R;
122     return *this;
123 }
124
125 MultivariateMonomial MultivariateMonomial::operator^(unsigned int R) const
126 {
127     MultivariateMonomial res(*this);
128     if (R > 1)
129     {
130         coeff = std::pow(coeff, R);
131         for (auto & ve : res.monomial)
132         {
133             ve.exp *= R;
134         }
135     }
136     return res;
137 }
138
139 bool MultivariateMonomial::operator==(const MultivariateMonomial & R) const
140 {
141     return coeff == R.coeff && monomial == R.monomial;
142 }
143
144 const std::wstring MultivariateMonomial::print(const std::map<uint64_t, std::wstring> & vars) const
145 {
146     std::wostringstream wos;
147     if (coeff == -1 || coeff == 1)
148     {
149         if (coeff == -1)
150         {
151             wos << L'-';
152         }
153         if (!monomial.empty())
154         {
155             wos << monomial.begin()->print(vars);
156             for (auto i = std::next(monomial.begin()), e = monomial.end(); i != e; ++i)
157             {
158                 wos << L"*" << i->print(vars);
159             }
160         }
161     }
162     else
163     {
164         wos << coeff;
165         for (const auto & ve : monomial)
166         {
167             wos << L"*" << ve.print(vars);
168         }
169     }
170     return wos.str();
171 }
172
173 std::wostream & operator<<(std::wostream & out, const MultivariateMonomial & m)
174 {
175     const std::map<uint64_t, std::wstring> vars;
176     out << m.print(vars);
177
178     return out;
179 }
180
181 bool MultivariateMonomial::Compare::operator()(const MultivariateMonomial & L, const MultivariateMonomial & R) const
182 {
183     const unsigned int le = L.exponent();
184     const unsigned int re = R.exponent();
185     if (le < re)
186     {
187         return true;
188     }
189     else if (le == re)
190     {
191         const unsigned int ls = static_cast<unsigned int>(L.monomial.size());
192         const unsigned int rs = static_cast<unsigned int>(R.monomial.size());
193         if (ls > rs)
194         {
195             return true;
196         }
197         else if (ls == rs)
198         {
199             for (Monomial::const_iterator i = L.monomial.begin(), j = R.monomial.begin(), e = L.monomial.end(); i != e; ++i, ++j)
200             {
201                 if (VarExp::Compare()(*i, *j))
202                 {
203                     return true;
204                 }
205                 else if (!VarExp::Eq()(*i, *j))
206                 {
207                     return false;
208                 }
209             }
210
211             for (Monomial::const_iterator i = L.monomial.begin(), j = R.monomial.begin(), e = L.monomial.end(); i != e; ++i, ++j)
212             {
213                 if (i->exp < j->exp)
214                 {
215                     return true;
216                 }
217                 else if (i->exp > j->exp)
218                 {
219                     return false;
220                 }
221             }
222
223         }
224     }
225     return false;
226 }
227
228 } // namespace analysis