52d51c375b416867f91e6fdad1da974bb389b59e
[scilab.git] / scilab / modules / elementary_functions / sci_gateway / cpp / sci_matrix.cpp
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2011 - DIGITEO - Antoine ELIAS
4  * Copyright (C) 2012 - DIGITEO - Cedric DELAMARRE
5  *
6  * Copyright (C) 2012 - 2016 - Scilab Enterprises
7  *
8  * This file is hereby licensed under the terms of the GNU GPL v2.0,
9  * pursuant to article 5.3.4 of the CeCILL v.2.1.
10  * This file was originally licensed under the terms of the CeCILL v2.1,
11  * and continues to be available under such terms.
12  * For more information, see the COPYING file which you should have received
13  * along with this program.
14  *
15  */
16 /*--------------------------------------------------------------------------*/
17 #include "elem_func_gw.hxx"
18 #include "function.hxx"
19 #include "double.hxx"
20 #include "string.hxx"
21 #include "struct.hxx"
22 #include "cell.hxx"
23 #include "overload.hxx"
24
25 extern "C"
26 {
27 #include "Scierror.h"
28 #include "localization.h"
29 }
30
31 /*--------------------------------------------------------------------------*/
32 types::Function::ReturnValue sci_matrix(types::typed_list &in, int _iRetCount, types::typed_list &out)
33 {
34     types::GenericType* pGTIn  = NULL;
35     types::GenericType* pGTOut = NULL;
36     int* piSizes    = NULL;
37     int iDims       = 0;
38     int iLeastOne   = -1;
39     int newSize     = 1;
40     bool bOk        = false;
41
42     if (in.size() < 2 )
43     {
44         Scierror(77, _("%s: Wrong number of input argument(s): At least %d expected.\n"), "matrix", 2);
45         return types::Function::Error;
46     }
47
48     if (_iRetCount > 1)
49     {
50         Scierror(78, _("%s: Wrong number of output argument(s): %d expected.\n"), "matrix", 1);
51         return types::Function::Error;
52     }
53
54     if (in[0]->isArrayOf()      == false &&
55             in[0]->isSparse()       == false &&
56             in[0]->isSparseBool()   == false)
57     {
58         std::wstring wstFuncName = L"%" + in[0]->getShortTypeStr() + L"_matrix";
59         return Overload::call(wstFuncName, in, _iRetCount, out);
60     }
61
62     pGTIn = in[0]->getAs<types::GenericType>();
63     if (pGTIn->getSize() == 0)
64     {
65         if (pGTIn->isStruct())
66         {
67             out.push_back(new types::Struct());
68         }
69         else if (pGTIn->isCell())
70         {
71             out.push_back(new types::Cell());
72         }
73         else
74         {
75             out.push_back(types::Double::Empty());
76         }
77
78         return types::Function::OK;
79     }
80
81     pGTOut = pGTIn->clone()->getAs<types::GenericType>();
82
83     if (in.size() == 2)
84     {
85         if (in[1]->isDouble() == false)
86         {
87             Scierror(999, _("%s: Wrong type for input argument #%d : A real matrix expected.\n"), "matrix", 2);
88             pGTOut->killMe();
89             return types::Function::Error;
90         }
91
92         types::Double* pDblNewSize = in[1]->getAs<types::Double>();
93
94         if (pDblNewSize->isComplex())
95         {
96             Scierror(999, _("%s: Wrong type for input argument #%d : A real matrix expected.\n"), "matrix", 2);
97             pGTOut->killMe();
98             return types::Function::Error;
99         }
100
101         iDims = pDblNewSize->getSize();
102         piSizes = new int[iDims];
103
104         for (int i = 0; i < iDims; i++)
105         {
106             piSizes[i] = static_cast<int>(pDblNewSize->get(i));
107             if (piSizes[i] == -1)
108             {
109                 if (iLeastOne == -1)
110                 {
111                     iLeastOne = i;
112                 }
113                 else
114                 {
115                     Scierror(999, _("%s: Wrong value for input argument #%d : Only one value can be equal to %d.\n"), "matrix", 2, -1);
116                     pGTOut->killMe();
117                     delete[] piSizes;
118                     return types::Function::Error;
119                 }
120             }
121             else if (piSizes[i] < -1)
122             {
123                 Scierror(999, _("%s: Wrong value for input argument #%d : At most %d expected.\n"), "matrix", 2, -1);
124                 pGTOut->killMe();
125                 delete[] piSizes;
126                 return types::Function::Error;
127             }
128             else
129             {
130                 newSize *= piSizes[i];
131             }
132         }
133     }
134     else
135     {
136         iDims = static_cast<int>(in.size()) - 1;
137         piSizes = new int[iDims];
138         for (int i = 1; i < static_cast<int>(in.size()); i++)
139         {
140             if (in[i]->isDouble() == false)
141             {
142                 Scierror(999, _("%s: Wrong type for input argument #%d : A real scalar expected.\n"), "matrix", i + 1);
143                 pGTOut->killMe();
144                 delete[] piSizes;
145                 return types::Function::Error;
146             }
147
148             types::Double* pDblNewSize = in[i]->getAs<types::Double>();
149
150             if (pDblNewSize->isComplex() || pDblNewSize->isScalar() == false)
151             {
152                 Scierror(999, _("%s: Wrong type for input argument #%d : A real scalar expected.\n"), "matrix", i + 1);
153                 pGTOut->killMe();
154                 delete[] piSizes;
155                 return types::Function::Error;
156             }
157
158             piSizes[i - 1] = static_cast<int>(pDblNewSize->get(0));
159             if (piSizes[i - 1] == -1)
160             {
161                 if (iLeastOne == -1)
162                 {
163                     iLeastOne = i - 1;
164                 }
165                 else
166                 {
167                     Scierror(999, _("%s: Wrong value for input argument #%d : Only one value can be equal to %d.\n"), "matrix", i + 1, -1);
168                     pGTOut->killMe();
169                     delete[] piSizes;
170                     return types::Function::Error;
171                 }
172             }
173             else if (piSizes[i - 1] < -1)
174             {
175                 Scierror(999, _("%s: Wrong value for input argument #%d : At most %d expected.\n"), "matrix", i + 1, -1);
176                 pGTOut->killMe();
177                 delete[] piSizes;
178                 return types::Function::Error;
179             }
180             else
181             {
182                 newSize *= piSizes[i - 1];
183             }
184         }
185     }
186
187     if (iLeastOne != -1)
188     {
189         piSizes[iLeastOne] = (int)pGTOut->getSize() / newSize;
190     }
191
192     if (pGTOut->isSparse() && iDims > 2)
193     {
194         Scierror(999, _("%s: Wrong value for input argument(s) : Sparse matrix cannot be reshaped beyond %d dimensions.\n"), "matrix", 2);
195         pGTOut->killMe();
196         delete[] piSizes;
197         return types::Function::Error;
198     }
199
200     bOk = pGTOut->reshape(piSizes, iDims);
201     delete[] piSizes;
202
203     if (bOk == false)
204     {
205         Scierror(999, _("%s: Input and output matrices must have the same number of elements.\n"), "matrix");
206         pGTOut->killMe();
207         return types::Function::Error;
208     }
209
210     out.push_back(pGTOut);
211     return types::Function::OK;
212 }
213 /*--------------------------------------------------------------------------*/