[bug_14433] atanh fixed about double free
[scilab.git] / scilab / modules / elementary_functions / sci_gateway / cpp / sci_atanh.cpp
1 /*
2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2012 - DIGITEO - Cedric DELAMARRE
4 *
5  * Copyright (C) 2012 - 2016 - Scilab Enterprises
6  *
7  * This file is hereby licensed under the terms of the GNU GPL v2.0,
8  * pursuant to article 5.3.4 of the CeCILL v.2.1.
9  * This file was originally licensed under the terms of the CeCILL v2.1,
10  * and continues to be available under such terms.
11  * For more information, see the COPYING file which you should have received
12  * along with this program.
13 *
14 */
15 /*--------------------------------------------------------------------------*/
16
17 #include <complex>
18
19 #include "elem_func_gw.hxx"
20 #include "function.hxx"
21 #include "double.hxx"
22 #include "overload.hxx"
23 #include "configvariable.hxx"
24
25 extern "C"
26 {
27 #include "Scierror.h"
28 #include "localization.h"
29 #include "elem_common.h"
30 #include "sciprint.h"
31 }
32
33 /*
34 clear a;nb = 2500;a = rand(nb, nb);tic();atanh(a);toc
35 clear a;nb = 2500;a = rand(nb, nb); a = a + a *%i;tic();atanh(a);toc
36 */
37 /*--------------------------------------------------------------------------*/
38 types::Function::ReturnValue sci_atanh(types::typed_list &in, int _iRetCount, types::typed_list &out)
39 {
40     types::Double* pDblIn = NULL;
41     types::Double* pDblOut = NULL;
42
43     if (in.size() != 1)
44     {
45         Scierror(77, _("%s: Wrong number of input argument(s): %d expected.\n"), "atanh", 1);
46         return types::Function::Error;
47     }
48
49     if (_iRetCount > 1)
50     {
51         Scierror(78, _("%s: Wrong number of output argument(s): %d expected.\n"), "atanh", 1);
52         return types::Function::Error;
53     }
54
55     if (in[0]->isDouble())
56     {
57         pDblIn = in[0]->getAs<types::Double>();
58         double* pInR = pDblIn->get();
59         double* pInI = pDblIn->getImg();
60
61         int iSize = pDblIn->getSize();
62         bool bComplex = pDblIn->isComplex();
63         bool bAlreadyDisp = false;
64
65         if (bComplex == false)
66         {
67             // check values
68             for (int i = 0; i < iSize; i++)
69             {
70                 double dAbsIn = abs(pInR[i]);
71                 if (dAbsIn == 1)
72                 {
73                     if (ConfigVariable::getIeee() == 0)
74                     {
75                         if (pInI && pDblIn->isComplex() == false)
76                         {
77                             delete[] pInI;
78                         }
79
80                         Scierror(78, _("%s: Warning: Wrong value for input argument #%d : Singularity of the function.\n"), "atanh", 1);
81                         return types::Function::Error;
82                     }
83
84                     if (ConfigVariable::getIeee() == 1 && ConfigVariable::getWarningMode() && bAlreadyDisp == false)
85                     {
86                         bAlreadyDisp = true;
87                         sciprint(_("%s: Warning: Wrong value for input argument #%d : Singularity of the function.\n"), "atanh", 1);
88                     }
89                 }
90                 else if (dAbsIn > 1 && bComplex == false)
91                 {
92                     bComplex = true;
93                     pInI = new double[iSize];
94                     memset(pInI, 0x00, iSize * sizeof(double));
95                 }
96             }
97         }
98
99         pDblOut = new types::Double(pDblIn->getDims(), pDblIn->getDimsArray(), bComplex);
100         double* pOutR = pDblOut->get();
101         double* pOutI = pDblOut->getImg();
102
103         if (bComplex)
104         {
105             // using scilab 5 macro atanh is faster than std::atanh (08/2015)
106             // see comment a the begins of this gateway
107             for (int i = 0; i < iSize; i++)
108             {
109                 //zcoss(-pInI[i], pInR[i], &pOutR[i], &pOutI[i]);
110                 std::complex<double> c(pInR[i], pInI[i]);
111                 std::complex<double> d = std::atanh(c);
112
113                 pOutR[i] = d.real();
114                 pOutI[i] = d.imag();
115             }
116
117             if (pInI && pDblIn->isComplex() == false)
118             {
119                 delete[] pInI;
120             }
121         }
122         else
123         {
124             for (int i = 0; i < iSize; i++)
125             {
126                 pOutR[i] = std::atanh(pInR[i]);
127             }
128         }
129         out.push_back(pDblOut);
130     }
131     else
132     {
133         std::wstring wstFuncName = L"%" + in[0]->getShortTypeStr() + L"_atanh";
134         return Overload::call(wstFuncName, in, _iRetCount, out);
135     }
136
137     return types::Function::OK;
138 }
139 /*--------------------------------------------------------------------------*/