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