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