summaryrefslogtreecommitdiff
path: root/macros/residued.sci
blob: cbcbebc92c97a15d379a22f361051d3d93b78962 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
// Copyright (C) 2018 - IIT Bombay - FOSSEE
//
// This file must be used under the terms of the CeCILL.
// This source file is licensed as described in the file COPYING, which
// you should have received as part of this distribution.  The terms
// are also available at
// http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
// Author:[insert name]
// Organization: FOSSEE, IIT Bombay
// Email: toolbox@scilab.in

//  Function File [r, p, f, m] = residued (b, a)
// Compute the partial fraction expansion (PFE) of filter
// H(z) = B(z)/A(z).  In the usual PFE function coderesiduez, the
// IIR part (poles p and residues r) is driven in parallel
// with the FIR part (f).  In this variant, the IIR part is driven by
// the output of the FIR part.  This structure can be more accurate in
// signal modeling applications.
//
// INPUTS:
// b and a are vectors specifying the digital filter
// H(z) = B(z)/A(z).
//NOTE that the polynomials 'b' and 'a' should have real coefficients(because of the function 'filter' used in polyval)
//
// RETURNED:
//
//  r = column vector containing the filter-pole residues
//  p = column vector containing the filter poles
//  f = row vector containing the FIR part, if any
//  m = column vector of pole multiplicities
//
//
// Test cases:
//1.
//B=[1 1 ]; A=[1 -2 1];
// [r,p,f,m] = residued(B,A);
//r =
//  -1
//   2
//p =
//   1
//   1
//
//f = [](0x0)
//e =
//   1
//   2
//2.
//B=[6,2]; A=[1 -2 1];
//[r,p,k,e]=residued(B,A)
//m  =
//    1.
//    2.
// f  =[]
// p  =
//    1.
//    1.
// r  =
//  - 2.
//    8.
//

function [r, p, f, m] = residued(b, a, toler)

  // RESIDUED - return residues, poles, and FIR part of B(z)/A(z)
  //
  // Let nb = length(b), na = length(a), and N=na-1 = no. of poles.
  // If nb<na, then f will be empty, and the returned filter is
  //
  //             r(1)                      r(N)
  // H(z) = ----------------  + ... + ----------------- = R(z)
  //        [ 1-p(1)/z ]^e(1)         [ 1-p(N)/z ]^e(N)
  //
  // This is the same result as returned by RESIDUEZ.
  // Otherwise, the FIR part f will be nonempty,
  // and the returned filter is
  //
  // H(z) = f(1) + f(2)/z + f(3)/z^2 + ... + f(nf)/z^M + R(z)/z^M
  //
  // where R(z) is the parallel one-pole filter bank defined above,
  // and M is the order of F(z) = length(f)-1 = nb-na.
  //
  // Note, in particular, that the impulse-response of the parallel
  // (complex) one-pole filter bank starts AFTER that of the the FIR part.
  // In the result returned by RESIDUEZ, R(z) is not divided by z^M,
  // so its impulse response starts at time 0 in parallel with f(n).
  //
[nargout,nargin]=argn();

  if nargin==3,
    warning("tolerance ignored");
  end
  NUM = b(:)';
  DEN = a(:)';
  nb = length(NUM);
  na = length(DEN);
  f = [];
  if na<=nb
    f = filter(NUM,DEN,[1,zeros(nb-na)]);
    NUM = NUM - conv(DEN,f);
    NUM = NUM(nb-na+2:$);
  end
  [r,p,f2,m] = residuez(NUM,DEN);
  if f2
       error('f2 not empty as expected');
       end

endfunction