## Copyright (C) 2007 R.G.H. Eschauzier <reschauzier@yahoo.com>
##
## This program is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free Software
## Foundation; either version 3 of the License, or (at your option) any later
## version.
##
## This program is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
## details.
##
## You should have received a copy of the GNU General Public License along with
## this program; if not, see <http://www.gnu.org/licenses/>.

## Adapted by Carnë Draug on 2011 <carandraug+dev@gmail.com>

## This function is necessary for impinvar and invimpinvar of the signal package

## Inverse of Octave residue function
function [b_out, a_out] = inv_residue(r_in, p_in, k_in, tol)

  n = length(r_in); % Number of poles/residues

  k = 0; % Capture contstant term
  if (length(k_in)==1)    % A single direct term (order N = order D)
    k = k_in(1);          % Capture constant term
  elseif (length(k_in)>1) % Greater than one means non-physical system
    error("Order numerator > order denominator");
  endif

  a_out = poly(p_in);

  b_out  = zeros(1,n+1);
  b_out += k*a_out; % Constant term: add k times denominator to numerator
  i=1;
  while (i<=n)
    term   = [1 -p_in(i)];               % Term to be factored out
    p      = r_in(i)*deconv(a_out,term); % Residue times resulting polynomial
    p      = prepad(p, n+1, 0, 2);       % Pad for proper length
    b_out += p;

    m          = 1;
    mterm      = term;
    first_pole = p_in(i);
    while (i<n && abs(first_pole-p_in(i+1))<tol) % Multiple poles at p(i)
       i++; %Next residue
       m++;
       mterm  = conv(mterm, term);              % Next multiplicity to be factored out
       p      = r_in(i) * deconv(a_out, mterm); % Resulting polynomial
       p      = prepad(p, n+1, 0, 2);           % Pad for proper length
       b_out += p;
    endwhile
  i++;
  endwhile
endfunction
