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