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 "clean.hxx"
24 #include "sparse.hxx"
25 #include "polynom.hxx"
26 
27 extern "C"
28 {
29 #include "Scierror.h"
30 #include "localization.h"
31 }
32 
33 /*--------------------------------------------------------------------------*/
sci_clean(types::typed_list & in,int _iRetCount,types::typed_list & out)34 types::Function::ReturnValue sci_clean(types::typed_list &in, int _iRetCount, types::typed_list &out)
35 {
36     types::Double* pDblOut      = NULL;
37     types::Polynom* pPolyOut    = NULL;
38     types::Sparse* pSparseOut   = NULL;
39 
40     double* pdReal  = NULL;
41     double* pdImg   = NULL;
42 
43     double dEpsR    = 1E-10;
44     double dEpsA    = 1E-10;
45 
46     int iSize       = 0;
47 
48     //Only for types::Sparse case
49     int* pRows = NULL;
50     int* pCols = NULL;
51 
52     if (in.size() < 1 || in.size() > 3)
53     {
54         Scierror(77, _("%s: Wrong number of input argument(s): %d to %d expected.\n"), "clean", 1, 3);
55         return types::Function::Error;
56     }
57 
58     if (_iRetCount > 1)
59     {
60         Scierror(78, _("%s: Wrong number of output argument(s): %d expected.\n"), "clean", 1);
61         return types::Function::Error;
62     }
63 
64     /***** get data *****/
65     if (in[0]->isDouble())
66     {
67         pDblOut = in[0]->getAs<types::Double>()->clone()->getAs<types::Double>();
68 
69         iSize = pDblOut->getSize();
70         pdReal = pDblOut->get();
71         if (pDblOut->isComplex())
72         {
73             pdImg = pDblOut->getImg();
74         }
75     }
76     else if (in[0]->isPoly())
77     {
78         types::Polynom* pPolyIn = in[0]->getAs<types::Polynom>();
79         iSize = pPolyIn->getSize();
80         pPolyOut = pPolyIn->clone()->getAs<types::Polynom>();
81     }
82     else if (in[0]->isSparse())
83     {
84         types::Sparse* pSparseIn = in[0]->getAs<types::Sparse>();
85         pSparseOut = new types::Sparse(pSparseIn->getRows(), pSparseIn->getCols());
86 
87         iSize = static_cast<int>(pSparseIn->nonZeros());
88         pRows = new int[iSize * 2];
89         pSparseIn->outputRowCol(pRows);
90         pCols = pRows + iSize;
91 
92         pdReal = new double[iSize];
93         if (pSparseIn->isComplex())
94         {
95             pSparseOut->toComplex();
96             pdImg  = new double[iSize];
97         }
98 
99         pSparseIn->outputValues(pdReal, pdImg);
100     }
101     else
102     {
103         std::wstring wstFuncName = L"%" + in[0]->getShortTypeStr() + L"_clean";
104         return Overload::call(wstFuncName, in, _iRetCount, out);
105     }
106 
107 
108     if (in.size() == 3)
109     {
110         if (in[2]->isDouble() == false)
111         {
112             Scierror(999, _("%s: Wrong type for input argument #%d : A real scalar expected.\n"), "clean", 3);
113             if (in[0]->isSparse())
114             {
115                 delete pSparseOut;
116                 delete[] pdReal;
117                 delete[] pRows;
118                 if (pdImg)
119                 {
120                     delete[] pdImg;
121                 }
122             }
123             return types::Function::Error;
124         }
125 
126         types::Double* pDbl = in[2]->getAs<types::Double>();
127 
128         if (pDbl->isScalar() == false || pDbl->isComplex())
129         {
130             Scierror(999, _("%s: Wrong type for input argument #%d : A real scalar expected.\n"), "clean", 3);
131             if (in[0]->isSparse())
132             {
133                 delete pSparseOut;
134                 delete[] pdReal;
135                 delete[] pRows;
136                 if (pdImg)
137                 {
138                     delete[] pdImg;
139                 }
140             }
141             return types::Function::Error;
142         }
143 
144         dEpsR = pDbl->get(0);
145     }
146 
147     if (in.size() >= 2)
148     {
149         if (in[1]->isDouble() == false)
150         {
151             Scierror(999, _("%s: Wrong type for input argument #%d : A real scalar expected.\n"), "clean", 2);
152             if (in[0]->isSparse())
153             {
154                 delete pSparseOut;
155                 delete[] pdReal;
156                 delete[] pRows;
157                 if (pdImg)
158                 {
159                     delete[] pdImg;
160                 }
161             }
162             return types::Function::Error;
163         }
164 
165         types::Double* pDbl = in[1]->getAs<types::Double>();
166 
167         if (pDbl->isScalar() == false || pDbl->isComplex())
168         {
169             Scierror(999, _("%s: Wrong type for input argument #%d : A real scalar expected.\n"), "clean", 2);
170             if (in[0]->isSparse())
171             {
172                 delete pSparseOut;
173                 delete[] pdReal;
174                 delete[] pRows;
175                 if (pdImg)
176                 {
177                     delete[] pdImg;
178                 }
179             }
180             return types::Function::Error;
181         }
182 
183         dEpsA = pDbl->get(0);
184     }
185 
186     /***** perform operation *****/
187     if (in[0]->isPoly())
188     {
189         for (int i = 0 ; i < iSize ; i++)
190         {
191             types::SinglePoly* pSP = pPolyOut->get(i);
192             clean(pSP->get(), pSP->getImg(), pSP->getSize(), dEpsA, dEpsR);
193         }
194     }
195     else
196     {
197         clean(pdReal, pdImg, iSize, dEpsA, dEpsR);
198     }
199 
200     /***** set result *****/
201     if (in[0]->isDouble())
202     {
203         out.push_back(pDblOut);
204     }
205     else if (in[0]->isPoly())
206     {
207         pPolyOut->updateRank();
208         out.push_back(pPolyOut);
209     }
210     else if (in[0]->isSparse())
211     {
212         if (pdImg)
213         {
214             for (int i = 0 ; i < iSize ; i++)
215             {
216                 std::complex<double> cplx = std::complex<double>(pdReal[i], pdImg[i]);
217                 pSparseOut->set(pRows[i] - 1, pCols[i] - 1, cplx, false);
218             }
219 
220             delete[] pdImg;
221         }
222         else
223         {
224             for (int i = 0 ; i < iSize ; i++)
225             {
226                 pSparseOut->set(pRows[i] - 1, pCols[i] - 1, pdReal[i], false);
227             }
228         }
229 
230         pSparseOut->finalize();
231 
232         delete[] pdReal;
233         delete[] pRows;
234         out.push_back(pSparseOut);
235     }
236 
237     return types::Function::OK;
238 }
239 /*--------------------------------------------------------------------------*/
240