## Copyright (C) 1996, 1998 Auburn University.  All rights reserved.
##
## This file is part of Octave.
##
## Octave 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 2, or (at your option) any
## later version.
##
## Octave 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 Octave; see the file COPYING.  If not, write to the Free
## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA.

## -*- texinfo -*-
## @deftypefn {Function File} {} sysappend (@var{sys}, @var{b}, @var{c}, @var{d}, @var{outname}, @var{inname}, @var{yd})
## appends new inputs and/or outputs to a system
##
## @strong{Inputs}
## @table @var
## @item sys
## system data structure
##
## @item b
## matrix to be appended to sys "B" matrix (empty if none)
##
## @item c
## matrix to be appended to sys "C" matrix (empty if none)
##
## @item d
## revised sys d matrix (can be passed as [] if the revised d is all zeros)
##
## @item outname
## list of names for new outputs
##
## @item inname
## list of names for new inputs
##
## @item yd
## binary vector; @math{yd(ii)=0} indicates a continuous output;
## @math{yd(ii)=1} indicates a discrete output.
## @end table
##
## @strong{Outputs} @var{sys}
## @example
## @group
##    sys.b := [sys.b , b]
##    sys.c := [sys.c  ]
##             [ c     ]
##    sys.d := [sys.d | D12 ]
##             [D21   | D22 ]
## @end group
## @end example
## where @math{D12}, @math{D21}, and @math{D22} are the appropriate dimensioned
## blocks of the input parameter @var{d}.
## @itemize @bullet
## @item The leading block @math{D11} of @var{d} is ignored.
## @item If @var{inname} and @var{outname} are not given as arguments,
##      the new inputs and outputs are be assigned default names.
## @item @var{yd} is a binary vector of length rows(c) that indicates
##      continuous/sampled outputs.  Default value for @var{yd} is:
##
## @item @var{sys} = continuous or mixed
## @var{yd} = @code{zeros(1,rows(c))}
##
## @item @var{sys} = discrete
## @var{yd} = @code{ones(1,rows(c))}
## @end itemize
## @end deftypefn

## Author: John Ingram <ingraje@eng.auburn.edu>
## Created: August 1996

function retsys = sysappend (sys, b, c, d, outname, inname, yd)

  sav_empty_list_elements_ok = empty_list_elements_ok;

  empty_list_elements_ok = 1;

  ## check input arguments
  if ( (nargin < 2) | (nargin > 7) | (!isstruct(sys)))
    usage("retsys = sysappend(sys,b,c[,d,outname,inname,yd]) ");
  elseif(!isstruct(sys))
    error("sys must be a system data structure");
  endif

  ## default system type must be state space form
  [Aa,Ab,Ac,Ad,Ats,Ann,Anz,Ast,Ain,Aout,Ayd] = sys2ss(sys);
  [Ann,Anz,Am,Ap] = sysdimensions(sys);

  ## default c
  if(nargin < 3)      c = [];                                endif

  ## default d
  if(nargin < 4)     make_d = 1;
  elseif(isempty(d)) make_d = 1;
  else               make_d = 0;                             endif
  if(make_d)         d = zeros(rows(c)+Ap,columns(b) + Am);  endif

  ## Append new input(s) if any
  Bm = max(columns(d),columns(b)+Am);
  if(Bm != Am)
    ## construct new signal names
    if(nargin >= 6)   # new names were passed
      if(!isstr(inname))
        error("inname must be a string");
      elseif(rows(inname) != (Bm - Am))
        error(sprintf("%d new inputs requested; inname(%dx%d)", ...
          (Bm-Am),rows(inname),columns(inname)));
      endif
    else
      inname = __sysdefioname__(Bm,"u",(Am+1));
    endif
    if(Am)   Ain = append(Ain,inname);
    else     Ain = inname;              endif

    ## default b matrix
    if(isempty(b))     b  = zeros(Ann+Anz,(Bm-Am));
    elseif(rows(b) != Ann+Anz | columns(b) != (Bm-Am))
        error(sprintf("b(%dx%d); should be (%dx%d)", rows(b), columns(b), ...
          (Ann+Anz), (Bm-Am)));
    endif

    ## append new b matrix
    Ab = [Ab,b];    # empty_list_elements_ok=1 makes this ok
  endif

  ## Append new output(s) if any
  Bp = max(rows(d),rows(c)+Ap);
  if(Bp != Ap)

    ## construct new signal names, output classification
    if(nargin >= 5)  # new names were passed
      if(!isstr(outname))
        error("outname must be a string");
      elseif(rows(outname) != (Bp - Ap))
        error(sprintf("%d new outputs requested; outname(%dx%d)", ...
          (Bp-Ap),rows(outname),columns(outname)));
      endif
    else
      outname = __sysdefioname__(Bp,"y",(Ap+1));
    endif
    if(Ap)   Aout = append(Aout,outname);
    else     Aout = outname;                endif

    ## construct new yd entries
    if(nargin == 7)
      if(!isvector(yd))
        error(sprintf("yd(%dx%d) must be a vector",rows(yd),columns(yd)))
      elseif(rows(c) != length(yd) & rows(d) != length(yd))
        error(sprintf("length(yd) = %d; c(%dx%d), d(%dx%d); mismatch", ...
          length(yd), rows(c), columns(c),rows(d),columns(d)));
      endif
    else
      ## default yd values
      yd = ones(1,Bp)*( (Ats > 0) & (Ann == 0)  & isempty(find(Ayd == 0)) ) ;
    endif
    Ayd = [vec(Ayd);vec(yd)];

    ## default c matrix
    if(isempty(c))      c = zeros((Bp-Ap),Ann+Anz);
    elseif(columns(c) != Ann+Anz | rows(c) != (Bp-Ap))
        error(sprintf("c(%dx%d); should be (%dx%d)", rows(c), columns(c), ...
          (Bp-Ap), (Ann+Anz) ));
    endif

    ## append new c matrix
    Ac = [Ac;c];    # empty_list_elements_ok=1 makes this ok
  endif

  ## check d matrix
  if(isempty(d)) d = zeros(Bp,Bm);
  elseif(rows(d) != Bp | columns(d) != Bm)
    error(sprintf("d(%dx%d) should be (%dx%d)",rows(d), columns(d), Bp, Bp));
  endif

  ## Splice in original D matrix
  if(Am & Ap)          d(1:Ap, 1:Am) = Ad;       endif
  Ad = d;

  ## construct return system
  retsys = ss2sys(Aa,Ab,Ac,Ad,Ats,Ann,Anz,Ast,Ain,Aout,find(Ayd == 1));

  empty_list_elements_ok = sav_empty_list_elements_ok;

endfunction
