Analysis: AnalysisVisitor can now be used as a singleton and fix bugs in cache system
[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)
144         {
145             if (!monomial.empty())
146             {
147                 wos << monomial.begin()->print(vars);
148                 for (auto i = std::next(monomial.begin()), e = monomial.end(); i != e; ++i)
149                 {
150                     wos << L"*" << i->print(vars);
151                 }
152             }
153         }
154         else
155         {
156             wos << coeff;
157             for (const auto & ve : monomial)
158             {
159                 wos << L"*" << ve.print(vars);
160             }
161         }
162         return wos.str();
163     }
164
165     std::wostream & operator<<(std::wostream & out, const MultivariateMonomial & m)
166     {
167         if (m.coeff == 1)
168         {
169             if (!m.monomial.empty())
170             {
171                 out << *m.monomial.begin();
172                 for (auto i = std::next(m.monomial.begin()), e = m.monomial.end(); i != e; ++i)
173                 {
174                     out << L"*" << *i;
175                 }
176             }
177         }
178         else
179         {
180             out << m.coeff;
181             for (const auto & ve : m.monomial)
182             {
183                 out << L"*" << ve;
184             }
185         }
186         return out;
187     }
188
189     bool MultivariateMonomial::Compare::operator()(const MultivariateMonomial & L, const MultivariateMonomial & R) const
190     {
191             const unsigned int le = L.exponent();
192             const unsigned int re = R.exponent();
193             if (le < re)
194             {
195                 return true;
196             }
197             else if (le == re)
198             {
199                 const unsigned int ls = static_cast<unsigned int>(L.monomial.size());
200                 const unsigned int rs = static_cast<unsigned int>(R.monomial.size());
201                 if (ls > rs)
202                 {
203                     return true;
204                 }
205                 else if (ls == rs)
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 (VarExp::Compare()(*i, *j))
210                         {
211                             return true;
212                         }
213                         else if (!VarExp::Eq()(*i, *j))
214                         {
215                             return false;
216                         }
217                     }
218
219                     for (Monomial::const_iterator i = L.monomial.begin(), j = R.monomial.begin(), e = L.monomial.end(); i != e; ++i, ++j)
220                     {
221                         if (i->exp < j->exp)
222                         {
223                             return true;
224                         }
225                         else if (i->exp > j->exp)
226                         {
227                             return false;
228                         }
229                     }
230
231                 }
232             }
233             return false;
234         }
235
236 } // namespace analysis