13163b5a0420985114e90f3620c7de7907476060
[scilab.git] / scilab / modules / ast / includes / run_MatrixExp.hxx
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2008-2008 - DIGITEO - Antoine ELIAS
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 // This code is separated in run_MatrixExp.hxx
14 // but will be inlined in runvisitor.hxx
15 // using #include with RunVisitorT class declaration.
16 //
17 // If you need additionnal headers, please add it in runvisitor.hxx
18
19 /*
20   [1,2;3,4] with/without special character $ and :
21 */
22 void visitprivate(const MatrixExp &e)
23 {
24     try
25     {
26         std::list<MatrixLineExp *>::const_iterator row;
27         std::list<Exp *>::const_iterator col;
28         InternalType *poResult = NULL;
29         list<InternalType*> rowList;
30         int iRows = 0;
31         int iCols = 0;
32
33         if (e.lines_get().size() == 0)
34         {
35             result_set(Double::Empty());
36             return;
37         }
38
39         //do all [x,x]
40         for (row = e.lines_get().begin() ; row != e.lines_get().end() ; row++)
41         {
42             InternalType* poRow = NULL;
43             for (col = (*row)->columns_get().begin() ; col != (*row)->columns_get().end() ; col++)
44             {
45                 int iCurCol = 0;
46                 //poResult = [poResult, col]
47
48                 (*col)->accept(*this);
49
50                 InternalType *pIT = result_get();
51                 if (pIT == NULL)
52                 {
53                     continue;
54                 }
55
56                 //reset result but whitout delete the value
57                 result_set(NULL);
58
59                 if (pIT->isGenericType() == false)
60                 {
61                     std::wostringstream os;
62                     os << _W("unable to concatenate\n");
63                     throw ScilabError(os.str(), 999, (*col)->location_get());
64                 }
65
66                 GenericType* pGT = pIT->getAs<GenericType>();
67
68                 if (pGT->isImplicitList() && pGT->getAs<ImplicitList>()->isComputable())
69                 {
70                     ImplicitList *pIL = pGT->getAs<ImplicitList>();
71                     InternalType* pIT2 = pIL->extractFullMatrix();
72                     if (pGT->isDeletable())
73                     {
74                         delete pGT;
75                     }
76                     pGT = pIT2->getAs<GenericType>();
77                 }
78
79                 if (pGT->isDouble() && pGT->getAs<Double>()->isEmpty())
80                 {
81                     continue;
82                 }
83
84                 if (poRow == NULL)
85                 {
86                     //first loop
87                     poRow = pGT;
88                     continue;
89                 }
90
91                 GenericType* pGTResult = poRow->getAs<GenericType>();
92                 //check dimension
93                 if (pGT->getDims() != 2 || pGT->getRows() != pGTResult->getRows())
94                 {
95                     std::wostringstream os;
96                     os << _W("inconsistent row/column dimensions\n");
97                     throw ScilabError(os.str(), 999, (*row)->location_get());
98                 }
99
100                 // if we concatenate [Double Sparse], transform the Double to Sparse and perform [Sparse Sparse]
101                 // this avoids to allocate a Double result of size of Double+Sparse and initialize all elements.
102                 if (pGT->isSparse() && pGTResult->isDouble())
103                 {
104                     poRow = new types::Sparse(*pGTResult->getAs<types::Double>());
105                 }
106                 else if (pGT->isSparseBool() && pGTResult->isBool()) // [Bool SparseBool] => [SparseBool SparseBool]
107                 {
108                     poRow = new types::SparseBool(*pGTResult->getAs<types::Bool>());
109                 }
110
111                 InternalType *p = AddElementToVariable(NULL, poRow, pGTResult->getRows(), pGTResult->getCols() + pGT->getCols());
112                 p = AddElementToVariable(p, pGT, 0, pGTResult->getCols());
113                 if (poRow->isDeletable())
114                 {
115                     delete poRow;
116                 }
117
118                 if (pGT->isDeletable())
119                 {
120                     delete pGT;
121                 }
122                 poRow = p;
123             }
124
125             if (poRow == NULL)
126             {
127                 continue;
128             }
129
130             GenericType* pGT = poRow->getAs<GenericType>();
131             if (poResult == NULL)
132             {
133                 poResult = pGT;
134                 continue;
135             }
136
137             //check dimension
138             GenericType* pGTResult = poResult->getAs<GenericType>();
139             //check dimension
140             if (pGT->getCols() != pGTResult->getCols())
141             {
142                 std::wostringstream os;
143                 os << _W("inconsistent row/column dimensions\n");
144                 throw ScilabError(os.str(), 999, (*e.lines_get().begin())->location_get());
145             }
146
147             // if we concatenate [Double Sparse], transform the Double to Sparse and perform [Sparse Sparse]
148             // this avoids to allocate a Double result of size of Double+Sparse and initialize all elements.
149             if (pGT->isSparse() && pGTResult->isDouble())
150             {
151                 poResult = new types::Sparse(*pGTResult->getAs<types::Double>());
152             }
153             else if (pGT->isSparseBool() && pGTResult->isBool()) // [Bool SparseBool] => [SparseBool SparseBool]
154             {
155                 poResult = new types::SparseBool(*pGTResult->getAs<types::Bool>());
156             }
157
158             InternalType *p = AddElementToVariable(NULL, poResult, pGTResult->getRows() + pGT->getRows(), pGT->getCols());
159             p = AddElementToVariable(p, pGT, pGTResult->getRows(), 0);
160             if (poResult->isDeletable())
161             {
162                 delete poResult;
163             }
164
165             if (pGT->isDeletable())
166             {
167                 delete pGT;
168             }
169
170             poResult = p;
171         }
172
173         if (poResult)
174         {
175             result_set(poResult);
176         }
177         else
178         {
179             result_set(Double::Empty());
180         }
181     }
182     catch (ScilabError error)
183     {
184         throw error;
185     }
186 }