Merge remote-tracking branch 'origin/master' into windows
[scilab.git] / scilab / modules / elementary_functions / sci_gateway / cpp / sci_abs.cpp
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2011 - DIGITEO - Antoine ELIAS
4  * Copyright (C) 2012 - DIGITEO - Cedric DELAMARRE
5  *
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 /*--------------------------------------------------------------------------*/
17
18 #include <cmath>
19
20 #include "elem_func_gw.hxx"
21 #include "api_scilab.hxx"
22 #include "function.hxx"
23 #include "overload.hxx"
24 #include "polynom.hxx"
25
26 extern "C"
27 {
28 #include "Scierror.h"
29 #include "localization.h"
30 #include "abs.h"
31 }
32
33 template <class T>
34 T* absInt(T* _pIn)
35 {
36     T* pIntOut = new T(_pIn->getDims(), _pIn->getDimsArray());
37     int size = _pIn->getSize();
38
39     typename T::type* pI = _pIn->get();
40     typename T::type* pO = pIntOut->get();
41     for (int i = 0; i < size; i++)
42     {
43         pO[i] = std::abs(pI[i]);
44     }
45
46     return pIntOut;
47 }
48 /*
49 clear a; nb = 2500; a = rand(nb, nb) - 0.5; tic(); abs(a); toc
50 clear a; nb = 2500; a = rand(nb, nb) - 0.5; a = a + a *%i; tic(); abs(a); toc
51 */
52 /*--------------------------------------------------------------------------*/
53 types::Function::ReturnValue sci_abs(types::typed_list &in, int _iRetCount, types::typed_list &out)
54 {
55     if (in.size() != 1)
56     {
57         Scierror(77, _("%s: Wrong number of input argument(s): %d expected.\n"), "abs", 1);
58         return types::Function::Error;
59     }
60
61     if (_iRetCount > 1)
62     {
63         Scierror(78, _("%s: Wrong number of output argument(s): %d expected.\n"), "abs", 1);
64         return types::Function::Error;
65     }
66
67     switch (in[0]->getType())
68     {
69         case types::InternalType::ScilabDouble:
70         {
71             api_scilab::Double* pDblIn = api_scilab::getAsDouble(in[0]);
72             api_scilab::Double* pDblOut = new api_scilab::Double(pDblIn->getDims(), pDblIn->getDimsArray());
73
74             double* pdblInR = pDblIn->get();
75             double* pdblInI = pDblIn->getImg();
76             double* pdblOut = pDblOut->get();
77             int size = pDblIn->getSize();
78             if (pDblIn->isComplex())
79             {
80                 for (int i = 0; i < size; i++)
81                 {
82                     if (ISNAN(pdblInR[i]))
83                     {
84                         pdblOut[i] = pdblInR[i];
85                     }
86                     else if (ISNAN(pdblInI[i]))
87                     {
88                         pdblOut[i] = pdblInI[i];
89                     }
90                     else
91                     {
92                         pdblOut[i] = dabsz(pdblInR[i], pdblInI[i]);
93                     }
94                 }
95             }
96             else
97             {
98                 for (int i = 0; i < size; i++)
99                 {
100                     if (ISNAN(pdblInR[i]))
101                     {
102                         pdblOut[i] = pdblInR[i];
103                     }
104                     else
105                     {
106                         pdblOut[i] = std::fabs(pdblInR[i]);
107                     }
108                 }
109             }
110
111             out.push_back(api_scilab::getReturnVariable(pDblOut));
112             delete pDblOut;
113             delete pDblIn;
114             break;
115         }
116         case types::InternalType::ScilabPolynom:
117         {
118             types::Polynom* pPolyIn = in[0]->getAs<types::Polynom>();
119             types::Polynom* pPolyOut = new types::Polynom(pPolyIn->getVariableName(), pPolyIn->getDims(), pPolyIn->getDimsArray());
120             double* data = NULL;
121
122             if (pPolyIn->isComplex())
123             {
124                 for (int i = 0; i < pPolyIn->getSize(); i++)
125                 {
126                     int rank = pPolyIn->get(i)->getRank();
127                     types::SinglePoly* pSP = new types::SinglePoly(&data, rank);
128
129                     for (int j = 0; j < rank + 1; j++)
130                     {
131                         data[j] = dabsz(pPolyIn->get(i)->get()[j], pPolyIn->get(i)->getImg()[j]);
132                     }
133
134                     pPolyOut->set(i, pSP);
135                     delete pSP;
136                     pSP = NULL;
137                 }
138             }
139             else
140             {
141                 for (int i = 0; i < pPolyIn->getSize(); i++)
142                 {
143                     int rank = pPolyIn->get(i)->getRank();
144                     types::SinglePoly* pSP = new types::SinglePoly(&data, rank);
145
146                     for (int j = 0; j < rank + 1; j++)
147                     {
148                         data[j] = dabss(pPolyIn->get(i)->get()[j]);
149                     }
150
151                     pPolyOut->set(i, pSP);
152                     delete pSP;
153                     pSP = NULL;
154                 }
155             }
156
157             out.push_back(pPolyOut);
158             break;
159         }
160         case types::InternalType::ScilabInt8:
161         {
162             out.push_back(absInt(in[0]->getAs<types::Int8>()));
163             break;
164         }
165         case types::InternalType::ScilabInt16:
166         {
167             out.push_back(absInt(in[0]->getAs<types::Int16>()));
168             break;
169         }
170         case types::InternalType::ScilabInt32:
171         {
172             out.push_back(absInt(in[0]->getAs<types::Int32>()));
173             break;
174         }
175         case types::InternalType::ScilabInt64:
176         {
177             out.push_back(absInt(in[0]->getAs<types::Int64>()));
178             break;
179         }
180         case types::InternalType::ScilabUInt8:
181         case types::InternalType::ScilabUInt16:
182         case types::InternalType::ScilabUInt32:
183         case types::InternalType::ScilabUInt64:
184         {
185             out.push_back(in[0]);
186             break;
187         }
188         default:
189         {
190             std::string stFuncName = "%" + in[0]->getShortTypeStr() + "_abs";
191             return Overload::call(stFuncName, in, _iRetCount, out);
192         }
193     }
194
195     return types::Function::OK;
196 }
197 /*--------------------------------------------------------------------------*/