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 
contains(const uint64_t var) const24 bool MultivariateMonomial::contains(const uint64_t var) const
25 {
26     return monomial.find(var) != monomial.end();
27 }
28 
checkVariable(const uint64_t max) const29 bool MultivariateMonomial::checkVariable(const uint64_t max) const
30 {
31     return std::prev(monomial.end())->var <= max;
32 }
33 
exponent() const34 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 
add(const VarExp & ve)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 
add(VarExp && ve)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 
operator *(const MultivariateMonomial & R) const72 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 
operator *=(const MultivariateMonomial & R)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 
operator *(const int64_t L,const MultivariateMonomial & R)93 MultivariateMonomial operator*(const int64_t L, const MultivariateMonomial & R)
94 {
95     return R * L;
96 }
97 
operator *(const int64_t R) const98 MultivariateMonomial MultivariateMonomial::operator*(const int64_t R) const
99 {
100     MultivariateMonomial res(*this);
101     res.coeff *= R;
102     return res;
103 }
104 
operator *=(const int64_t R)105 MultivariateMonomial & MultivariateMonomial::operator*=(const int64_t R)
106 {
107     coeff *= R;
108     return *this;
109 }
110 
operator /(const int64_t R) const111 MultivariateMonomial MultivariateMonomial::operator/(const int64_t R) const
112 {
113     MultivariateMonomial res(*this);
114     res.coeff /= R;
115     return res;
116 }
117 
operator /=(const int64_t R)118 MultivariateMonomial & MultivariateMonomial::operator/=(const int64_t R)
119 {
120     coeff /= R;
121     return *this;
122 }
123 
operator ^(unsigned int R) const124 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 
operator ==(const MultivariateMonomial & R) const138 bool MultivariateMonomial::operator==(const MultivariateMonomial & R) const
139 {
140     return coeff == R.coeff && monomial == R.monomial;
141 }
142 
print(const std::map<uint64_t,std::wstring> & vars) const143 const std::wstring MultivariateMonomial::print(const std::map<uint64_t, std::wstring> & vars) const
144 {
145     std::wostringstream wos;
146     if (coeff == -1 || coeff == 1)
147     {
148         if (coeff == -1)
149         {
150             wos << L'-';
151         }
152         if (!monomial.empty())
153         {
154             wos << monomial.begin()->print(vars);
155             for (auto i = std::next(monomial.begin()), e = monomial.end(); i != e; ++i)
156             {
157                 wos << L"*" << i->print(vars);
158             }
159         }
160     }
161     else
162     {
163         wos << coeff;
164         for (const auto & ve : monomial)
165         {
166             wos << L"*" << ve.print(vars);
167         }
168     }
169     return wos.str();
170 }
171 
operator <<(std::wostream & out,const MultivariateMonomial & m)172 std::wostream & operator<<(std::wostream & out, const MultivariateMonomial & m)
173 {
174     const std::map<uint64_t, std::wstring> vars;
175     out << m.print(vars);
176 
177     return out;
178 }
179 
operator ()(const MultivariateMonomial & L,const MultivariateMonomial & R) const180 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
228