f8f794618386763d47b07e6b7e9f33fb3bb4ea1e
[scilab.git] / scilab / modules / elementary_functions / sci_gateway / cpp / elem_func_gw.cpp
1 /*
2 *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 *  Copyright (C) 2008-2008 - DIGITEO - Antoine ELIAS
4 *  Copyright (C) 2011-2011 - DIGITEO - Bruno JOFRET
5 *  Copyright (C) 2018 - St├ęphane MOTTELET
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 //for Visual Leak Detector in debug compilation mode
17 //#define DEBUG_VLD
18 #if defined(DEBUG_VLD) && defined(_DEBUG)
19 #include <vld.h>
20 #endif
21
22 #include "elem_func_gw.hxx"
23 #include "function.hxx"
24 #include "context.hxx"
25 #include "overload.hxx"
26 #include "Scierror.h"
27 #include "localization.h"
28 #include "charEncoding.h"
29 #include "sparse.hxx"
30 #include "int.hxx"
31 #include "double.hxx"
32 #include "bool.hxx"
33 #include "string.hxx"
34
35 #define MODULE_NAME L"elementary_functions"
36 extern "C"
37 {
38 #include "gw_elementary_functions.h"
39 }
40
41 int ElemFuncModule::Load()
42 {
43     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"abs", &sci_abs, MODULE_NAME));
44     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"acos", &sci_acos, MODULE_NAME));
45     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"asin", &sci_asin, MODULE_NAME));
46     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"atan", &sci_atan, MODULE_NAME));
47     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"bitstring", &sci_bitstring, MODULE_NAME));
48     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"ceil", &sci_ceil, MODULE_NAME));
49     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"clean", &sci_clean, MODULE_NAME));
50     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"conj", &sci_conj, MODULE_NAME));
51     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"cos", &sci_cos, MODULE_NAME));
52     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"cumprod", &sci_cumprod, MODULE_NAME));
53     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"cumsum", &sci_cumsum, MODULE_NAME));
54     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"diag", &sci_diag, MODULE_NAME));
55     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"dsearch", &sci_dsearch, MODULE_NAME));
56     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"exp", &sci_exp, MODULE_NAME));
57     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"expm", &sci_expm, MODULE_NAME));
58     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"eye", &sci_eye, MODULE_NAME));
59     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"floor", &sci_floor, MODULE_NAME));
60     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"frexp", &sci_frexp, MODULE_NAME));
61     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"gsort", &sci_gsort, MODULE_NAME));
62     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"imag", &sci_imag, MODULE_NAME));
63     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"imult", &sci_imult, MODULE_NAME));
64     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"int", &sci_int, MODULE_NAME));
65     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"isreal", &sci_isreal, MODULE_NAME));
66     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"isequal", &sci_isequal, MODULE_NAME));
67     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"isvector", &sci_isvector, MODULE_NAME));
68     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"kron", &sci_kron, MODULE_NAME));
69     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"linspace", &sci_linspace, MODULE_NAME));
70     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"log", &sci_log, MODULE_NAME));
71     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"log1p", &sci_log1p, MODULE_NAME));
72     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"matrix", &sci_matrix, MODULE_NAME));
73     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"max", &sci_max, MODULE_NAME));
74     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"min", &sci_min, MODULE_NAME));
75     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"nearfloat", &sci_nearfloat, MODULE_NAME));
76     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"number_properties", &sci_number_properties, MODULE_NAME));
77     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"ones", &sci_ones, MODULE_NAME));
78     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"prod", &sci_prod, MODULE_NAME));
79     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"permute", &sci_permute, MODULE_NAME));
80     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"rand", &sci_rand, MODULE_NAME));
81     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"real", &sci_real, MODULE_NAME));
82     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"round", &sci_round, MODULE_NAME));
83     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"sign", &sci_sign, MODULE_NAME));
84     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"sin", &sci_sin, MODULE_NAME));
85     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"size", &sci_size, MODULE_NAME));
86     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"sqrt", &sci_sqrt, MODULE_NAME));
87     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"sum", &sci_sum, MODULE_NAME));
88     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"tan", &sci_tan, MODULE_NAME));
89     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"testmatrix", &sci_testmatrix, MODULE_NAME));
90     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"tril", &sci_tril, MODULE_NAME));
91     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"triu", &sci_triu, MODULE_NAME));
92     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"zeros", &sci_zeros, MODULE_NAME));
93     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"rat", &sci_rat, MODULE_NAME));
94     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"base2dec", &sci_base2dec, MODULE_NAME));
95     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"dec2base", &sci_dec2base, MODULE_NAME));
96     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"log10", &sci_log10, MODULE_NAME));
97     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"cosh", &sci_cosh, MODULE_NAME));
98     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"sinh", &sci_sinh, MODULE_NAME));
99     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"tanh", &sci_tanh, MODULE_NAME));
100     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"acosh", &sci_acosh, MODULE_NAME));
101     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"asinh", &sci_asinh, MODULE_NAME));
102     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"atanh", &sci_atanh, MODULE_NAME));
103     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"isvector", &sci_isvector, MODULE_NAME));
104     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"issquare", &sci_issquare, MODULE_NAME));
105     return 1;
106 }
107
108
109 bool getDimsFromArguments(types::typed_list& in, const std::string& _pstName, int* _iDims, int** _piDims, bool* _alloc)
110 {
111     types::Double* pOut = 0;
112
113     *_alloc = false;
114     *_iDims = 0;
115     *_piDims = NULL;
116
117     if (in.size() == 0)
118     {
119         *_iDims = 2;
120         *_piDims = new int[*_iDims];
121         (*_piDims)[0] = 1;
122         (*_piDims)[1] = 1;
123         *_alloc = true;
124         return true;
125     }
126     else if (in.size() == 1)
127     {
128         *_iDims = 1;
129         // :
130         if (in[0]->isColon())
131         {
132             *_iDims = -1;
133             return false;
134         }
135
136         if (in[0]->isArrayOf() == false)
137         {
138             if (in[0]->isSparse())
139             {
140                 types::Sparse* sp = in[0]->getAs<types::Sparse>();
141                 *_iDims = sp->getDims();
142                 *_piDims = sp->getDimsArray();
143                 return true;
144             }
145             else if (in[0]->isSparseBool())
146             {
147                 types::SparseBool* sp = in[0]->getAs<types::SparseBool>();
148                 *_iDims = sp->getDims();
149                 *_piDims = sp->getDimsArray();
150                 return true;
151             }
152             return false;
153         }
154
155         types::GenericType* pIn = in[0]->getAs<types::GenericType>();
156         *_iDims = pIn->getDims();
157         *_piDims = pIn->getDimsArray();
158
159         return true;
160     }
161     else
162     {
163         *_iDims = static_cast<int>(in.size());
164         *_piDims = new int[*_iDims];
165         *_alloc = true;
166         for (int i = 0; i < *_iDims; i++)
167         {
168             if (in[i]->isArrayOf() == false)
169             {
170                 Scierror(999, _("%s: Wrong type for input argument #%d: A scalar expected.\n"), _pstName.c_str(), i + 1);
171                 delete[] * _piDims;
172                 return false;
173             }
174
175             types::GenericType* pGTIn = in[i]->getAs<types::GenericType>();
176             if (pGTIn->isScalar() == false || pGTIn->isComplex())
177             {
178                 Scierror(999, _("%s: Wrong size for input argument #%d: A scalar expected.\n"), _pstName.c_str(), i + 1);
179                 delete[] * _piDims;
180                 return false;
181             }
182
183             switch (in[i]->getType())
184             {
185                 case types::InternalType::ScilabDouble:
186                 {
187                     double dValue = in[i]->getAs<types::Double>()->get(0);
188                     if (dValue >= INT_MAX)
189                     {
190                         Scierror(999, _("%s: variable size exceeded : less than %d expected.\n"), _pstName.c_str(), INT_MAX);
191                         delete[] * _piDims;
192                         return false;
193                     }
194                     (*_piDims)[i] = static_cast<int>(dValue);
195                 }
196                 break;
197                 case types::InternalType::ScilabInt8:
198                     (*_piDims)[i] = static_cast<int>(in[i]->getAs<types::Int8>()->get()[0]);
199                     break;
200                 case types::InternalType::ScilabUInt8:
201                     (*_piDims)[i] = static_cast<int>(in[i]->getAs<types::UInt8>()->get()[0]);
202                     break;
203                 case types::InternalType::ScilabInt16:
204                     (*_piDims)[i] = static_cast<int>(in[i]->getAs<types::Int16>()->get()[0]);
205                     break;
206                 case types::InternalType::ScilabUInt16:
207                     (*_piDims)[i] = static_cast<int>(in[i]->getAs<types::UInt16>()->get()[0]);
208                     break;
209                 case types::InternalType::ScilabInt32:
210                     (*_piDims)[i] = in[i]->getAs<types::Int32>()->get()[0];
211                     break;
212                 case types::InternalType::ScilabUInt32:
213                     (*_piDims)[i] = static_cast<int>(in[i]->getAs<types::UInt32>()->get()[0]);
214                     break;
215                 case types::InternalType::ScilabInt64:
216                 {
217                     long long llValue = in[i]->getAs<types::Int64>()->get(0);
218                     if (llValue >= INT_MAX)
219                     {
220                         Scierror(999, _("%s: variable size exceeded : less than %d expected.\n"), _pstName.c_str(), INT_MAX);
221                         delete[] * _piDims;
222                         return false;
223                     }
224                     (*_piDims)[i] = static_cast<int>(llValue);
225                     break;
226                 }
227                 case types::InternalType::ScilabUInt64:
228                 {
229                     unsigned long long ullValue = in[i]->getAs<types::UInt64>()->get(0);
230                     if (ullValue >= INT_MAX)
231                     {
232                         Scierror(999, _("%s: variable size exceeded : less than %d expected.\n"), _pstName.c_str(), INT_MAX);
233                         delete[] * _piDims;
234                         return false;
235                     }
236                     (*_piDims)[i] = static_cast<int>(ullValue);
237                     break;
238                 }
239                 default:
240                     Scierror(999, _("%s: Wrong size for input argument #%d: A scalar expected.\n"), _pstName.c_str(), i + 1);
241                     delete[] * _piDims;
242                     return false;
243             }
244         }
245
246         return true;
247     }
248
249     return false;
250 }
251
252 types::Double* trigo(types::Double* in, func_real func_r, func_complex func_c, bool forceComplex)
253 {
254     bool isComplex = in->isComplex() || forceComplex;
255     types::Double* out = new types::Double(in->getDims(), in->getDimsArray(), isComplex);
256
257     int size = in->getSize();
258     double* pInR = in->get();
259     double* pOutR = out->get();
260
261     if (isComplex)
262     {
263         double* pInI = in->getImg();
264         double* pOutI = out->getImg();
265         std::complex<double> d;
266         for (int i = 0; i < size; ++i)
267         {
268             d.real(pInR[i]);
269             d.imag(pInI[i]);
270             std::complex<double> res = func_c(d);
271             pOutR[i] = res.real();
272             pOutI[i] = res.imag();
273         }
274     }
275     else
276     {
277         for (int i = 0; i < size; ++i)
278         {
279             pOutR[i] = func_r(pInR[i]);
280         }
281     }
282
283     return out;
284 }
285
286 types::Function::ReturnValue zerosOrOnesFromValue(types::typed_list& in, int _iRetCount, types::typed_list& out, bool value)
287 {
288     int iDims = 0;
289     int* piDims = NULL;
290
291     static std::map<std::wstring, types::InternalType::ScilabType> mapOfTypes = {
292         {L"double", types::InternalType::ScilabDouble},
293         {L"constant", types::InternalType::ScilabDouble},
294         {L"boolean", types::InternalType::ScilabBool},
295         {L"uint8", types::InternalType::ScilabUInt8},
296         {L"int8", types::InternalType::ScilabInt8},
297         {L"uint16", types::InternalType::ScilabUInt16},
298         {L"int16", types::InternalType::ScilabInt16},
299         {L"uint32", types::InternalType::ScilabUInt32},
300         {L"int32", types::InternalType::ScilabInt32},
301         {L"uint64", types::InternalType::ScilabUInt64},
302         {L"int64", types::InternalType::ScilabInt64}
303     };
304
305     types::InternalType::ScilabType reftype = types::InternalType::ScilabDouble;
306     bool alloc = false;
307
308     int size = (int)in.size();
309     types::InternalType* it = in[size - 1];
310     if (size > 1 && it->isString())
311     {
312         // get optional type string
313         wchar_t* pType = it->getAs<types::String>()->get()[0];
314         auto f = mapOfTypes.find(pType);
315         if (f == mapOfTypes.end())
316         {
317             Scierror(999, _("%s: Wrong value for input argument #%d: Must be in the set {%s}"),
318                 value ? "ones" : "zeros", in.size(), "double, boolean, (u)int(8|16|32|64) ");
319             return types::Function::Error;
320         }
321
322         reftype = f->second;
323         in.pop_back();
324     }
325
326     bool ret = getDimsFromArguments(in, value ? "ones" : "zeros", &iDims, &piDims, &alloc);
327     if (ret == false)
328     {
329         switch (iDims)
330         {
331             case -1:
332                 Scierror(21, _("Invalid index.\n"));
333                 break;
334             case 1:
335             {
336                 //call overload
337                 return Overload::generateNameAndCall(value ? L"ones" : L"zeros", in, _iRetCount, out);
338             }
339         }
340
341         return types::Function::Error;
342     }
343
344     if (std::find(piDims, piDims+iDims, 0) != piDims+iDims)
345     {
346       // in Scilab, empty matrix is always a Double
347       reftype = types::InternalType::ScilabDouble;
348     }
349
350     switch (reftype)
351     {
352         case types::InternalType::ScilabInt8:
353         {
354             types::Int8* pOut = new types::Int8(iDims, piDims);
355             std::fill(pOut->get(), pOut->get() + pOut->getSize(), value);
356             out.push_back(pOut);
357             break;
358         }
359         case types::InternalType::ScilabInt16:
360         {
361             types::Int16* pOut = new types::Int16(iDims, piDims);
362             std::fill(pOut->get(), pOut->get() + pOut->getSize(), value);
363             out.push_back(pOut);
364             break;
365         }
366         case types::InternalType::ScilabInt32:
367         {
368             types::Int32* pOut = new types::Int32(iDims, piDims);
369             std::fill(pOut->get(), pOut->get() + pOut->getSize(), value);
370             out.push_back(pOut);
371             break;
372         }
373         case types::InternalType::ScilabInt64:
374         {
375             types::Int64* pOut = new types::Int64(iDims, piDims);
376             std::fill(pOut->get(), pOut->get() + pOut->getSize(), value);
377             out.push_back(pOut);
378             break;
379         }
380         case types::InternalType::ScilabUInt8:
381         {
382             types::UInt8* pOut = new types::UInt8(iDims, piDims);
383             std::fill(pOut->get(), pOut->get() + pOut->getSize(), value);
384             out.push_back(pOut);
385             break;
386         }
387         case types::InternalType::ScilabUInt16:
388         {
389             types::UInt16* pOut = new types::UInt16(iDims, piDims);
390             std::fill(pOut->get(), pOut->get() + pOut->getSize(), value);
391             out.push_back(pOut);
392             break;
393         }
394         case types::InternalType::ScilabUInt32:
395         {
396             types::UInt32* pOut = new types::UInt32(iDims, piDims);
397             std::fill(pOut->get(), pOut->get() + pOut->getSize(), value);
398             out.push_back(pOut);
399             break;
400         }
401         case types::InternalType::ScilabUInt64:
402         {
403             types::UInt64* pOut = new types::UInt64(iDims, piDims);
404             std::fill(pOut->get(), pOut->get() + pOut->getSize(), value);
405             out.push_back(pOut);
406             break;
407         }
408         case types::InternalType::ScilabBool:
409         {
410             types::Bool* pOut = new types::Bool(iDims, piDims);
411             std::fill(pOut->get(), pOut->get() + pOut->getSize(), value);
412             out.push_back(pOut);
413             break;
414         }
415         default: // other cases: create double with inherited dimensions only (not type)
416         case types::InternalType::ScilabDouble:
417         {
418             types::Double* pOut = new types::Double(iDims, piDims);
419             std::fill(pOut->get(), pOut->get() + pOut->getSize(), value);
420             out.push_back(pOut);
421             break;
422         }
423     }
424
425     if (alloc)
426     {
427         delete[] piDims;
428     }
429
430     return types::Function::OK;
431 }