c258913965562e11264fd398651c77d9e9444ffb
[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 "overload.hxx"
22
23 extern "C"
24 {
25 #include "Scierror.h"
26 #include "localization.h"
27 }
28
29 /*--------------------------------------------------------------------------*/
30 types::Function::ReturnValue sci_matrix(types::typed_list &in, int _iRetCount, types::typed_list &out)
31 {
32     types::GenericType* pGTIn  = NULL;
33     types::GenericType* pGTOut = NULL;
34     int* piSizes    = NULL;
35     int iDims       = 0;
36     int iLeastOne   = -1;
37     int newSize     = 1;
38     bool bOk        = false;
39
40     if (in.size() < 2 )
41     {
42         Scierror(77, _("%s: Wrong number of input argument(s): At least %d expected.\n"), "matrix", 2);
43         return types::Function::Error;
44     }
45
46     if (_iRetCount > 1)
47     {
48         Scierror(78, _("%s: Wrong number of output argument(s): %d expected.\n"), "matrix", 1);
49         return types::Function::Error;
50     }
51
52     if (in[0]->isArrayOf()      == false &&
53             in[0]->isSparse()       == false &&
54             in[0]->isSparseBool()   == false)
55     {
56         std::wstring wstFuncName = L"%" + in[0]->getShortTypeStr() + L"_matrix";
57         return Overload::call(wstFuncName, in, _iRetCount, out);
58     }
59
60     pGTIn = in[0]->getAs<types::GenericType>();
61     if (pGTIn->getSize() == 0)
62     {
63         out.push_back(types::Double::Empty());
64         return types::Function::OK;
65     }
66
67     pGTOut = pGTIn->clone()->getAs<types::GenericType>();
68
69     if (in.size() == 2)
70     {
71         if (in[1]->isDouble() == false)
72         {
73             pGTOut->killMe();
74             Scierror(999, _("%s: Wrong type for input argument #%d : A real matrix expected.\n"), "matrix", 2);
75             return types::Function::Error;
76         }
77
78         types::Double* pDblNewSize = in[1]->getAs<types::Double>();
79
80         if (pDblNewSize->isComplex())
81         {
82             pGTOut->killMe();
83             Scierror(999, _("%s: Wrong type for input argument #%d : A real matrix expected.\n"), "matrix", 2);
84             return types::Function::Error;
85         }
86
87         iDims = pDblNewSize->getSize();
88         piSizes = new int[iDims];
89
90         for (int i = 0; i < iDims; i++)
91         {
92             piSizes[i] = static_cast<int>(pDblNewSize->get(i));
93             if (piSizes[i] == -1)
94             {
95                 if (iLeastOne == -1)
96                 {
97                     iLeastOne = i;
98                 }
99                 else
100                 {
101                     pGTOut->killMe();
102                     Scierror(999, _("%s: Wrong value for input argument #%d : Only one value can be equal to %d.\n"), "matrix", 2, -1);
103                     return types::Function::Error;
104                 }
105             }
106             else if (piSizes[i] < -1)
107             {
108                 pGTOut->killMe();
109                 Scierror(999, _("%s: Wrong value for input argument #%d : At most %d expected.\n"), "matrix", 2, -1);
110                 return types::Function::Error;
111             }
112             else
113             {
114                 newSize *= piSizes[i];
115             }
116         }
117     }
118     else
119     {
120         iDims = static_cast<int>(in.size()) - 1;
121         piSizes = new int[iDims];
122         for (int i = 1; i < static_cast<int>(in.size()); i++)
123         {
124             if (in[i]->isDouble() == false)
125             {
126                 pGTOut->killMe();
127                 Scierror(999, _("%s: Wrong type for input argument #%d : A real scalar expected.\n"), "matrix", i + 1);
128                 return types::Function::Error;
129             }
130
131             types::Double* pDblNewSize = in[i]->getAs<types::Double>();
132
133             if (pDblNewSize->isComplex() || pDblNewSize->isScalar() == false)
134             {
135                 pGTOut->killMe();
136                 Scierror(999, _("%s: Wrong type for input argument #%d : A real scalar expected.\n"), "matrix", i + 1);
137                 return types::Function::Error;
138             }
139
140             piSizes[i - 1] = static_cast<int>(pDblNewSize->get(0));
141             if (piSizes[i - 1] == -1)
142             {
143                 if (iLeastOne == -1)
144                 {
145                     iLeastOne = i - 1;
146                 }
147                 else
148                 {
149                     pGTOut->killMe();
150                     Scierror(999, _("%s: Wrong value for input argument #%d : Only one value can be equal to %d.\n"), "matrix", i + 1, -1);
151                     return types::Function::Error;
152                 }
153             }
154             else if (piSizes[i - 1] < -1)
155             {
156                 pGTOut->killMe();
157                 Scierror(999, _("%s: Wrong value for input argument #%d : At most %d expected.\n"), "matrix", i + 1, -1);
158                 return types::Function::Error;
159             }
160             else
161             {
162                 newSize *= piSizes[i - 1];
163             }
164         }
165     }
166
167     if (iLeastOne != -1)
168     {
169         piSizes[iLeastOne] = (int)pGTOut->getSize() / newSize;
170     }
171
172     if (pGTOut->isSparse() && iDims > 2)
173     {
174         pGTOut->killMe();
175         Scierror(999, _("%s: Wrong value for input argument(s) : Sparse matrix cannot be reshaped beyond %d dimensions.\n"), "matrix", 2);
176         return types::Function::Error;
177     }
178
179     bOk = pGTOut->reshape(piSizes, iDims);
180
181     if (bOk == false)
182     {
183         pGTOut->killMe();
184         Scierror(999, _("%s: Input and output matrices must have the same number of elements.\n"), "matrix");
185         return types::Function::Error;
186     }
187
188     delete[] piSizes;
189
190     out.push_back(pGTOut);
191     return types::Function::OK;
192 }
193 /*--------------------------------------------------------------------------*/