Merge remote-tracking branch 'origin/master' into windows
[scilab.git] / scilab / modules / ast / src / cpp / analysis / SymbolicList.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  *
14  */
15
16 #include "AnalysisVisitor.hxx"
17 #include "gvn/SymbolicList.hxx"
18 #include "ForList.hxx"
19 #include "tools.hxx"
20
21 namespace analysis
22 {
23
24 bool SymbolicList::getType(GVN & gvn, TIType & type) const
25 {
26     double dstart, dstep, dend;
27     bool known = false;
28     if (symbolic)
29     {
30         const MultivariatePolynomial & mpStart = *start.gvnVal->poly;
31         const MultivariatePolynomial & mpStep = *step.gvnVal->poly;
32         const MultivariatePolynomial & mpEnd = *end.gvnVal->poly;
33         if (mpStart.isConstant() && mpStep.isConstant() && mpEnd.isConstant())
34         {
35             dstart = mpStart.constant;
36             dstep = mpStep.constant;
37             dend = mpEnd.constant;
38             known = true;
39         }
40     }
41     else
42     {
43         dstart = start.dval;
44         dstep = step.dval;
45         dend = end.dval;
46         known = true;
47     }
48
49     if (known)
50     {
51         double out;
52         int _type = ForList64::checkList(dstart, dend, dstep, out);
53
54         switch (_type)
55         {
56             case 0:
57                 type = TIType(gvn, TIType::EMPTY);
58                 return true;
59             case 1:
60                 type = TIType(gvn, TIType::DOUBLE);
61                 return true;
62             case 2:
63             {
64                 const uint64_t N = ForList64::size(dstart, dend, dstep);
65                 type = TIType(gvn, TIType::DOUBLE, 1, N);
66                 return true;
67             }
68             default:
69                 return false;
70         }
71     }
72
73     GVN::Value * gvnStart = start.gvnVal, * gvnStep = step.gvnVal, * gvnEnd = end.gvnVal;
74     if (!gvnStep->poly->isConstant())
75     {
76         return false;
77     }
78
79     dstep = gvnStep->poly->constant;
80     if (dstep == 0)
81     {
82         type = TIType(gvn, TIType::EMPTY);
83         return true;
84     }
85
86     if (dstep != -1 && dstep != 1)
87     {
88         // TODO : we must be able to handle general step (even if -1 or 1 seem to be the most frequent values)
89         // but it implies that we need a symbolic division on polynomials.
90         return false;
91     }
92
93     GVN::Value * ONEValue = gvn.getValue(1.);
94     SymbolicDimension ONE(gvn, ONEValue);
95
96     if (gvnStart->value == gvnEnd->value)
97     {
98         type = TIType(gvn, TIType::DOUBLE, ONE, ONE);
99         return true;
100     }
101
102     GVN::Value * v;
103     if (dstep == 1)
104     {
105         v = gvn.getValue(OpValue::Kind::MINUS, *gvnEnd, *gvnStart);
106     }
107     else
108     {
109         v = gvn.getValue(OpValue::Kind::MINUS, *gvnStart, *gvnEnd);
110     }
111     v = gvn.getValue(OpValue::Kind::PLUS, *v, *ONEValue);
112     if (v->poly->constant < 0 && v->poly->isCoeffNegative(false))
113     {
114         type = TIType(gvn, TIType::EMPTY);
115         return true;
116     }
117
118     type = TIType(gvn, TIType::DOUBLE, ONE, SymbolicDimension(gvn, v));
119     return true;
120 }
121
122 bool SymbolicList::get(AnalysisVisitor & visitor, ast::ListExp & le, SymbolicList & sl)
123 {
124     le.getStart().accept(visitor);
125     Result Rstart = visitor.getResult();
126     le.getEnd().accept(visitor);
127     Result Rend = visitor.getResult();
128     le.getStep().accept(visitor);
129     Result & Rstep = visitor.getResult();
130
131     double start, step, end;
132     if (Rstart.getConstant().getDblValue(start) && Rstep.getConstant().getDblValue(step) && Rend.getConstant().getDblValue(end))
133     {
134         if (tools::isAnInt(start) && tools::isAnInt(step) && tools::isAnInt(end))
135         {
136             sl = SymbolicList(start, step, end);
137             return true;
138         }
139         return false;
140     }
141
142     GVN::Value * gvnStart, * gvnStep, * gvnEnd;
143     if (Rstart.getConstant().getDblValue(start))
144     {
145         int64_t _start;
146         if (tools::asInteger(start, _start))
147         {
148             gvnStart = visitor.getGVN().getValue(_start);
149         }
150         else
151         {
152             return false;
153         }
154     }
155     else if (GVN::Value * v = Rstart.getConstant().getGVNValue())
156     {
157         gvnStart = v;
158     }
159     else
160     {
161         return false;
162     }
163
164     if (Rstep.getConstant().getDblValue(step))
165     {
166         int64_t _step;
167         if (tools::asInteger(step, _step))
168         {
169             gvnStep = visitor.getGVN().getValue(_step);
170         }
171         else
172         {
173             return false;
174         }
175     }
176     else if (GVN::Value * v = Rstep.getConstant().getGVNValue())
177     {
178         gvnStep = v;
179     }
180     else
181     {
182         return false;
183     }
184
185     if (Rend.getConstant().getDblValue(end))
186     {
187         int64_t _end;
188         if (tools::asInteger(end, _end))
189         {
190             gvnEnd = visitor.getGVN().getValue(_end);
191         }
192         else
193         {
194             return false;
195         }
196     }
197     else if (GVN::Value * v = Rend.getConstant().getGVNValue())
198     {
199         gvnEnd = v;
200     }
201     else
202     {
203         return false;
204     }
205
206     sl = SymbolicList(gvnStart, gvnStep, gvnEnd);
207
208     return true;
209 }
210
211 void SymbolicList::evalDollar(GVN & gvn, const GVN::Value * dollarVal)
212 {
213     if (GVN::Value * const dollar = gvn.getExistingValue(symbol::Symbol("$")))
214     {
215         if (GVN::Value * v = evalDollar(gvn, getStart(), dollar, dollarVal))
216         {
217             setStart(v);
218         }
219
220         if (GVN::Value * v = evalDollar(gvn, getStep(), dollar, dollarVal))
221         {
222             setStep(v);
223         }
224
225         if (GVN::Value * v = evalDollar(gvn, getEnd(), dollar, dollarVal))
226         {
227             setEnd(v);
228         }
229     }
230 }
231
232 bool SymbolicList::checkAsIndex(const GVN::Value * dim)
233 {
234     if (symbolic)
235     {
236         if (getStep()->poly->constant > 0 && getStep()->poly->isCoeffPositive(false))
237         {
238             // step is positive
239
240         }
241         else if (getStep()->poly->constant < 0 && getStep()->poly->isCoeffNegative(false))
242         {
243             // step is negative
244
245         }
246         else
247         {
248
249         }
250     }
251     else
252     {
253
254     }
255
256     return true;
257 }
258 }