Analysis: try to restore it !
[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         wos << coeff;
144         for (const auto & ve : monomial)
145         {
146             wos << L"*" << ve.print(vars);
147         }
148         return wos.str();
149     }
150
151     std::wostream & operator<<(std::wostream & out, const MultivariateMonomial & m)
152     {
153         out << m.coeff;
154         for (const auto & ve : m.monomial)
155         {
156             out << L"*" << ve;
157         }
158         return out;
159     }
160
161     bool MultivariateMonomial::Compare::operator()(const MultivariateMonomial & L, const MultivariateMonomial & R) const
162     {
163             const unsigned int le = L.exponent();
164             const unsigned int re = R.exponent();
165             if (le < re)
166             {
167                 return true;
168             }
169             else if (le == re)
170             {
171                 const unsigned int ls = static_cast<unsigned int>(L.monomial.size());
172                 const unsigned int rs = static_cast<unsigned int>(R.monomial.size());
173                 if (ls > rs)
174                 {
175                     return true;
176                 }
177                 else if (ls == rs)
178                 {
179                     for (Monomial::const_iterator i = L.monomial.begin(), j = R.monomial.begin(), e = L.monomial.end(); i != e; ++i, ++j)
180                     {
181                         if (VarExp::Compare()(*i, *j))
182                         {
183                             return true;
184                         }
185                         else if (!VarExp::Eq()(*i, *j))
186                         {
187                             return false;
188                         }
189                     }
190
191                     for (Monomial::const_iterator i = L.monomial.begin(), j = R.monomial.begin(), e = L.monomial.end(); i != e; ++i, ++j)
192                     {
193                         if (i->exp < j->exp)
194                         {
195                             return true;
196                         }
197                         else if (i->exp > j->exp)
198                         {
199                             return false;
200                         }
201                     }
202
203                 }
204             }
205             return false;
206         }
207
208 } // namespace analysis