Analysis: replace constant in Result by a C++ union
[scilab.git] / scilab / modules / ast / src / cpp / analysis / MatrixAnalyzer.cpp
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2014 - 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 "AnalysisVisitor.hxx"
14 #include "calls/MatrixAnalyzer.hxx"
15 #include "tools.hxx"
16
17 namespace analysis
18 {
19 bool MatrixAnalyzer::analyze(AnalysisVisitor & visitor, const unsigned int lhs, ast::CallExp & e)
20 {
21     if (lhs > 1)
22     {
23         return false;
24     }
25
26     const ast::exps_t args = e.getArgs();
27     if (args.size() != 3)
28     {
29         return false;
30     }
31
32     ast::Exp * first = *args.begin();
33     ast::Exp * second = *std::next(args.begin());
34     ast::Exp * third = *std::next(std::next(args.begin()));
35
36     first->accept(visitor);
37     Result R1 = visitor.getResult();
38     if (!R1.getType().ismatrix())
39     {
40         return false;
41     }
42
43     second->accept(visitor);
44     Result R2 = visitor.getResult();
45     third->accept(visitor);
46     Result & R3 = visitor.getResult();
47
48     double val;
49     SymbolicDimension rows;
50     SymbolicDimension cols;
51
52     if (R2.getConstant().getDblValue(val))
53     {
54         const int nrows = tools::cast<int>(val);
55         if (nrows <= 0)
56         {
57             return false;
58         }
59         else
60         {
61             rows = SymbolicDimension(visitor.getGVN(), nrows);
62         }
63     }
64     else if (GVN::Value * gvnValue = R2.getConstant().getGVNValue())
65     {
66         if (gvnValue->poly->isConstant() && gvnValue->poly->constant <= 0)
67         {
68             return false;
69         }
70         rows.setValue(gvnValue);
71         rows.setGVN(&visitor.getGVN());
72     }
73     else
74     {
75         return false;
76     }
77
78     if (R3.getConstant().getDblValue(val))
79     {
80         const int ncols = tools::cast<int>(val);
81         if (ncols <= 0)
82         {
83             return false;
84         }
85         else
86         {
87             cols = SymbolicDimension(visitor.getGVN(), ncols);
88         }
89     }
90     else if (GVN::Value * gvnValue = R3.getConstant().getGVNValue())
91     {
92         if (gvnValue->poly->isConstant() && gvnValue->poly->constant <= 0)
93         {
94             return false;
95         }
96         cols.setValue(gvnValue);
97         cols.setGVN(&visitor.getGVN());
98     }
99     else
100     {
101         return false;
102     }
103
104     const TIType & type = R1.getType();
105     SymbolicDimension prod1 = type.rows * type.cols;
106     SymbolicDimension prod2 = rows * cols;
107     bool res = visitor.getCM().check(ConstraintManager::EQUAL, prod1.getValue(), prod2.getValue());
108     if (res)
109     {
110         res = visitor.getCM().check(ConstraintManager::POSITIVE, rows.getValue());
111         if (!res)
112         {
113             return false;
114         }
115     }
116     else
117     {
118         return false;
119     }
120
121     TIType resT(visitor.getGVN(), R1.getType().type, rows, cols);
122     Result & _res = e.getDecorator().setResult(Result(resT, visitor.getTemp().add(resT)));
123     visitor.setResult(_res);
124     return true;
125 }
126 }