Coverity #1321243, #1321246, #1321242, #1321236, #1321239, #1321238, #1097871, #13212...
[scilab.git] / scilab / modules / elementary_functions / sci_gateway / cpp / sci_sum.cpp
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2006 - INRIA - Allan CORNET
4  * Copyright (C) 2011 - DIGITEO - Antoine ELIAS
5  * Copyright (C) 2012 - Scilab Enterprises - Cedric Delamarre
6  *
7  * Copyright (C) 2012 - 2016 - Scilab Enterprises
8  *
9  * This file is hereby licensed under the terms of the GNU GPL v2.0,
10  * pursuant to article 5.3.4 of the CeCILL v.2.1.
11  * This file was originally licensed under the terms of the CeCILL v2.1,
12  * and continues to be available under such terms.
13  * For more information, see the COPYING file which you should have received
14  * along with this program.
15  *
16  */
17 /*--------------------------------------------------------------------------*/
18 #include "elem_func_gw.hxx"
19 #include "function.hxx"
20 #include "double.hxx"
21 #include "string.hxx"
22 #include "overload.hxx"
23 #include "sum.hxx"
24 #include "int.hxx"
25 #include "polynom.hxx"
26
27 extern "C"
28 {
29 #include "Scierror.h"
30 #include "localization.h"
31 #include "charEncoding.h"
32 #include "basic_functions.h"
33 }
34
35 /*--------------------------------------------------------------------------*/
36 types::Function::ReturnValue sci_sum(types::typed_list &in, int _iRetCount, types::typed_list &out)
37 {
38     types::Double* pDblIn       = NULL;
39     types::Double* pDblOut      = NULL;
40     types::Polynom* pPolyIn     = NULL;
41     types::Polynom* pPolyOut    = NULL;
42
43     int iOrientation    = 0;
44     int iOuttype        = 1; // 1 = native | 2 = double (type of output value)
45
46     if (in.size() < 1 || in.size() > 3)
47     {
48         Scierror(999, _("%s: Wrong number of input arguments: %d to %d expected.\n"), "sum", 1, 3);
49         return types::Function::Error;
50     }
51
52     if (_iRetCount > 1)
53     {
54         Scierror(78, _("%s: Wrong number of output argument(s): %d expected.\n"), "sum", 1);
55         return types::Function::Error;
56     }
57
58     bool isCopy = true;
59     /***** get data *****/
60     switch (in[0]->getType())
61     {
62         case types::InternalType::ScilabDouble:
63         {
64             pDblIn = in[0]->getAs<types::Double>();
65             isCopy = false;
66             break;
67         }
68         case types::InternalType::ScilabBool:
69         {
70             pDblIn = getAsDouble(in[0]->getAs<types::Bool>());
71             iOuttype = 2;
72             break;
73         }
74         case types::InternalType::ScilabPolynom:
75         {
76             pPolyIn = in[0]->getAs<types::Polynom>();
77             break;
78         }
79         case types::InternalType::ScilabInt8:
80         {
81             pDblIn = getAsDouble(in[0]->getAs<types::Int8>());
82             break;
83         }
84         case types::InternalType::ScilabInt16:
85         {
86             pDblIn = getAsDouble(in[0]->getAs<types::Int16>());
87             break;
88         }
89         case types::InternalType::ScilabInt32:
90         {
91             pDblIn = getAsDouble(in[0]->getAs<types::Int32>());
92             break;
93         }
94         case types::InternalType::ScilabInt64:
95         {
96             pDblIn = getAsDouble(in[0]->getAs<types::Int64>());
97             break;
98         }
99         case types::InternalType::ScilabUInt8:
100         {
101             pDblIn = getAsDouble(in[0]->getAs<types::UInt8>());
102             break;
103         }
104         case types::InternalType::ScilabUInt16:
105         {
106             pDblIn = getAsDouble(in[0]->getAs<types::UInt16>());
107             break;
108         }
109         case types::InternalType::ScilabUInt32:
110         {
111             pDblIn = getAsDouble(in[0]->getAs<types::UInt32>());
112             break;
113         }
114         case types::InternalType::ScilabUInt64:
115         {
116             pDblIn = getAsDouble(in[0]->getAs<types::UInt64>());
117             break;
118         }
119         default:
120         {
121             std::wstring wstFuncName = L"%" + in[0]->getShortTypeStr() + L"_sum";
122             types::Function::ReturnValue ret = Overload::call(wstFuncName, in, _iRetCount, out);
123             return ret;
124         }
125     }
126
127     if (in.size() >= 2)
128     {
129         if (in[1]->isDouble())
130         {
131             types::Double* pDbl = in[1]->getAs<types::Double>();
132
133             if (pDbl->isScalar() == false)
134             {
135                 if (isCopy && pDblIn)
136                 {
137                     pDblIn->killMe();
138                 }
139
140                 Scierror(999, _("%s: Wrong value for input argument #%d: A positive scalar expected.\n"), "sum", 2);
141                 return types::Function::Error;
142             }
143
144             iOrientation = static_cast<int>(pDbl->get(0));
145
146             if (iOrientation <= 0)
147             {
148                 if (isCopy && pDblIn)
149                 {
150                     pDblIn->killMe();
151                 }
152
153                 Scierror(999, _("%s: Wrong value for input argument #%d: A positive scalar expected.\n"), "sum", 2);
154                 return types::Function::Error;
155             }
156         }
157         else if (in[1]->isString())
158         {
159             types::String* pStr = in[1]->getAs<types::String>();
160
161             if (pStr->isScalar() == false)
162             {
163                 if (isCopy && pDblIn)
164                 {
165                     pDblIn->killMe();
166                 }
167
168                 Scierror(999, _("%s: Wrong size for input argument #%d: A scalar string expected.\n"), "sum", 2);
169                 return types::Function::Error;
170             }
171
172             wchar_t* wcsString = pStr->get(0);
173
174             if (wcscmp(wcsString, L"*") == 0)
175             {
176                 iOrientation = 0;
177             }
178             else if (wcscmp(wcsString, L"r") == 0)
179             {
180                 iOrientation = 1;
181             }
182             else if (wcscmp(wcsString, L"c") == 0)
183             {
184                 iOrientation = 2;
185             }
186             else if (wcscmp(wcsString, L"m") == 0)
187             {
188                 int iDims = 0;
189                 int* piDimsArray = NULL;
190
191                 if (pDblIn)
192                 {
193                     iDims = pDblIn->getDims();
194                     piDimsArray = pDblIn->getDimsArray();
195                 }
196                 else
197                 {
198                     iDims = pPolyIn->getDims();
199                     piDimsArray = pPolyIn->getDimsArray();
200                 }
201
202                 // old function was "mtlsel"
203                 for (int i = 0; i < iDims; i++)
204                 {
205                     if (piDimsArray[i] > 1)
206                     {
207                         iOrientation = i + 1;
208                         break;
209                     }
210                 }
211             }
212             else if ((wcscmp(wcsString, L"native") == 0) && (in.size() == 2))
213             {
214                 iOuttype = 1;
215             }
216             else if ((wcscmp(wcsString, L"double") == 0) && (in.size() == 2))
217             {
218                 iOuttype = 2;
219             }
220             else
221             {
222                 const char* pstrExpected = NULL;
223                 if (in.size() == 2)
224                 {
225                     pstrExpected = "\"*\",\"r\",\"c\",\"m\",\"native\",\"double\"";
226                 }
227                 else
228                 {
229                     pstrExpected = "\"*\",\"r\",\"c\",\"m\"";
230                 }
231
232                 if (isCopy && pDblIn)
233                 {
234                     pDblIn->killMe();
235                 }
236
237                 Scierror(999, _("%s: Wrong value for input argument #%d: Must be in the set {%s}.\n"), "sum", 2, pstrExpected);
238                 return types::Function::Error;
239             }
240         }
241         else
242         {
243             if (isCopy && pDblIn)
244             {
245                 pDblIn->killMe();
246             }
247
248             Scierror(999, _("%s: Wrong type for input argument #%d: A real matrix or a string expected.\n"), "sum", 2);
249             return types::Function::Error;
250         }
251     }
252
253     if (in.size() == 3)
254     {
255         if (in[2]->isString() == false)
256         {
257             if (isCopy && pDblIn)
258             {
259                 pDblIn->killMe();
260             }
261
262             Scierror(999, _("%s: Wrong type for input argument #%d: string expected.\n"), "sum", 3);
263             return types::Function::Error;
264         }
265
266         types::String* pStr = in[2]->getAs<types::String>();
267
268         if (pStr->isScalar() == false)
269         {
270             if (isCopy && pDblIn)
271             {
272                 pDblIn->killMe();
273             }
274
275             Scierror(999, _("%s: Wrong size for input argument #%d: A scalar string expected.\n"), "sum", 3);
276             return types::Function::Error;
277         }
278
279         wchar_t* wcsString = pStr->get(0);
280
281         if (wcscmp(wcsString, L"native") == 0)
282         {
283             iOuttype = 1;
284         }
285         else if (wcscmp(wcsString, L"double") == 0)
286         {
287             iOuttype = 2;
288         }
289         else
290         {
291             if (isCopy && pDblIn)
292             {
293                 pDblIn->killMe();
294             }
295
296             Scierror(999, _("%s: Wrong value for input argument #%d: %s or %s expected.\n"), "sum", 3, "\"native\"", "\"double\"");
297             return types::Function::Error;
298         }
299     }
300
301     /***** perform operation *****/
302     if (pDblIn)
303     {
304         if (pDblIn->isEmpty())
305         {
306             if (iOrientation == 0)
307             {
308                 out.push_back(new types::Double(0));
309             }
310             else
311             {
312                 out.push_back(types::Double::Empty());
313             }
314
315             if (isCopy)
316             {
317                 pDblIn->killMe();
318             }
319
320             return types::Function::OK;
321         }
322         else if (iOrientation > pDblIn->getDims())
323         {
324             pDblOut = pDblIn;
325
326             if (in[0]->isBool() == false)
327             {
328                 iOuttype = 2;
329             }
330         }
331         else
332         {
333             pDblOut = sum(pDblIn, iOrientation);
334             if (isCopy)
335             {
336                 pDblIn->killMe();
337             }
338         }
339     }
340     else if (pPolyIn)
341     {
342         iOuttype = 1;
343         if (iOrientation > pPolyIn->getDims())
344         {
345             pPolyOut = pPolyIn->getAs<types::Polynom>();
346         }
347         else
348         {
349             pPolyOut = sum(pPolyIn, iOrientation);
350         }
351     }
352
353     /***** set result *****/
354     if ((iOuttype == 1) && isCopy)
355     {
356         switch (in[0]->getType())
357         {
358             case types::InternalType::ScilabBool:
359             {
360                 types::Bool* pB = new types::Bool(pDblOut->getDims(), pDblOut->getDimsArray());
361                 int* p = pB->get();
362                 double* pd = pDblOut->get();
363                 int size = pB->getSize();
364                 for (int i = 0; i < size; ++i)
365                 {
366                     p[i] = pd[i] != 0 ? 1 : 0;
367                 }
368                 out.push_back(pB);
369                 break;
370             }
371             case types::InternalType::ScilabPolynom:
372             {
373                 out.push_back(pPolyOut);
374                 break;
375             }
376             case types::InternalType::ScilabInt8:
377             {
378                 out.push_back(toInt<types::Int8>(pDblOut));
379                 break;
380             }
381             case types::InternalType::ScilabInt16:
382             {
383                 out.push_back(toInt<types::Int16>(pDblOut));
384                 break;
385             }
386             case types::InternalType::ScilabInt32:
387             {
388                 out.push_back(toInt<types::Int32>(pDblOut));
389                 break;
390             }
391             case types::InternalType::ScilabInt64:
392             {
393                 out.push_back(toInt<types::Int64>(pDblOut));
394                 break;
395             }
396             case types::InternalType::ScilabUInt8:
397             {
398                 out.push_back(toInt<types::UInt8>(pDblOut));
399                 break;
400             }
401             case types::InternalType::ScilabUInt16:
402             {
403                 out.push_back(toInt<types::UInt16>(pDblOut));
404                 break;
405             }
406             case types::InternalType::ScilabUInt32:
407             {
408                 out.push_back(toInt<types::UInt32>(pDblOut));
409                 break;
410             }
411             case types::InternalType::ScilabUInt64:
412             {
413                 out.push_back(toInt<types::UInt64>(pDblOut));
414                 break;
415             }
416             default:
417                 return types::Function::Error;
418         }
419
420         if (pDblOut)
421         {
422             pDblOut->killMe();
423         }
424     }
425     else
426     {
427         out.push_back(pDblOut);
428     }
429
430     return types::Function::OK;
431 }
432 /*--------------------------------------------------------------------------*/