2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2017 - ESI - Antoine ELIAS
5 * Copyright (C) 2012 - 2016 - Scilab Enterprises
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.
18 Copyright (C) 1996-2017 John W. Eaton
20 This file is part of Octave.
22 Octave is free software; you can redistribute it and/or modify it
23 under the terms of the GNU General Public License as published by
24 the Free Software Foundation; either version 3 of the License, or
25 (at your option) any later version.
27 Octave is distributed in the hope that it will be useful, but
28 WITHOUT ANY WARRANTY; without even the implied warranty of
29 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 GNU General Public License for more details.
32 You should have received a copy of the GNU General Public License
33 along with Octave; see the file COPYING. If not, see
34 <http://www.gnu.org/licenses/>.
38 // Based on Tony Richardson's filter.m.
40 // Originally translated to C++ by KH (Kurt.Hornik@wu-wien.ac.at)
41 // with help from Fritz Leisch and Andreas Weingessel on Oct 20, 1994.
43 // Rewritten to use templates to handle both real and complex cases by
44 // jwe, Wed Nov 1 19:15:29 1995.
46 #include "signal_gw.hxx"
48 #include "polynom.hxx"
49 #include "function.hxx"
50 #include "overload.hxx"
54 #include "sci_malloc.h"
55 #include "localization.h"
59 const char fname[] = "filter";
61 static void clean_filter(types::Double* a, bool alloc_a, types::Double* b, bool alloc_b)
74 static types::Double* filter(types::Double* b, types::Double* a, types::Double* x, types::Double* si)
79 int size_a = a->getSize();
80 int size_b = b->getSize();
82 int len = std::max(size_a, size_b);
84 int dims[2] = {1, len};
87 types::Double* new_a = a->resize(dims, 2)->getAs<types::Double>();
93 types::Double* new_b = b->resize(dims, 2)->getAs<types::Double>();
99 double* pa = new_a->get();
100 double* pb = new_b->get();
101 double* px = x->get();
107 clean_filter(new_a, alloc_a, new_b, alloc_b);
108 Scierror(999, _("%s: Wrong value for input argument #%d: First element must not be %s.\n"), fname, 2, "0");
112 int size_x = x->getSize();
114 int rows_si = si->getRows();
116 if (rows_si != len - 1)
118 clean_filter(new_a, alloc_a, new_b, alloc_b);
119 Scierror(999, "%s: first dimension of SI must be of length max (length (a), length (b)) - 1 (%d) (%d)", fname, rows_si, size_x);
125 clean_filter(new_a, alloc_a, new_b, alloc_b);
131 if (alloc_a == false)
133 new_a = new_a->clone();
136 if (alloc_b == false)
138 new_b = new_b->clone();
146 for (int i = 0; i < len; ++i)
153 if (size_a <= 1 && rows_si <= 0)
155 types::Double* ret = x->clone();
156 double* pret = ret->get();
157 int s = ret->getSize();
158 for (int i = 0; i < s; ++i)
163 clean_filter(new_a, alloc_a, new_b, alloc_b);
167 types::Double* y = new types::Double(x->getRows(), x->getCols());
169 double* py = y->get();
170 double* psi = si->get();
175 for (int i = 0; i < size_x; ++i)
177 py[i] = psi[0] + pb[0] * px[i];
178 for (int j = 0; j < rows_si - 1; ++j)
180 psi[j] = psi[j + 1] - pa[j + 1] * py[i] + pb[j + 1] * px[i];
183 psi[rows_si - 1] = pb[rows_si] * px[i] - pa[rows_si] * py[i];
188 for (int i = 0; i < size_x; ++i)
190 py[i] = psi[0] + pb[0] * px[i];
191 psi[0] = pb[rows_si] * px[i] - pa[rows_si] * py[i];
198 for (int i = 0; i < size_x; ++i)
200 py[i] = psi[0] + pb[0] * px[i];
204 for (int j = 0; j < rows_si - 1; j++)
206 psi[j] = psi[j + 1] + pb[j + 1] * px[i];
209 psi[rows_si - 1] = pb[rows_si] * px[i];
213 psi[0] = pb[1] * px[i];
219 clean_filter(new_a, alloc_a, new_b, alloc_b);
222 /*--------------------------------------------------------------------------*/
223 types::Function::ReturnValue sci_filter(types::typed_list &in, int _iRetCount, types::typed_list &out)
225 int iRhs = (int)in.size();
227 bool alloc_si = false;
228 types::Double* b = nullptr;
229 types::Double* a = nullptr;
230 types::Double* x = nullptr;
231 types::Double* si = nullptr;
233 if (iRhs < 3 || iRhs > 4)
235 Scierror(999, _("%s: Wrong number of input arguments: %d to %d expected.\n"), fname, 3, 4);
236 return types::Function::Error;
239 types::InternalType::ScilabId type_b = in[0]->getId();
240 types::InternalType::ScilabId type_a = in[1]->getId();
241 types::InternalType::ScilabId type_x = in[2]->getId();
242 types::InternalType::ScilabId type_si = types::InternalType::IdDouble;
246 type_si = in[3]->getId();
249 if (type_b != types::InternalType::IdDouble && type_b != types::InternalType::IdScalarDouble ||
250 type_a != types::InternalType::IdDouble && type_a != types::InternalType::IdScalarDouble ||
251 type_x != types::InternalType::IdDouble && type_x != types::InternalType::IdScalarDouble ||
252 type_si != types::InternalType::IdDouble && type_si != types::InternalType::IdScalarDouble)
254 return Overload::call(L"%_filter", in, _iRetCount, out);
257 b = in[0]->getAs<types::Double>();
258 a = in[1]->getAs<types::Double>();
259 x = in[2]->getAs<types::Double>();
263 si = in[3]->getAs<types::Double>();
268 int size_a = a->getSize();
269 int size_b = b->getSize();
270 int len = std::max(size_a, size_b) - 1;
271 int leadDim = x->getRows() == 1 ? 1 : 0;
273 int si_dims[2] = {x->getRows(), x->getCols()};
274 for (int i = leadDim; i > 0; i--)
276 si_dims[i] = si_dims[i - 1];
281 si = new types::Double(2, si_dims);
285 if (b->isVector() == false)
287 Scierror(999, _("%s: Wrong size for input argument #%d: Vector expected.\n"), fname, 1);
288 return types::Function::Error;
291 if (a->isVector() == false)
293 Scierror(999, _("%s: Wrong size for input argument #%d: Vector expected.\n"), fname, 2);
294 return types::Function::Error;
297 if (x->isVector() == false)
299 Scierror(999, _("%s: Wrong size for input argument #%d: Vector expected.\n"), fname, 3);
300 return types::Function::Error;
303 if (iRhs > 3 && si->isVector() == false)
305 Scierror(999, _("%s: Wrong size for input argument #%d: Vector expected.\n"), fname, 4);
306 return types::Function::Error;
309 types::Double* ret = filter(b, a, x, si);
310 if (_iRetCount != 2 && alloc_si)
317 return types::Function::Error;
325 return types::Function::OK;