945bf3f194dab439a8f3b795896235dcfaa4679f
[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                 int iDims = 0;
122                 int* piDimsArray = NULL;
123
124                 if (pDblIn)
125                 {
126                     iDims = pDblIn->getDims();
127                     piDimsArray = pDblIn->getDimsArray();
128                 }
129                 else if (pIntIn)
130                 {
131                     iDims = pIntIn->getDims();
132                     piDimsArray = pIntIn->getDimsArray();
133                 }
134                 else
135                 {
136                     iDims = pPolyIn->getDims();
137                     piDimsArray = pPolyIn->getDimsArray();
138                 }
139
140                 // old function was "mtlsel"
141                 for (int i = 0; i < iDims; i++)
142                 {
143                     if (piDimsArray[i] > 1)
144                     {
145                         iOrientation = i + 1;
146                         break;
147                     }
148                 }
149             }
150             else if ((wcscmp(wcsString, L"native") == 0) && (in.size() == 2))
151             {
152                 iOuttype = 1;
153             }
154             else if ((wcscmp(wcsString, L"double") == 0) && (in.size() == 2))
155             {
156                 iOuttype = 2;
157             }
158             else
159             {
160                 const char* pstrExpected = NULL;
161                 if (in.size() == 2)
162                 {
163                     pstrExpected = "\"*\",\"r\",\"c\",\"m\",\"native\",\"double\"";
164                 }
165                 else
166                 {
167                     pstrExpected = "\"*\",\"r\",\"c\",\"m\"";
168                 }
169
170                 Scierror(999, _("%s: Wrong value for input argument #%d: Must be in the set {%s}.\n"), "sum", 2, pstrExpected);
171                 return types::Function::Error;
172             }
173         }
174         else
175         {
176             Scierror(999, _("%s: Wrong type for input argument #%d: A real matrix or a string expected.\n"), "sum", 2);
177             return types::Function::Error;
178         }
179     }
180
181     if (in.size() == 3)
182     {
183         if (in[2]->isString() == false)
184         {
185             Scierror(999, _("%s: Wrong type for input argument #%d: string expected.\n"), "sum", 3);
186             return types::Function::Error;
187         }
188
189         types::String* pStr = in[2]->getAs<types::String>();
190
191         if (pStr->isScalar() == false)
192         {
193             Scierror(999, _("%s: Wrong size for input argument #%d: A scalar string expected.\n"), "sum", 3);
194             return types::Function::Error;
195         }
196
197         wchar_t* wcsString = pStr->get(0);
198
199         if (wcscmp(wcsString, L"native") == 0)
200         {
201             iOuttype = 1;
202         }
203         else if (wcscmp(wcsString, L"double") == 0)
204         {
205             iOuttype = 2;
206         }
207         else
208         {
209             Scierror(999, _("%s: Wrong value for input argument #%d: %s or %s expected.\n"), "sum", 3, "\"native\"", "\"double\"");
210             return types::Function::Error;
211         }
212     }
213
214     bool isCopy = true;
215     /***** get data *****/
216     switch (in[0]->getType())
217     {
218         case types::InternalType::ScilabDouble:
219         {
220             pDblIn = in[0]->getAs<types::Double>();
221             isCopy = false;
222             break;
223         }
224         case types::InternalType::ScilabBool:
225         {
226             pDblIn = getAsDouble(in[0]->getAs<types::Bool>());
227             break;
228         }
229         case types::InternalType::ScilabPolynom:
230         {
231             pPolyIn = in[0]->getAs<types::Polynom>();
232             isCopy = false;
233             break;
234         }
235         case types::InternalType::ScilabInt8:
236         case types::InternalType::ScilabInt16:
237         case types::InternalType::ScilabInt32:
238         case types::InternalType::ScilabInt64:
239         case types::InternalType::ScilabUInt8:
240         case types::InternalType::ScilabUInt16:
241         case types::InternalType::ScilabUInt32:
242         case types::InternalType::ScilabUInt64:
243         {
244             if (iOuttype == 1)
245             {
246                 pIntIn = in[0]->getAs<types::GenericType>();
247                 isCopy = false;
248             }
249             else
250             {
251                 switch (in[0]->getType())
252                 {
253                     case types::InternalType::ScilabInt8:
254                     {
255                         pDblIn = getAsDouble(in[0]->getAs<types::Int8>());
256                         break;
257                     }
258                     case types::InternalType::ScilabInt16:
259                     {
260                         pDblIn = getAsDouble(in[0]->getAs<types::Int16>());
261                         break;
262                     }
263                     case types::InternalType::ScilabInt32:
264                     {
265                         pDblIn = getAsDouble(in[0]->getAs<types::Int32>());
266                         break;
267                     }
268                     case types::InternalType::ScilabInt64:
269                     {
270                         pDblIn = getAsDouble(in[0]->getAs<types::Int64>());
271                         break;
272                     }
273                     case types::InternalType::ScilabUInt8:
274                     {
275                         pDblIn = getAsDouble(in[0]->getAs<types::UInt8>());
276                         break;
277                     }
278                     case types::InternalType::ScilabUInt16:
279                     {
280                         pDblIn = getAsDouble(in[0]->getAs<types::UInt16>());
281                         break;
282                     }
283                     case types::InternalType::ScilabUInt32:
284                     {
285                         pDblIn = getAsDouble(in[0]->getAs<types::UInt32>());
286                         break;
287                     }
288                     case types::InternalType::ScilabUInt64:
289                     {
290                         pDblIn = getAsDouble(in[0]->getAs<types::UInt64>());
291                         break;
292                     }
293                 }
294             }
295             break;
296         }
297     }
298
299     /***** perform operation *****/
300     if (pDblIn)
301     {
302         if (pDblIn->isEmpty())
303         {
304             if (iOrientation == 0)
305             {
306                 out.push_back(new types::Double(0));
307             }
308             else
309             {
310                 out.push_back(types::Double::Empty());
311             }
312
313             if (isCopy)
314             {
315                 pDblIn->killMe();
316             }
317
318             return types::Function::OK;
319         }
320         else if (iOrientation > pDblIn->getDims())
321         {
322             pDblOut = pDblIn;
323
324             if (in[0]->isBool() == false)
325             {
326                 iOuttype = 2;
327             }
328         }
329         else
330         {
331             pDblOut = sum(pDblIn, iOrientation);
332             if (isCopy)
333             {
334                 pDblIn->killMe();
335             }
336         }
337     }
338     else if (pIntIn)
339     {
340         iOuttype = 1;
341         if (iOrientation > pIntIn->getDims())
342         {
343             pIntOut = pIntIn;
344         }
345         else
346         {
347             switch (pIntIn->getType())
348             {
349                 case types::InternalType::ScilabInt8:
350                 {
351                     pIntOut = sum(pIntIn->getAs<types::Int8>(), iOrientation);
352                     break;
353                 }
354                 case types::InternalType::ScilabInt16:
355                 {
356                     pIntOut = sum(pIntIn->getAs<types::Int16>(), iOrientation);
357                     break;
358                 }
359                 case types::InternalType::ScilabInt32:
360                 {
361                     pIntOut = sum(pIntIn->getAs<types::Int32>(), iOrientation);
362                     break;
363                 }
364                 case types::InternalType::ScilabInt64:
365                 {
366                     pIntOut = sum(pIntIn->getAs<types::Int64>(), iOrientation);
367                     break;
368                 }
369                 case types::InternalType::ScilabUInt8:
370                 {
371                     pIntOut = sum(pIntIn->getAs<types::UInt8>(), iOrientation);
372                     break;
373                 }
374                 case types::InternalType::ScilabUInt16:
375                 {
376                     pIntOut = sum(pIntIn->getAs<types::UInt16>(), iOrientation);
377                     break;
378                 }
379                 case types::InternalType::ScilabUInt32:
380                 {
381                     pIntOut = sum(pIntIn->getAs<types::UInt32>(), iOrientation);
382                     break;
383                 }
384                 case types::InternalType::ScilabUInt64:
385                 {
386                     pIntOut = sum(pIntIn->getAs<types::UInt64>(), iOrientation);
387                     break;
388                 }
389             }
390         }
391     }
392     else if (pPolyIn)
393     {
394         iOuttype = 1;
395         if (iOrientation > pPolyIn->getDims())
396         {
397             pPolyOut = pPolyIn;
398         }
399         else
400         {
401             pPolyOut = sum(pPolyIn, iOrientation);
402         }
403     }
404
405     /***** set result *****/
406     if ((iOuttype == 1) && isCopy)
407     {
408         switch (in[0]->getType())
409         {
410             case types::InternalType::ScilabBool:
411             {
412                 types::Bool* pB = new types::Bool(pDblOut->getDims(), pDblOut->getDimsArray());
413                 int* p = pB->get();
414                 double* pd = pDblOut->get();
415                 int size = pB->getSize();
416                 for (int i = 0; i < size; ++i)
417                 {
418                     p[i] = pd[i] != 0 ? 1 : 0;
419                 }
420                 out.push_back(pB);
421                 break;
422             }
423             case types::InternalType::ScilabPolynom:
424             {
425                 out.push_back(pPolyOut);
426                 break;
427             }
428             default:
429                 return types::Function::Error;
430         }
431
432         if (pDblOut)
433         {
434             pDblOut->killMe();
435         }
436     }
437     else
438     {
439         if (pPolyOut)
440         {
441             out.push_back(pPolyOut);
442         }
443         else if (pIntOut)
444         {
445             out.push_back(pIntOut);
446         }
447         else
448         {
449             out.push_back(pDblOut);
450         }
451
452     }
453
454     return types::Function::OK;
455 }
456 /*--------------------------------------------------------------------------*/