elementary_functions module.
[scilab.git] / scilab / modules / elementary_functions / sci_gateway / cpp / sci_cumprod.cpp
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2012 - DIGITEO - Cedric DELAMARRE
4  *
5  * This file must be used under the terms of the CeCILL.
6  * This source file is licensed as described in the file COPYING, which
7  * you should have received as part of this distribution.  The terms
8  * are also available at
9  * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
10  *
11  */
12 /*--------------------------------------------------------------------------*/
13 #include "elem_func_gw.hxx"
14 #include "function.hxx"
15 #include "double.hxx"
16 #include "string.hxx"
17 #include "overload.hxx"
18 #include "execvisitor.hxx"
19 #include "cumprod.hxx"
20
21 extern "C"
22 {
23 #include "Scierror.h"
24 #include "localization.h"
25 #include "basic_functions.h"
26 }
27
28 /*--------------------------------------------------------------------------*/
29 types::Function::ReturnValue sci_cumprod(types::typed_list &in, int _iRetCount, types::typed_list &out)
30 {
31     types::Double* pDblIn       = NULL;
32     types::Double* pDblOut      = NULL;
33     types::Polynom* pPolyIn     = NULL;
34     types::Polynom* pPolyOut    = NULL;
35
36     int iOrientation    = 0;
37     int iOuttype        = 1; // 1 = native | 2 = double (type of output value)
38
39     if (in.size() < 1 || in.size() > 3)
40     {
41         ScierrorW(77, _W("%ls: Wrong number of input argument(s): %d to %d expected.\n"), L"cumprod", 1, 3);
42         return types::Function::Error;
43     }
44
45     if (_iRetCount > 1)
46     {
47         ScierrorW(78, _W("%ls: Wrong number of output argument(s): %d expected.\n"), L"cumprod", 1);
48         return types::Function::Error;
49     }
50
51     /***** get data *****/
52     if (in[0]->isDouble()) // double
53     {
54         pDblIn = in[0]->getAs<types::Double>();
55     }
56     else if (in[0]->isBool()) // bool
57     {
58         types::Bool* pBIn = in[0]->getAs<types::Bool>();
59         pDblIn = new types::Double(pBIn->getDims(), pBIn->getDimsArray());
60         for (int i = 0; i < pBIn->getSize(); i++)
61         {
62             pBIn->get(i) ? pDblIn->set(i, 1) : pDblIn->set(i, 0);
63         }
64         iOuttype = 2;
65     }
66     else if (in[0]->isPoly()) // polynom
67     {
68         pPolyIn = in[0]->getAs<types::Polynom>();
69     }
70     else if (in[0]->isInt8()) // int
71     {
72         types::Int8* pIIn = in[0]->getAs<types::Int8>();
73         pDblIn = new types::Double(pIIn->getDims(), pIIn->getDimsArray());
74         for (int i = 0; i < pIIn->getSize(); i++)
75         {
76             pDblIn->set(i, static_cast<double>(pIIn->get(i)));
77         }
78     }
79     else if (in[0]->isInt16())
80     {
81         types::Int16* pIIn = in[0]->getAs<types::Int16>();
82         pDblIn = new types::Double(pIIn->getDims(), pIIn->getDimsArray());
83         for (int i = 0; i < pIIn->getSize(); i++)
84         {
85             pDblIn->set(i, static_cast<double>(pIIn->get(i)));
86         }
87     }
88     else if (in[0]->isInt32())
89     {
90         types::Int32* pIIn = in[0]->getAs<types::Int32>();
91         pDblIn = new types::Double(pIIn->getDims(), pIIn->getDimsArray());
92         for (int i = 0; i < pIIn->getSize(); i++)
93         {
94             pDblIn->set(i, static_cast<double>(pIIn->get(i)));
95         }
96     }
97     else if (in[0]->isInt64()) // uint
98     {
99         types::Int64* pIIn = in[0]->getAs<types::Int64>();
100         pDblIn = new types::Double(pIIn->getDims(), pIIn->getDimsArray());
101         for (int i = 0; i < pIIn->getSize(); i++)
102         {
103             pDblIn->set(i, static_cast<double>(pIIn->get(i)));
104         }
105     }
106     else if (in[0]->isUInt8())
107     {
108         types::UInt8* pIIn = in[0]->getAs<types::UInt8>();
109         pDblIn = new types::Double(pIIn->getDims(), pIIn->getDimsArray());
110         for (int i = 0; i < pIIn->getSize(); i++)
111         {
112             pDblIn->set(i, static_cast<double>(pIIn->get(i)));
113         }
114     }
115     else if (in[0]->isUInt16())
116     {
117         types::UInt16* pIIn = in[0]->getAs<types::UInt16>();
118         pDblIn = new types::Double(pIIn->getDims(), pIIn->getDimsArray());
119         for (int i = 0; i < pIIn->getSize(); i++)
120         {
121             pDblIn->set(i, static_cast<double>(pIIn->get(i)));
122         }
123     }
124     else if (in[0]->isUInt32())
125     {
126         types::UInt32* pIIn = in[0]->getAs<types::UInt32>();
127         pDblIn = new types::Double(pIIn->getDims(), pIIn->getDimsArray());
128         for (int i = 0; i < pIIn->getSize(); i++)
129         {
130             pDblIn->set(i, static_cast<double>(pIIn->get(i)));
131         }
132     }
133     else if (in[0]->isUInt64())
134     {
135         types::UInt64* pIIn = in[0]->getAs<types::UInt64>();
136         pDblIn = new types::Double(pIIn->getDims(), pIIn->getDimsArray());
137         for (int i = 0; i < pIIn->getSize(); i++)
138         {
139             pDblIn->set(i, static_cast<double>(pIIn->get(i)));
140         }
141     }
142     else
143     {
144         std::wstring wstFuncName = L"%"  + in[0]->getShortTypeStr() + L"_cumprod";
145         return Overload::call(wstFuncName, in, _iRetCount, out, new ExecVisitor());
146     }
147
148     if (in.size() == 3)
149     {
150         if (in[2]->isString() == false)
151         {
152             ScierrorW(999, _W("%ls: Wrong type for input argument #%d : A string expected.\n"), L"cumprod", 3);
153             return types::Function::Error;
154         }
155
156         wchar_t* wcsString = in[2]->getAs<types::String>()->get(0);
157
158         if (wcscmp(wcsString, L"native") == 0)
159         {
160             iOuttype = 1;
161         }
162         else if (wcscmp(wcsString, L"double") == 0)
163         {
164             iOuttype = 2;
165         }
166         else
167         {
168             ScierrorW(999, _W("%ls: Wrong value for input argument #%d : It must be one of the following strings : native or double.\n"), L"cumprod", 3);
169             return types::Function::Error;
170         }
171     }
172
173     if (in.size() >= 2)
174     {
175         if (in[1]->isDouble())
176         {
177             types::Double* pDbl = in[1]->getAs<types::Double>();
178
179             if (pDbl->isScalar() == false)
180             {
181                 ScierrorW(999, _W("%ls: Wrong value for input argument #%d : A positive scalar expected.\n"), L"cumprod", 2);
182                 return types::Function::Error;
183             }
184
185             iOrientation = static_cast<int>(pDbl->get(0));
186
187             if (iOrientation <= 0)
188             {
189                 ScierrorW(999, _W("%ls: Wrong value for input argument #%d : A positive scalar expected.\n"), L"cumprod", 2);
190                 return types::Function::Error;
191             }
192         }
193         else if (in[1]->isString())
194         {
195             wchar_t* wcsString = in[1]->getAs<types::String>()->get(0);
196
197             if (wcscmp(wcsString, L"*") == 0)
198             {
199                 iOrientation = 0;
200             }
201             else if (wcscmp(wcsString, L"r") == 0)
202             {
203                 iOrientation = 1;
204             }
205             else if (wcscmp(wcsString, L"c") == 0)
206             {
207                 iOrientation = 2;
208             }
209             else if (wcscmp(wcsString, L"m") == 0)
210             {
211                 int iDims = 0;
212                 int* piDimsArray = NULL;
213
214                 if (pDblIn)
215                 {
216                     iDims = pDblIn->getDims();
217                     piDimsArray = pDblIn->getDimsArray();
218                 }
219                 else
220                 {
221                     iDims = pPolyIn->getDims();
222                     piDimsArray = pPolyIn->getDimsArray();
223                 }
224
225                 // old function was "mtlsel"
226                 for (int i = 0; i < iDims; i++)
227                 {
228                     if (piDimsArray[i] > 1)
229                     {
230                         iOrientation = i + 1;
231                         break;
232                     }
233                 }
234             }
235             else if ((wcscmp(wcsString, L"native") == 0) && (in.size() == 2))
236             {
237                 iOuttype = 1;
238             }
239             else if ((wcscmp(wcsString, L"double") == 0) && (in.size() == 2))
240             {
241                 iOuttype = 2;
242             }
243             else
244             {
245                 if (in.size() == 2)
246                 {
247                     ScierrorW(999, _W("%ls: Wrong value for input argument #%d : It must be one of the following strings : *, r, c, m, native or double.\n"), L"cumprod", 2);
248                 }
249                 else
250                 {
251                     ScierrorW(999, _W("%ls: Wrong value for input argument #%d : It must be one of the following strings : *, r, c or m.\n"), L"cumprod", 2);
252                 }
253
254                 return types::Function::Error;
255             }
256         }
257         else
258         {
259             ScierrorW(999, _W("%ls: Wrong type for input argument #%d : A real matrix or a string expected.\n"), L"cumprod", 2);
260             return types::Function::Error;
261         }
262     }
263
264     /***** perform operation *****/
265     if (pDblIn)
266     {
267         if (iOrientation > pDblIn->getDims())
268         {
269             if (in[0]->isDouble())
270             {
271                 pDblOut = pDblIn->clone()->getAs<types::Double>();
272             }
273             else
274             {
275                 pDblOut = pDblIn;
276             }
277
278             if (in[0]->isBool() == false)
279             {
280                 iOuttype = 2;
281             }
282         }
283         else
284         {
285             pDblOut = new types::Double(pDblIn->getDims(), pDblIn->getDimsArray(), pDblIn->isComplex());
286             cumprod(pDblIn, iOrientation, pDblOut);
287             if (in[0]->isDouble() == false)
288             {
289                 delete pDblIn;
290                 pDblIn = NULL;
291             }
292         }
293     }
294     else if (pPolyIn)
295     {
296         iOuttype = 1;
297         if (iOrientation > pPolyIn->getDims())
298         {
299             pPolyOut = pPolyIn->clone()->getAs<types::Polynom>();
300         }
301         else
302         {
303             pPolyOut = new types::Polynom(pPolyIn->getVariableName(), pPolyIn->getDims(), pPolyIn->getDimsArray());
304             pPolyOut->setComplex(pPolyIn->isComplex());
305             cumprod(pPolyIn, iOrientation, pPolyOut);
306         }
307     }
308
309     /***** set result *****/
310     if ((iOuttype == 1) && (in[0]->isDouble() == false))
311     {
312         if (in[0]->isBool())
313         {
314             types::Bool* pBOut = new types::Bool(pDblOut->getDims(), pDblOut->getDimsArray());
315             for (int i = 0; i < pDblOut->getSize(); i++)
316             {
317                 pDblOut->get(i) ? pBOut->set(i, 1) : pBOut->set(i, 0);
318             }
319             out.push_back(pBOut);
320         }
321         else if (in[0]->isPoly())
322         {
323             out.push_back(pPolyOut);
324         }
325         else if (in[0]->isInt8())
326         {
327             types::Int8* pIOut = new types::Int8(pDblOut->getDims(), pDblOut->getDimsArray());
328             for (int i = 0; i < pIOut->getSize(); i++)
329             {
330                 pIOut->set(i, static_cast<char>(pDblOut->get(i)));
331             }
332             out.push_back(pIOut);
333         }
334         else if (in[0]->isInt16())
335         {
336             types::Int16* pIOut = new types::Int16(pDblOut->getDims(), pDblOut->getDimsArray());
337             for (int i = 0; i < pIOut->getSize(); i++)
338             {
339                 pIOut->set(i, static_cast<short int>(pDblOut->get(i)));
340             }
341             out.push_back(pIOut);
342         }
343         else if (in[0]->isInt32())
344         {
345             types::Int32* pIOut = new types::Int32(pDblOut->getDims(), pDblOut->getDimsArray());
346             for (int i = 0; i < pIOut->getSize(); i++)
347             {
348                 pIOut->set(i, static_cast<int>(pDblOut->get(i)));
349             }
350             out.push_back(pIOut);
351         }
352         else if (in[0]->isInt64())
353         {
354             types::Int64* pIOut = new types::Int64(pDblOut->getDims(), pDblOut->getDimsArray());
355             for (int i = 0; i < pIOut->getSize(); i++)
356             {
357                 pIOut->set(i, static_cast<long long int>(pDblOut->get(i)));
358             }
359             out.push_back(pIOut);
360         }
361         else if (in[0]->isUInt8())
362         {
363             types::UInt8* pIOut = new types::UInt8(pDblOut->getDims(), pDblOut->getDimsArray());
364             for (int i = 0; i < pIOut->getSize(); i++)
365             {
366                 pIOut->set(i, static_cast<unsigned char>(pDblOut->get(i)));
367             }
368             out.push_back(pIOut);
369         }
370         else if (in[0]->isUInt16())
371         {
372             types::UInt16* pIOut = new types::UInt16(pDblOut->getDims(), pDblOut->getDimsArray());
373             for (int i = 0; i < pIOut->getSize(); i++)
374             {
375                 pIOut->set(i, static_cast<unsigned short int>(pDblOut->get(i)));
376             }
377             out.push_back(pIOut);
378         }
379         else if (in[0]->isUInt32())
380         {
381             types::UInt32* pIOut = new types::UInt32(pDblOut->getDims(), pDblOut->getDimsArray());
382             for (int i = 0; i < pIOut->getSize(); i++)
383             {
384                 pIOut->set(i, static_cast<unsigned int>(pDblOut->get(i)));
385             }
386             out.push_back(pIOut);
387         }
388         else if (in[0]->isUInt64())
389         {
390             types::UInt64* pIOut = new types::UInt64(pDblOut->getDims(), pDblOut->getDimsArray());
391             for (int i = 0; i < pIOut->getSize(); i++)
392             {
393                 pIOut->set(i, static_cast<unsigned long long int>(pDblOut->get(i)));
394             }
395             out.push_back(pIOut);
396         }
397     }
398     else
399     {
400         out.push_back(pDblOut);
401     }
402
403     return types::Function::OK;
404 }
405 /*--------------------------------------------------------------------------*/