* Bug 16463 fixed: now matrix(sparse([]),[0 0]) is empty sparse
[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         out.push_back(pGTIn->clone());
66         return types::Function::OK;
67     }
68
69     pGTOut = pGTIn->clone()->getAs<types::GenericType>();
70
71     if (in.size() == 2)
72     {
73         if (in[1]->isDouble() == false)
74         {
75             Scierror(999, _("%s: Wrong type for input argument #%d : A real matrix expected.\n"), "matrix", 2);
76             pGTOut->killMe();
77             return types::Function::Error;
78         }
79
80         types::Double* pDblNewSize = in[1]->getAs<types::Double>();
81
82         if (pDblNewSize->isComplex())
83         {
84             Scierror(999, _("%s: Wrong type for input argument #%d : A real matrix expected.\n"), "matrix", 2);
85             pGTOut->killMe();
86             return types::Function::Error;
87         }
88
89         iDims = pDblNewSize->getSize();
90         piSizes = new int[iDims];
91
92         for (int i = 0; i < iDims; i++)
93         {
94             piSizes[i] = static_cast<int>(pDblNewSize->get(i));
95             if (piSizes[i] == -1)
96             {
97                 if (iLeastOne == -1)
98                 {
99                     iLeastOne = i;
100                 }
101                 else
102                 {
103                     Scierror(999, _("%s: Wrong value for input argument #%d : Only one value can be equal to %d.\n"), "matrix", 2, -1);
104                     pGTOut->killMe();
105                     delete[] piSizes;
106                     return types::Function::Error;
107                 }
108             }
109             else if (piSizes[i] < -1)
110             {
111                 Scierror(999, _("%s: Wrong value for input argument #%d : At most %d expected.\n"), "matrix", 2, -1);
112                 pGTOut->killMe();
113                 delete[] piSizes;
114                 return types::Function::Error;
115             }
116             else
117             {
118                 newSize *= piSizes[i];
119             }
120         }
121     }
122     else
123     {
124         iDims = static_cast<int>(in.size()) - 1;
125         piSizes = new int[iDims];
126         for (int i = 1; i < static_cast<int>(in.size()); i++)
127         {
128             if (in[i]->isDouble() == false)
129             {
130                 Scierror(999, _("%s: Wrong type for input argument #%d : A real scalar expected.\n"), "matrix", i + 1);
131                 pGTOut->killMe();
132                 delete[] piSizes;
133                 return types::Function::Error;
134             }
135
136             types::Double* pDblNewSize = in[i]->getAs<types::Double>();
137
138             if (pDblNewSize->isComplex() || pDblNewSize->isScalar() == false)
139             {
140                 Scierror(999, _("%s: Wrong type for input argument #%d : A real scalar expected.\n"), "matrix", i + 1);
141                 pGTOut->killMe();
142                 delete[] piSizes;
143                 return types::Function::Error;
144             }
145
146             piSizes[i - 1] = static_cast<int>(pDblNewSize->get(0));
147             if (piSizes[i - 1] == -1)
148             {
149                 if (iLeastOne == -1)
150                 {
151                     iLeastOne = i - 1;
152                 }
153                 else
154                 {
155                     Scierror(999, _("%s: Wrong value for input argument #%d : Only one value can be equal to %d.\n"), "matrix", i + 1, -1);
156                     pGTOut->killMe();
157                     delete[] piSizes;
158                     return types::Function::Error;
159                 }
160             }
161             else if (piSizes[i - 1] < -1)
162             {
163                 Scierror(999, _("%s: Wrong value for input argument #%d : At most %d expected.\n"), "matrix", i + 1, -1);
164                 pGTOut->killMe();
165                 delete[] piSizes;
166                 return types::Function::Error;
167             }
168             else
169             {
170                 newSize *= piSizes[i - 1];
171             }
172         }
173     }
174
175     if (iLeastOne != -1)
176     {
177         piSizes[iLeastOne] = (int)pGTOut->getSize() / newSize;
178     }
179
180     if (pGTOut->isSparse() && iDims > 2)
181     {
182         Scierror(999, _("%s: Wrong value for input argument(s) : Sparse matrix cannot be reshaped beyond %d dimensions.\n"), "matrix", 2);
183         pGTOut->killMe();
184         delete[] piSizes;
185         return types::Function::Error;
186     }
187
188     bOk = pGTOut->reshape(piSizes, iDims);
189     delete[] piSizes;
190
191     if (bOk == false)
192     {
193         Scierror(999, _("%s: Input and output matrices must have the same number of elements.\n"), "matrix");
194         pGTOut->killMe();
195         return types::Function::Error;
196     }
197
198     out.push_back(pGTOut);
199     return types::Function::OK;
200 }
201 /*--------------------------------------------------------------------------*/