changeset 3213:ba1c7cdc6090

[project @ 1998-11-06 16:15:36 by jwe]
author jwe
date Fri, 06 Nov 1998 16:16:31 +0000
parents bf61c443a366
children 8cc04ca5b4ca
files scripts/control/DEMOcontrol.m scripts/control/abcddim.m scripts/control/abcddims.m scripts/control/analdemo.m scripts/control/are.m scripts/control/axis2dlim.m scripts/control/bddemo.m scripts/control/bode.m scripts/control/bode_bounds.m scripts/control/bodquist.m scripts/control/buildssic.m scripts/control/c2d.m scripts/control/com2str.m scripts/control/controldemo.m scripts/control/ctrb.m scripts/control/d2c.m scripts/control/damp.m scripts/control/dare.m scripts/control/dcgain.m scripts/control/demomarsyas.m scripts/control/dezero.m scripts/control/dgkfdemo.m scripts/control/dgram.m scripts/control/dhinfdemo.m scripts/control/dlqe.m scripts/control/dlqg.m scripts/control/dlqr.m scripts/control/dlyap.m scripts/control/dmr2d.m scripts/control/fir2sys.m scripts/control/frdemo.m scripts/control/freqchkw.m scripts/control/freqresp.m scripts/control/gram.m scripts/control/h2norm.m scripts/control/h2syn.m scripts/control/hinf_ctr.m scripts/control/hinfdemo.m scripts/control/hinfnorm.m scripts/control/hinfsyn.m scripts/control/hinfsyn_chk.m scripts/control/impulse.m scripts/control/is_abcd.m scripts/control/is_controllable.m scripts/control/is_detectable.m scripts/control/is_dgkf.m scripts/control/is_digital.m scripts/control/is_observable.m scripts/control/is_sample.m scripts/control/is_siso.m scripts/control/is_stabilizable.m scripts/control/is_stable.m scripts/control/jet707.m scripts/control/lqe.m scripts/control/lqg.m scripts/control/lqr.m scripts/control/lsim.m scripts/control/ltifr.m scripts/control/mb.m scripts/control/minfo.m scripts/control/moddemo.m scripts/control/nichols.m scripts/control/nyquist.m scripts/control/obsv.m scripts/control/ord2.m scripts/control/outlist.m scripts/control/packedform.m scripts/control/packsys.m scripts/control/parallel.m scripts/control/pinv.m scripts/control/place.m scripts/control/polyout.m scripts/control/prompt.m scripts/control/pzmap.m scripts/control/qzval.m scripts/control/rldemo.m scripts/control/rlocus.m scripts/control/rotg.m scripts/control/run_cmd.m scripts/control/series.m scripts/control/sortcom.m scripts/control/ss2sys.m scripts/control/ss2tf.m scripts/control/ss2zp.m scripts/control/starp.m scripts/control/step.m scripts/control/stepimp.m scripts/control/strappend.m scripts/control/susball.m scripts/control/swap.m scripts/control/swapcols.m scripts/control/swaprows.m scripts/control/sys2fir.m scripts/control/sys2ss.m scripts/control/sys2tf.m scripts/control/sys2zp.m scripts/control/sysadd.m scripts/control/sysappend.m scripts/control/syschnames.m scripts/control/syschnamesl.m scripts/control/syschtsam.m scripts/control/sysconnect.m scripts/control/syscont.m scripts/control/syscont_disc.m scripts/control/sysdefioname.m scripts/control/sysdefstname.m scripts/control/sysdimensions.m scripts/control/sysdisc.m scripts/control/sysdup.m scripts/control/sysgetsignals.m scripts/control/sysgettsam.m scripts/control/sysgettype.m scripts/control/sysgroup.m scripts/control/sysgroupn.m scripts/control/sysmult.m scripts/control/sysout.m scripts/control/sysprune.m scripts/control/sysreorder.m scripts/control/sysrepdemo.m scripts/control/sysscale.m scripts/control/syssub.m scripts/control/sysupdate.m scripts/control/tf2ss.m scripts/control/tf2sys.m scripts/control/tf2sysl.m scripts/control/tf2zp.m scripts/control/tfout.m scripts/control/tzero.m scripts/control/tzero2.m scripts/control/ugain.m scripts/control/unpacksys.m scripts/control/wgt1o.m scripts/control/zgfmul.m scripts/control/zgfslv.m scripts/control/zginit.m scripts/control/zgpbal.m scripts/control/zgreduce.m scripts/control/zgrownorm.m scripts/control/zgscal.m scripts/control/zgsgiv.m scripts/control/zgshsr.m scripts/control/zp2ss.m scripts/control/zp2ssg2.m scripts/control/zp2sys.m scripts/control/zp2tf.m scripts/control/zpout.m
diffstat 146 files changed, 15882 insertions(+), 622 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/DEMOcontrol.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,58 @@
+# Copyright (C) 1996 A. Scottedward Hodel
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+function DEMOcontrol()
+# Controls toolbox demo.
+# Demo programs: bddemo.m, frdemo.m, analdemo.m, moddmeo.m, rldemo.m
+#  
+# Written by David Clem August 15, 1994
+# $Revision: 1.2 $    
+
+  disp(' O C T A V E    C O N T R O L   S Y S T E M S   T O O L B O X')
+
+  while (1)
+    clc
+    k = 0;
+    while (k > 8 || k < 1),
+      k = menu("Octave Controls System Toolbox Demo", ...
+	'System representation', ...
+    	'Block diagram manipulations ', ...
+    	'Frequency response functions ', ...
+    	'State space analysis functions ', ...
+    	'Root locus functions ', ...
+	'LQG/H2/Hinfinity functions ', ...
+    	'End');
+
+    endwhile
+    if(k == 1)
+      sysrepdemo
+    elseif (k == 2)
+      bddemo
+    elseif (k == 3)
+      frdemo
+    elseif (k == 4)
+      analdemo
+    elseif (k == 5)
+      rldemo
+    elseif (k == 6)
+      dgkfdemo
+    elseif (k == 7)
+      return
+    endif
+  endwhile
+endfunction
--- a/scripts/control/abcddim.m	Thu Nov 05 04:24:46 1998 +0000
+++ b/scripts/control/abcddim.m	Fri Nov 06 16:16:31 1998 +0000
@@ -1,71 +1,121 @@
-## Copyright (C) 1996, 1997 John W. Eaton
-##
-## 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-1307, USA.
-
-## Usage: [n, m, p] = abcddim (a, b, c, d)
-##
-## Check for compatibility of the dimensions of the matrices defining
-## the linear system (a, b, c, d).
-##
-## Returns n = number of system states,
-##         m = number of system inputs,
-##         p = number of system outputs.
-##
-## Returns n = m = p = -1 if the system is not compatible.
-
-## Author: A. S. Hodel <scotte@eng.auburn.edu>
-## Created: August 1993
-## Adapted-By: jwe
+# Copyright (C) 1993, 1994, 1995 John W. Eaton
+# 
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA.
 
 function [n, m, p] = abcddim (a, b, c, d)
 
+# Usage: [n, m, p] = abcddim (a, b, c, d)
+#
+# Check for compatibility of the dimensions of the matrices defining
+# the linear system (a, b, c, d).
+#
+# Returns n = number of system states,
+#         m = number of system inputs,
+#         p = number of system outputs.
+#
+# Note: n = 0 (pure gain block) is returned without warning.
+#
+# Returns n = m = p = -1 if the system is not compatible.
+#
+# See also: is_abcd
+
+# Written by A. S. Hodel (scotte@eng.auburn.edu) August 1993.
+# a s hodel: modified to accept pure-gain systems aug 1996
+# $Revision: 1.15 $
+# $Log: abcddim.m,v $
+# Revision 1.15  1998-11-06 16:15:36  jwe
+# *** empty log message ***
+#
+# Revision 1.1.1.1  1998/05/19 20:24:05  jwe
+#
+# Revision 1.4  1997/12/01 16:44:22  scotte
+# *** empty log message ***
+#
+# Revision 1.3  1997/02/12 15:38:14  hodel
+# *** empty log message ***
+#
+#
+# fixed typo
+#
+# Revision 1.1  1997/02/12 11:34:53  hodel
+# Initial revision
+#
+# Revision 1.7  1997/02/07 15:29:56  scotte
+# fixed is_square check to allow for empty a matrix
+# (this allows for pure gain blocks)
+#
+
   if (nargin != 4)
-    error ("usage: abcddim (a, b, c, d)");
+    error ("abcddim: four arguments required");
   endif
 
   n = m = p = -1;
 
-  [an, am] = size(a);
-  if (an != am)
-    error ("abcddim: a is not square");
+  [a,an,am] = abcddims(a);
+  [b,bn,bm] = abcddims(b);
+  [c,cn,cm] = abcddims(c);
+  [d,dn,dm] = abcddims(d);
+
+  if ( (!is_square(a)) & (!isempty(a)) )
+    warning (["abcddim: a is not square (",num2str(an),"x",num2str(am),")"]);
+    return
   endif
 
-  [bn, bm] = size(b);
-  if (bn != am)
-    error ("abcddim: a and b are not compatible");
+  if( (bm == 0) & (dm == 0) )
+    warning("abcddim: no inputs");
+  elseif (bn != am)
+    warning (["abcddim: a(",num2str(an),"x",num2str(am), ...
+      " and b(",num2str(bn),"x",num2str(bm),") are not compatible"]);
+    return
   endif
 
-  [cn, cm] = size(c);
-  if (cm != an)
-    error ("abcddim: a and c are not compatible");
+  if( (cn == 0) & (dn == 0 ) )
+    warning("abcddim: no outputs");
+  elseif (cm != an)
+    warning (["abcddim: a(",num2str(an),"x",num2str(am), ...
+	" and c(",num2str(cn),"x",num2str(cm),") are not compatible"]);
+    return
   endif
 
-  [dn, dm] = size(d);
-  if (cn != dn)
-    error ("abcddim: c and d are not compatible");
+  have_connections = (bn*cn != 0);
+
+  if( (dn == 0) & have_connections)
+    warning("abcddim: empty d matrix passed; setting compatibly with b, c");
+    [d,dn,dm] = abcddims(zeros(cn,bm));
   endif
 
-  if (bm != dm)
-    error ("abcddim: b and d are not compatible");
+  if(an > 0)
+    [dn, dm] = size(d);
+    if ( (cn != dn) & have_connections )
+      warning (["abcddim: c(",num2str(cn),"x",num2str(cm), ...
+	" and d(",num2str(dn),"x",num2str(dm),") are not compatible"]);
+      return
+    endif
+
+    if ( (bm != dm) & have_connections )
+      warning (["abcddim: b(",num2str(bn),"x",num2str(bm), ...
+	  " and d(",num2str(dn),"x",num2str(dm),") are not compatible"]);
+      return
+    endif
+
+    m = bm;
+    p = cn;
+  else
+    [p,m] = size(d);
   endif
-
   n = an;
-  m = bm;
-  p = cn;
-
 endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/abcddims.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,34 @@
+# Copyright (C) 1993, 1994, 1995 John W. Eaton
+# 
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+function [y,my,ny] = abcddims (x)
+
+# Usage: [y,my,ny] = abcddims (x)
+#
+# Used internally in abcddim.  If x is a zero-size matrix, both dimensions
+# get set to 0.  my and ny are the row and column dimensions of the result.
+
+# Written by A. S. Hodel (scotte@eng.auburn.edu) Feb 1997
+# $Revision: 1.1.1.1 $
+
+  y = x;
+  if(isempty(y))
+    y = [];
+  endif
+  [my,ny] = size(y);
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/analdemo.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,238 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function analdemo()
+# Octave Controls toolbox demo: State Space analysis demo
+# Written by David Clem August 15, 1994
+# Updated by John Ingram December 1996
+# $Revision: 1.4 $
+  
+  while (1)
+    clc
+    k=0;
+    while(k > 8 || k < 1)
+      k = menu("Octave State Space Analysis Demo", ...
+        "System grammians (gram, dgram)", ...
+        "System zeros (tzero)", ...
+        "Continuous => Discrete and Discrete => Continuous conversions (c2d,d2c)", ...
+	"Algebraic Riccati Equation (are, dare)", ...
+  	"Balanced realizations (balreal, dbalreal)", ...
+  	"Open loop truncations via Hankel singular values (balreal, dbalreal)", ...
+        "SISO pole placement", ...
+        "Return to main demo menu");
+    endwhile
+    if (k == 1)
+      clc
+      help dgram
+      prompt
+
+      clc 
+      disp("System Grammians: (see Moore, IEEE T-AC, 1981) \n");
+      disp("Example #1, consider the discrete time state space system:\n");
+      a=[1 5 -8.4;1.2 -3 5;1 7 9]
+      b=[1 5;2 6;-4.4 5]
+      c=[1 -1.5 2;6 -9.8 1]
+      d=0
+      prompt
+      disp("\nThe discrete controllability grammian is computed as follows:");
+      cmd = "grammian = dgram(a, b);";
+      run_cmd;
+      disp("Results:\n");
+      grammian = dgram(a,b)
+      disp("Variable Description:\n");
+      disp("grammian => discrete controllability grammian");
+      disp("a, b => a and b matrices of discrete time system\n");
+      disp("A dual approach may be used to compute the observability grammian.");
+      prompt
+      clc
+
+      help gram
+      prompt
+      clc
+
+      disp("Example #2, consider the continuous state space system:\n");
+      a=[1 3 -10.2;3.7 -2 9;1 3 7]
+      b=[1 12;6 2;-3.8 7]
+      c=[1 -1.1 7;3 -9.8 2]
+      d=0
+      prompt
+      disp("\nThe continuous controllability grammian is computed as follows:");
+      cmd = "grammian = gram(a, b);";
+      run_cmd;
+      disp("Results:\n");
+      grammian = gram(a,b)
+      disp("Variable Description:\n");
+      disp("grammian => continuous controllability grammian");
+      disp("a, b => a and b matrices of continuous time system\n");
+      disp("A dual approach may be used to compute the observability grammian.");
+      prompt
+      clc
+
+      
+    elseif (k == 2)
+      clc
+      help tzero
+      prompt
+
+      disp("System zeros (tzero) example\n");
+      disp("Example #1, consider the state space system:\n");
+      a=[0 1 0;-10 -2 0;-10 0 -8]
+      b=[0;1;9]
+      c=[-10 0 -4]
+      d=1
+      prompt
+      disp("\nTo compute the zeros of this system, enter the following command:\n");
+      cmd = "zer = tzero(a,b,c,d);";
+      run_cmd;
+      disp("Results:\n");
+      zer = tzero(a,b,c,d)
+      disp("Variable Description:\n");
+      disp("zer => zeros of state space system");
+      disp("a, b, c, d => state space system used as input argument");
+      prompt
+      clc
+
+      disp("Example #2, consider the state space system from example 1 again:");
+      cmd = "sys = ss2sys(a,b,c,d);";
+      disp(cmd);
+      eval(cmd);
+      sysout(sys);
+      disp("\nThe zeros of this system can also be calculated directly from the");
+      disp("system variable:");
+      cmd = "zer = tzero(sys);";
+      run_cmd;
+      disp("Results:\n")
+      zer = tzero(sys)
+      disp("Variable Description:\n");
+      disp("zer => zeros of state space system");
+      disp("sys => state space system used as input argument");
+      prompt
+      clc
+
+    elseif (k == 3)
+      clc
+      help c2d
+      prompt
+
+      clc
+      disp("Continuous => Discrete and Discrete => Continuous conversions (c2d,d2c)");
+      disp("\nExample #1, consider the following continuous state space system");
+      cmd = "sys_cont = ss2sys([-11 6;-15 8], [1;2], [2 -1], 0);";
+      eval(cmd);
+      disp(cmd);
+      disp("Examine the poles and zeros of the continuous system:");
+      sysout(sys_cont,"all");
+      disp("\nTo convert this to a discrete system, a sampling time is needed:");
+      cmd = "Tsam = 0.5;";
+      run_cmd;
+      disp("\nNow convert to a discrete system with the command:");
+      cmd = "sys_disc = c2d(sys_cont,Tsam);";
+      run_cmd;
+      disp("Examine the poles and zeros of the discrete system:");
+      sysout(sys_disc,"all");
+      prompt
+      clc
+
+      disp("\nNow we will convert the discrete system back to a continuous system");
+      disp("using the d2c command:");
+      help d2c
+      prompt
+      cmd = "new_sys_cont = d2c(sys_disc);";
+      run_cmd;
+      disp("\nExamine the poles and zeros of the discrete system:");
+      sysout(new_sys_cont,"all");
+      prompt
+
+    elseif (k == 4)
+      clc
+      help are
+      prompt
+      clc
+
+      disp("Algebraic Riccati Equation (are, dare)");
+
+      disp("\nExample #1, consider the continuous state space system:\n");
+      a=[1 3 -10.2;3.7 -2 9;1 3 7]
+      b=[1 12;6 2;-3.8 7]
+      c=[1 -1.1 7;3 -9.8 2]
+      d=0
+      prompt
+      disp("\nThe solution to the continuous algebraic riccati equation");
+      disp("is computed as follows:");
+      cmd = "x_cont = are(a, b, c);";
+      run_cmd;
+      disp("Results:\n")
+      x_cont = are(a,b,c)
+      disp("Variable Description:\n")
+      disp("x_cont => solution to the continuous algebraic riccati equation");
+      disp("a, b, c => a, b, and c matrices of continuous time system\n");
+      prompt
+
+      clc
+      help dare
+      prompt
+      clc
+
+      disp("Example #2, consider the discrete time state space system:\n");
+      a=[1 5 -8.4;1.2 -3 5;1 7 9]
+      b=[1 5;2 6;-4.4 5]
+      c=[1 -1.5 2;6 -9.8 1]
+      d=0
+      r=eye(columns(b))
+      prompt
+      disp("\nThe solution to the continuous algebraic riccati equation");
+      disp("is computed as follows:");
+      cmd = "x_disc = dare(a, b, c, r);";
+      run_cmd;
+      disp("Results:\n")
+      x_disc = dare(a,b,c,r)
+      disp("Variable Description:\n");
+      disp("x_disc => solution to the discrete algebraic riccati equation");
+      disp("a, b, c => a, b and c matrices of discrete time system\n");
+      prompt
+      clc
+
+    elseif (k == 5)
+      disp("--- Balanced realization: not yet implemented")
+    elseif (k == 6)
+      disp("--- Open loop balanced truncation: not yet implemented")
+    elseif (k == 7)
+      disp("SISO pole placement example:")
+      cmd = "sys=tf2sys(1,[1 -2 1]);";
+      run_cmd
+      disp("System in zero-pole form is:")
+      cmd = "sysout(sys,\"zp\");";
+      run_cmd
+      disp("and in state space form:")
+      cmd = "sysout(sys,\"ss\");";
+      run_cmd
+      disp("Desired poles at -1, -1");
+      cmd = "K=place(sys,[-1 -1])";
+      run_cmd
+      disp("Check results:")
+      cmd = "[A,B] = sys2ss(sys);";
+      run_cmd
+      cmd = "poles=eig(A-B*K)";
+      run_cmd
+      prompt
+    elseif (k == 8)
+      return
+    endif
+  endwhile  
+endfunction
+
--- a/scripts/control/are.m	Thu Nov 05 04:24:46 1998 +0000
+++ b/scripts/control/are.m	Fri Nov 06 16:16:31 1998 +0000
@@ -1,44 +1,42 @@
-## Copyright (C) 1996, 1997 John W. Eaton
-##
-## 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-1307, USA.
-
-## Usage: x = are (a, b, c {,opt})
-##
-## Solves algebraic riccati equation
-##
-##   a' x + x a - x b x + c = 0
-##
-## for identically dimensioned square matrices a, b, c.  If b (c) is not
-## square, then the function attempts to use b * b' (c' * c) instead.
-##
-## Solution method: apply Laub's Schur method (IEEE Trans. Auto. Contr,
-## 1979) to the appropriate Hamiltonian matrix.
-##
-## opt is an option passed to the eigenvalue balancing routine default is "B".
-##
-## See also: balance
-
-## Author: A. S. Hodel <scotte@eng.auburn.edu>
-## Created: August 1993
-## Adapted-By: jwe
+# Copyright (C) 1993, 1994, 1995 John W. Eaton
+# 
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA.
 
 function x = are (a, b, c, opt)
 
+# Usage: x = are (a, b, c {,opt})
+#
+# Solves algebraic riccati equation
+#
+#   a' x + x a - x b x + c = 0
+#
+# for identically dimensioned square matrices a, b, c.  If b (c) is not
+# square, then the function attempts to use b * b' (c' * c) instead.
+#
+# Solution method: apply Laub's Schur method (IEEE Trans. Auto. Contr,
+# 1979) to the appropriate Hamiltonian matrix.
+#
+# opt is an option passed to the eigenvalue balancing routine default is "B".
+#
+# See also: balance
+
+# Written by A. S. Hodel (scotte@eng.auburn.edu) August 1993.
+# $Revision: 1.18 $
+
   if (nargin == 3 || nargin == 4)
     if (nargin == 4)
       if (! (strcmp (opt, "N") || strcmp (opt, "P") ...
@@ -73,11 +71,11 @@
       error ("are: a, b, c not conformably dimensioned.");
     endif
 
-    ## Should check for controllability/observability here
-    ## use Boley-Golub (Syst. Contr. Letters, 1984) method, not the
-    ##
-    ##                     n-1
-    ## rank ([ B A*B ... A^   *B]) method
+# Should check for controllability/observability here
+# use Boley-Golub (Syst. Contr. Letters, 1984) method, not the
+#
+#                     n-1
+# rank ([ B A*B ... A^   *B]) method 
 
     [d, h] = balance ([a, -b; -c, -a'], opt);
     [u, s] = schur (h, "A");
@@ -86,7 +84,7 @@
     n2 = 2 * n;
     x = u (n1:n2, 1:n) / u (1:n, 1:n);
   else
-    usage ("x = are (a, b, c)");
+    usage ("x = are (a, b, c)")
   endif
 
 endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/axis2dlim.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,57 @@
+# Copyright (C) 1998 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+
+function axvec = axis2dlim(axdata)
+# function axvec = axis2dlim(axdata)
+# determine axis limits for 2-d data; leaves a 10% margin around the plots.
+# puts in margins of +/- 0.1 if data is one dimensional (or a single point)
+# inputs:
+#   axdata: nx2 matrix of data [x,y]
+# outputs:
+#   vector of axis limits appropriate for call to axis() function
+ 
+  if(isempty(axdata))
+    axdata = 0;
+  endif
+
+  # compute axis limits
+  minv = min(axdata);
+  maxv = max(axdata);
+  delv = (maxv-minv)/2;      # breadth of the plot
+  midv = (minv + maxv)/2;    # midpoint of the plot
+  axmid = [midv(1), midv(1), midv(2), midv(2)];
+  axdel = [-0.1, 0.1,-0.1,0.1];   # default plot width (if less than 2-d data)
+  if(max(delv) == 0)
+    if(midv(1) != 0)
+      axdel(1:2) = [-0.1*midv(1),0.1*midv(1)];
+    endif
+    if(midv(2) != 0)
+      axdel(3:4) = [-0.1*midv(2),0.1*midv(2)];
+    endif
+  else
+    # they're at least one-dimensional
+    if(delv(1) != 0)
+      axdel(1:2) = 1.1*[-delv(1),delv(1)];
+    endif
+    if(delv(2) != 0)
+      axdel(3:4) = 1.1*[-delv(2),delv(2)];
+    endif
+  endif
+  axvec = axmid + axdel; 
+endfunction
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/bddemo.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,622 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function bddemo()
+# Octave Controls toolbox demo: Block Diagram Manipulations demo
+# Written by David Clem August 15, 1994
+# Modified by A S Hodel Summer-Fall 1996
+
+# Revision 1.6  1998/05/05 17:02:45  scotte
+# updated May 5 by Kai Meuller
+#
+# Revision 1.2  1998/05/05  13:21:51  mueller
+# buildssic command description
+# buildssic example added
+#
+# Revision 1.1  1998/05/05  13:20:26  mueller
+# Initial revision
+#
+ 
+  str_sav = implicit_str_to_num_ok;
+  sav_page = page_screen_output;
+  implicit_str_to_num_ok = 1;
+  page_screen_output = 1;
+
+  while (1)
+    clc
+    k=0;
+    while(k > 14 || k < 1)
+      k = menu("Octave Block Diagram Manipulations Demo", ...
+  	"sysadd/syssub: F(s) = G(s) +/- H(s)", ...
+ 	"sysappend: add new inputs/outputs", ...
+	"syschnames: change names of inputs, outputs, and/or states", ...
+	"sysconnect: connect specified system inputs/outputs", ...
+	"syscont/sysdisc: extract the continuous (discrete) part of a system", ...
+	"sysdup: duplicate specified inputs/outputs", ...
+	"sysgroup: group two systems into a single system,", ...
+	"sysmult: F(s) = G(s)*H(s) (series connection)", ...
+	"sysprune: keep only specified inputs/outputs", ...
+	"sysscale: scale inputs/outputs by specified gain matrices", ...
+	"parallel: parallel connection of two systems", ...
+	"buildssic: the combination of all", ...
+	"Design examples:", ...
+	"Return to main demo menu");
+    endwhile
+    if (k == 1)
+      clc
+      disp("sysadd: add two systems together")
+      disp("syssub: subtract F = G - H")
+      prompt
+      help sysadd
+      prompt
+      help syssub
+      prompt
+      disp('Example #1, \n')
+      cmd = "sys1 = tf2sys([1 -1],[1 2 1]);";
+      run_cmd
+      cmd = "sys2 = tf2sys([1 -1],[1 2 3]);";
+      run_cmd
+      disp("sys1=")
+      sysout(sys1);
+      prompt
+      disp("sys2=")
+      sysout(sys2);
+      cmd = "sys_sum1 = sysadd(sys1,sys1);";
+      run_cmd
+      disp("This example adds sys1 to itself.")
+      cmd = "sysout(sys_sum1)";
+      run_cmd
+      disp("Notice that the numerator is twice what it used to be.")
+      prompt
+      disp("Example 2:")
+      cmd = "sys_sub1 = syssub(sys1,sys2);";
+      run_cmd
+      disp("Notice that sysadd (actually sysgroup, called by sysadd) lets you")
+      disp("know that your two systems had identical names for their states,")
+      disp("inputs and outputs.  The warning message is perfectly harmless,")
+      disp("and is provided for user information only.")
+      disp("sys_sub1=")
+      sysout(sys_sub1)
+      disp("Notice that, since the two transfer functions had different")
+      disp("denominators, syssub converted the primary system type to ")
+      disp("state space.  This is the typical behavior unless the")
+      disp("the two systems are both SISO, they both have the same poles,")
+      disp("and at least one of them has  tf for its primary system type.");
+      prompt
+    elseif (k == 2)
+      disp("sysappend: add new inputs and/or outputs to a system")
+      help sysappend
+      prompt
+      disp("Consider a double-integrator system:")
+      sys = tf2sys(1,[1 0 0]);
+      sys=sysupdate(sys,"ss");
+      sysout(sys,"ss");
+      disp("We add a velocity disturbance input as follows:")
+      cmd = "sys1=sysappend(sys,[1;0]);";
+      run_cmd
+      sysout(sys1,"ss");
+      disp("Names of inputs can be included as follows:")
+      cmd = "sys1=sysappend(sys,[1;0], [],[],[],\"Disturb\");";
+      run_cmd
+      disp("Notice that empty matrices can be listed for the D matrix if")
+      disp("all entries are zeros.")
+      disp(" ")
+      disp("sys1 is thus:")
+      sysout(sys1);
+      prompt
+    elseif (k == 3)
+      disp("syschnames:")
+      help syschnames
+      disp("Example system");
+      a = rand(3,3);
+      b = rand(3,2);
+      c = rand(2,3);
+      sys = ss2sys(a,b,c);
+      sysout(sys);
+      prompt
+      disp("Change state names to larry, moe, and curly as follows:")
+      sys = syschnames(sys,"st",1:3,["larry";"moe  " ; "curly"]);
+      cmd = "sys = syschnames(sys,\"st\",1:3,[\"larry\";\"moe  \" ; \"curly\"]);";
+      run_cmd
+      disp("Indicate that output 2 is discrete-time:")
+      cmd = "sys = syschnames(sys,\"yd\",2,1);";
+      run_cmd
+      disp("Resulting system is:")
+      sysout(sys);
+      prompt
+    elseif (k == 4)
+      help sysconnect
+      prompt
+      disp("********* N O T E *********")
+      disp("sysconnect is demonstrated fully in the design examples (option 13)");
+      prompt
+    elseif (k == 5)
+      disp("syscont and sysdisc: ")
+      disp("Example block diagram 1:")
+      disp("        ------------------     ---------------------");
+      disp(" u_in ->| Discrete system |--->| Continuous system | ---> y_out");
+      disp("        ------------------     ---------------------");
+      sys1 = tf2sys([1 2],[1 2 1], 1,"u_in","y_disc");
+      sys2 = tf2sys([1 0],[1 -3 -2],0,"c_in","y_out");
+      sys = sysmult(sys2,sys1);
+      disp("Consider the hybrid system")
+      sysout(sys);
+      prompt
+      help syscont
+      disp("The continuous part of the system can be extracted with syscont")
+      cmd = "[csys,Acd,Ccd] = syscont(sys);";
+      run_cmd
+      disp("The resulting csys is")
+      sysout(csys);
+      disp("Notice that B is 0; there is no purely continuous path from the")
+      disp("input to the output");
+      prompt
+      help sysdisc
+      disp("The discrete part of the system can be extracted with sysdisc")
+      cmd = "[dsys,Adc,Cdc] = sysdisc(sys)";
+      run_cmd
+      disp("The resulting dsys is")
+      sysout(dsys);
+      disp("sysdisc returns dsys=empty since sys has no discrete outputs.");
+      prompt
+      disp("Example block diagram 2:")
+      sys1 = tf2sys([1 2],[1 2 1], 1,"u_in","y_disc");
+      sys2 = tf2sys([1 0],[1 -3 -2],0,"c_in","y_out");
+      disp("             ---------------------")
+      disp(" u_in -->o-->| Discrete system   | --------> y_disc")
+      disp("         ^   ---------------------    |")  
+      disp("         |                            | ");
+      disp("         -----------------------------|---")
+      disp("                                      |  |")
+      disp("         ------------------------------  |")
+      disp("         |                               |")
+      disp("         v   ---------------------       |")
+      disp(" c_in -->o-->| continuous system | --------> y_out")
+      disp("             ---------------------")
+      disp("repeat the above example with sys=")
+      sys = sysgroup(sys1, sys2);
+      sysout(sys)
+      prompt
+      sys = sysconnect(sys,[1 2],[2 1]);
+      sysout(sys);
+      cmd = "[csys,Acd,Bcd] = syscont(sys);";
+      run_cmd
+      cmd = "[dsys,Acd,Bcd] = sysdisc(sys);";
+      run_cmd
+      disp("csys is now")
+      sysout(csys)
+      disp("dsys is now")
+      sysout(dsys);
+      prompt
+    elseif (k == 6)
+      help sysdup
+      prompt
+      disp("********* N O T E *********")
+      disp("sysdup is fully demonstrated in the design examples (option 13)")
+      prompt
+    elseif (k == 7)
+      help sysgroup
+      disp(" ")
+      prompt
+      disp("Example: combine two SISO systems together:")
+      cmd = "sys_a=tf2sys([1 2],[3 4]);";
+      run_cmd
+      cmd = "sys_b=tf2sys([5 6],[7 8],1);";
+      run_cmd
+      cmd = "sys_g=sysgroup(sys_a,sys_b);";
+      run_cmd
+      disp("Notice that sysgroup warns you when you join a purely continuous")
+      disp("system to a purely discrete system.  sysgroup also warns when")
+      disp("you join two systems that have common state, input, or output names.")
+      cmd = "sysout(sys_g)";
+      run_cmd
+      disp("Since the grouped system is a multiple-input multiple-output system,")
+      disp("the output system is by default in state-space format.")
+      disp(" ")
+      disp("********* N O T E *********")
+      disp("sysgroup is further demonstrated in the design examples (option 13)")
+      prompt
+    elseif (k == 8)
+      help sysmult
+      disp("sysmult performs a series connection of two systems.")
+      disp("Example 1")
+      disp(" ")
+      disp("         ----------     ----------")
+      disp("   u --->|  Bsys  |---->|  Asys  |---> y")
+      disp("         ----------     ----------")
+      disp(" ")
+      Asys = tf2sys(1,[1 2 1],0,"a_in","a_out");
+      Bsys = tf2sys([2 3],[1 3 2],0,"b_in","b_out");
+      disp("Asys=")
+      sysout(Asys);
+      disp("Bsys=");
+      sysout(Bsys);
+      cmd = "sys = sysmult(Asys,Bsys);";
+      run_cmd
+      disp("sys =")
+      sysout(sys);
+      disp("Notice that sysmult automatically transforms to state space")
+      disp("internal representation.  This is to avoid numerical problems")
+      disp("when multiplying polynomials");
+      prompt
+      disp("Example 2: same system, except that Bsys is discrete-time");
+      Bsys = tf2sys([2 3],[1 3 2],1e-2,"b_in","b_out");
+      sysout(Bsys);
+      cmd = "sys = sysmult(Asys,Bsys);";
+      run_cmd
+      disp("sys =")
+      sysout(sys);
+      prompt
+    elseif (k == 9)
+      help sysprune
+      prompt
+      disp("********* N O T E *********")
+      disp("sysprune is demonstrated in the design examples (option 13)");
+      prompt
+    elseif (k == 10)
+      help sysscale
+      disp(" ")
+      prompt
+      disp("********* N O T E *********")
+      disp("See the design examples (option 13) for use of sysscale.")
+      prompt
+    elseif ( k == 11)
+      help parallel
+      disp("parallel operates by making a call to sysgroup and sysscale.")
+      disp("Example:")
+      sys1 = tf2sys(1,[1 1],0,"in1","out1");
+      sys2 = tf2sys(2,[1 2],0,"in2","out2");
+      disp("sys1=")
+      sysout(sys1);
+      disp("sys2=")
+      sysout(sys2);
+      cmd = "sysp = parallel(sys1,sys2);";
+      run_cmd
+      disp("sysp=")
+      sysout(sysp);
+      prompt
+      disp("parallel can be used for multiple input systems as well:")
+
+      in1 = ["u1.1";"u1.2"];
+      in2 = ["u2.1";"u2.2"];
+      out1 = ["y1.1";"y1.2"];
+      out2 = ["y2.1";"y2.2"];
+
+      sys1 = ss2sys([-1,0;0 -2],eye(2),eye(2),[]);
+      sys2 = ss2sys([-2,0;0 -4],eye(2),eye(2),[]);
+
+      sys1 = syschnames(sys1,"in",1:2,in1);
+      sys1 = syschnames(sys1,"out",1:2,out1);
+
+      sys2 = syschnames(sys2,"in",1:2,in2);
+      sys2 = syschnames(sys2,"out",1:2,out2);
+     
+      disp("sys1=")
+      sysout(sys1);
+      disp("sys2=")
+      sysout(sys2);
+      cmd = "sysp = parallel(sys1,sys2);";
+      run_cmd
+      disp("sysp=")
+      sysout(sysp);
+      prompt
+    elseif (k == 12)
+      # buildssic description
+      disp(" ")
+      disp("        ---------------------------------------")
+      disp("                    b u i l d s s i c")
+      disp("          (BUILD State Space InterConnections)")
+      disp("        ---------------------------------------")
+      disp(" ")
+      disp("buildssic builds a single system from up to 8 systems.")
+      disp("It's primary pupose is the forming of interconnections")
+      disp("for H2/H_inf designs and the building of closed loop")
+      disp("systems.")
+      disp("The interconnections may be of arbitrary complexity.")
+      disp("The use of buildssic is an alternative to sysgroup,")
+      disp("sysadd/syssub, sysappend, sysconnect, sysdup, sysmult")
+      disp("sysprune, sysscale, parallel etc.")
+      disp("In contrast to these functions buildssic does not")
+      disp("handle mixed continuous and discrete systems. However,")
+      disp("discrete systems can be connected as long as their")
+      disp("sampling times are identical. Another drawback: the")
+      disp("names of input/output and state variables are clobbered.")
+      disp("Of course, buildsysic is useful in combination with sysgroup,")
+      disp("sysmult etc.")
+      prompt
+      disp("********* N O T E *********")
+      disp("buildssic is demonstrated in the design examples (option 13)");
+      prompt
+    elseif (k == 13)
+      disp("Design examples")
+      disp("Packed system matrices may be connected and manipulated")
+      disp("With the functions listed below:")
+      disp("  sysdup: duplicate selected inputs/outputs")
+      disp("  sysconnect: connect selected inputs/outputs")
+      disp("  sysgroup: group two systems together")
+      disp("  sysprune: prune a system to keep only selected inputs and outputs")
+      disp("  sysscale:pre/post multiply a system by constant matrices")
+      disp("  buildssic: connect systems with arbitrary complexity.")
+      prompt
+      disp("As a simple example, we will construct the system block ")
+      disp("diagram shown below ")
+      disp(" ")
+      disp("         +          --------    --------");
+      disp("  r(t) ---> (+) --->| K(s) |--->| P(s) | ----> y(t)");
+      disp("            -^      --------    --------  |");
+      disp("             |                            |");
+      disp("             ------------------------------");
+      disp(" ")
+      disp("where P(s) is the plant, K(s) is the controller.")
+      prompt
+      disp("Simple example: P(s) is a first order lag, K(s) is a PI ")
+      disp("controller")
+      nump = 1;
+      denp = [1  1];
+      disp("P(s)=")
+      tfout(nump,denp)
+      numk = [1 1];
+      denk = [1 0];
+      disp("\nK(s)=")
+      tfout(numk,denk);
+      prompt
+      disp("We'll show three approaches.  ")
+      P = tf2sys(nump,denp,0,"plant input","plant output");
+      K = tf2sys(numk, denk,0,"controller input","controller output");
+
+      meth = 0;
+      while(meth != 5)
+        disp("The first method consists of the following steps:")
+        disp("   step 1: create systems P and K")
+        disp("   step 2: group P and K together")
+        disp("   step 3: create a summing junction")
+        disp("   step 4: connect outputs to respective inputs")
+        disp("   step 5: prune the desired i/o connections")
+        disp("The second method is done as follows:")
+        disp("   step 1: create systems P and K and a summing block S")
+        disp("   step 2: connect P, K, and S in series")
+        disp("   step 3: connect y to inverted summing connection")
+        disp("   step 4: prune the desired i/o connections")
+        disp("The third method uses buildssic:")
+        disp("   step 1: GW = buildssic(...,K,P)")
+        disp(" ")
+        disp("Other design examples are in dgkfdemo (controldemo option 7)")
+        disp(" ")
+        meth = menu("Select design example method", ...
+		"Method 1 ", ...
+		"Method 1 (w/o algebraic loop warning)", ...
+		"Method 2", ...
+		"Method 3", ...
+		"Exit design examples");
+        if(meth == 1)
+          disp(" * * * Method 1 * * *")
+          disp(" ")
+          disp("         +          --------    --------");
+          disp("  r(t) ---> (+) --->| K(s) |--->| P(s) | ----> y(t)");
+          disp("            -^      --------    --------  |");
+          disp("             |                            |");
+          disp("             ------------------------------");
+          disp(" ")
+          disp("Step 1: put plants in system format:");
+          nump
+          denp
+          cmd =  "P = tf2sys(nump,denp,0,""plant input"",""plant output"");";
+          run_cmd
+          disp("P=")
+          sysout(P)
+          prompt
+          numk
+          denk
+          cmd = "K = tf2sys(numk, denk,0,""controller input"",""controller output"");";
+          run_cmd
+          sysout(K)
+          prompt
+          disp("Step 2: group the systems together")
+          cmd = "PK = sysgroup(P,K);";
+          run_cmd
+          disp("PK=")
+          sysout(PK);
+          prompt
+          disp(" ")
+          disp("                           y2   u1")
+          disp("         +          --------    --------");
+          disp("  r(t) ---> (+) --->| K(s) |--->| P(s) | ----> y(t)");
+          disp("  u2        -^      --------    --------    |  y1");
+          disp("          u3 |                              |");
+          disp("             --------------------------------");
+          disp(" ")
+          disp("The controller has two inputs summed together, r(t)")
+          disp("and the negative feedback of  y(t)")
+          disp("Step 3a: duplicate controller input: (input 2 of PK)")
+          prompt
+          cmd = "PK = sysdup(PK,[],2);";
+          run_cmd
+          disp("PK=")
+          sysout(PK);
+          disp("Notice that PK now has three inputs (input 3 is a duplicate ");
+          prompt("of input 2).  Press return to go on")
+          disp("Step 3b: scale input 3 by -1")
+          cmd = "PK = sysscale(PK,[],diag([1,1,-1]));";
+          run_cmd
+          disp("PK=")
+          sysout(PK);
+          prompt
+          disp("Step 4: connect:")
+          disp("   y(t) (output 1) to the negative sum junction (input 3)")
+          disp("   u(t) (output 2) to plant input (input 1)")
+          disp("and prune extraneous inputs/outputs (retain input 2, output 1)")
+          prompt
+          out_connect = [1 2]
+          in_connect = [3 1]
+          cmd = "PK0 = sysconnect(PK,out_connect,in_connect);"; 
+          run_cmd
+          prompt
+          disp("Notice that sysconnect detects the possibility of algebraic") 
+          disp("connections when connecting inputs.  Option 2 (Method 1 ")
+          disp("without algebraic loops) shows how to avoid this warning")
+          disp("by performing connections one at a time.")
+          prompt
+          disp("PK0=")
+          sysout(PK0);
+          disp("Notice that the connected inputs now have stars on their")
+          disp("names.  This is how the Octave controls toolbox reminds you")
+          disp("that the loop has been closed around these inputs.")
+          prompt("Press return to prune extra inputs/outputs from system")
+          disp("Only keep plant output (output 1) and r(t) (input 2)")
+          cmd = "PK0 = sysprune(PK0,1,2);";
+          run_cmd
+          disp("PK0=")
+          sysout(PK0);
+          prompt
+          disp("The resulting closed-loop transfer function is obtained as follows:")
+          cmd = "[num,den] = sys2tf(PK0);";
+          run_cmd
+          prompt
+          disp("Transfer function is now")
+          tfout(num,den)
+          disp("You can check this: Pk0=PK/(1+PK), as expected")
+          prompt
+        elseif(meth == 2)
+          disp("Method 1 without algebraic loops")
+          disp(" ")
+          disp("                           y2   u1")
+          disp("         +          --------    --------");
+          disp("  r(t) ---> (+) --->| K(s) |--->| P(s) | ----> y(t)");
+          disp("  u2        -^      --------    --------    |  y1");
+          disp("          u3 |                              |");
+          disp("             --------------------------------");
+          disp(" ")
+          disp("Recall that sysconnect checks for algebraic loops.  Although")
+          disp("Design option 1 gets a warning message about a possible");
+ 	  disp("algebraic loop, such a loop does not exist.")
+          disp("This can be seen by performing the connections one at a time");
+          cmd = "PK = sysgroup(P,K);";
+          run_cmd
+          disp("PK=")
+          sysout(PK);
+          disp("Create an additial inverted input to the controller.")
+          cmd = "PK = sysdup(PK,[],2);";
+          run_cmd
+          cmd = "PK = sysscale(PK,[],diag([1,1,-1]));";
+          run_cmd
+          disp("PK=")
+          sysout(PK);
+          disp("Connect controller to plant:")
+          cmd = "PK0 = sysconnect(PK,2,1);"; 
+          run_cmd
+          disp("Plant output to negative control input")
+          cmd = "PK0 = sysconnect(PK0,1,3);"; 
+          run_cmd
+          disp("Only keep plant output (output 1) and r(t) (input 2)")
+          cmd = "PK0 = sysprune(PK0,1,2);";
+          run_cmd
+          disp("PK0=")
+          sysout(PK0);
+          prompt
+          disp("The transfer function form of PK0 is:")
+          sysout(PK0,"tf");
+          prompt
+        elseif(meth == 3)
+          disp(" * * * Method 2 * * *")
+          disp(" ")
+          disp("         +          --------    --------");
+          disp("  r(t) ---> (+) --->| K(s) |--->| P(s) | ----> y(t)");
+          disp("            -^      --------    --------  |");
+          disp("             |                            |");
+          disp("             ------------------------------");
+          disp(" ")
+      disp("Step 1: We've already created systems P and K.  Create a sum ")
+      disp("block as follows:")
+      implicit_str_to_num_ok = "warn";
+      cmd = "S = ss2sys([],[],[],[1 -1],0,0,0,[],[""r(t)"";""y(t)""],""e(t)"");";
+      run_cmd
+      implicit_str_to_num_ok = 1;
+      disp("You may avoid the string conversion warning by setting the ")
+      disp("Octave global variables implicit_str_to_num_ok = 1");
+      disp(" ");
+      disp("(You may wish to look at help ss2sys to see what the above does)");
+      disp("S=")
+      sysout(S)
+      disp("notice that this is just a gain block that outputs e = r - y")
+      prompt
+      disp("Step 2: series connections of P, K, and S")
+      cmd = "PKS = sysmult(P,sysmult(K,S));";
+      run_cmd
+      disp("PKS=")
+      sysout(PKS)
+      disp("Step 3: connect y to inverted input")
+      cmd = "PKcl = sysconnect(PKS,1,2);";
+      run_cmd
+      disp("PKcl=")
+      sysout(PKcl)
+      disp("Step 4: prune desired inputs/outputs")
+      cmd = "PKcl=sysprune(PKcl,1,1);";
+      run_cmd
+      disp("PKcl=")
+      sysout(PKcl)
+      prompt
+        elseif(meth == 4)
+          disp(" * * * Method 3 * * *")
+          disp(" ")
+          disp("         +          --------    --------");
+          disp("  r(t) ---> (+) --->| K(s) |--->| P(s) | ----> y(t)");
+          disp("            -^      --------    --------  |");
+          disp("             |                            |");
+          disp("             ------------------------------");
+          disp(" ")
+      disp("Step 1: We've already created systems P and K.")
+      disp("        Let us call buildssic:")
+      disp("   PKcl = buildssic([1 2;2 -1],[],[1],[2],P,K)")
+      disp(" ")
+      disp("                         ^      ^  ^   ^  ^ ^")
+      disp("                         |      |  |   |  | |")
+      disp("     Connection list ----+      |  |   |  | |")
+      disp(" internal input list -----------+  |   |  | +-- controller")
+      disp("         output list --------------+   |  |")
+      disp("          input list ------------------+  +---- plant")
+      disp(" ")
+      disp(" Connection list: connect input 1 (P) with output 2 (K)")
+      disp("                  connect input 2 (K) with neg. outp. 1 (P)")
+      disp(" ")
+      disp("  int. inp. list: do not append internal inputs")
+      disp("                  (e.g. the internal input of K (r-y))")
+      disp(" ")
+      disp("     output list: the only output is 1 (P), positive")
+      disp(" ")
+      disp("      input list: the only input is 2 (K), positive")
+      disp(" ")
+      cmd = "PKcl = buildssic([1 2;2 -1],[],[1],[2],P,K);"
+      run_cmd
+      sysout(PKcl)
+      prompt
+      disp("The transfer function form of PKcl is:")
+      sysout(PKcl,"tf");
+      disp("You can check this: PKcl = PK / (1 + PK), as expected")
+      prompt
+      elseif(meth != 5)
+        disp("Illegal selection")
+     endif
+    endwhile
+      
+    elseif (k == 14)
+      return
+    endif
+  endwhile  
+  implict_str_to_num_ok = str_sav;
+  page_screen_output = sav_page;
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/bode.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,180 @@
+# Copyright (C) 1996,1998 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [mag,phase,w] = bode(sys,w,outputs,inputs)
+# [mag,phase,w] = bode(sys[,w,outputs,inputs])
+# Produce Bode plots of a system
+#
+# Compute the frequency response of a system.
+# inputs:
+#   sys: system data structure (must be either purely continuous or discrete;
+#	 see is_digital)
+#   w: frequency values for evaluation.
+#      if sys is continuous, then bode evaluates G(jw)
+#      if sys is discrete, then bode evaluates G(exp(jwT)), where T=sys.tsam
+#         (the system sampling time)
+#      default: the default frequency range is selected as follows: (These
+#        steps are NOT performed if w is specified)
+#          (1) via routine bodquist, isolate all poles and zeros away from
+#              w=0 (jw=0 or exp(jwT)=1) and select the frequency
+#             range based on the breakpoint locations of the frequencies.
+#          (2) if sys is discrete time, the frequency range is limited
+#              to jwT in [0,2p*pi]
+#          (3) A "smoothing" routine is used to ensure that the plot phase does
+#              not change excessively from point to point and that singular
+#              points (e.g., crossovers from +/- 180) are accurately shown.
+#   outputs, inputs: the indices of the output(s) and input(s) to be used in
+#     the frequency response; see sysprune.
+# outputs:
+#    mag, phase: the magnitude and phase of the frequency response
+#       G(jw) or G(exp(jwT)) at the selected frequency values.
+#    w: the vector of frequency values used
+# If no output arguments are given, bode plots the results to the screen.
+# Descriptive labels are automatically placed.  See xlabel, ylable, title,
+# and replot.
+#
+# Note: if the requested plot is for an MIMO system, mag is set to
+# ||G(jw)|| or ||G(exp(jwT))|| and phase information is not computed.
+
+# Written by John Ingram  July 10th, 1996
+# Based on previous code
+# By R. Bruce Tenison, July 13, 1994
+# Modified by David Clem November 13, 1994
+# again by A. S. Hodel July 1995 (smart plot range, etc.)
+# Modified by Kai P. Mueller September 28, 1997 (multiplot mode)
+# $Revision: 1.6 $
+# $Log: bode.m,v $
+# Revision 1.6  1998/09/04 20:57:18  hodelas
+# fixed bodquist bug (use reshape instead of  transpose); removed extraneous
+# output from bode.
+#
+# Bodquist is now much faster
+#
+# Revision 1.4  1998/08/24 15:50:03  hodelas
+# updated documentation
+#
+# Revision 1.3  1998/08/13 20:11:27  hodelas
+# Added calls to axis2dlim for flat-plots
+#
+# Revision 1.2  1998/07/24 18:16:51  hodelas
+# rewrote bodquist as a function call.  nyquist interactive plot now optional
+#
+# Revision 1.1.1.1  1998/05/19 20:24:05  jwe
+#
+# Revision 1.7  1998/02/09 13:04:11  scotte
+# fixed oneplot/gset nokey to function only if gnuplot_has_multiplot
+#
+# Revision 1.6  1997/12/01 16:51:50  scotte
+# updated by Mueller 27 Nov 97
+#
+# Revision 1.2  1997/11/24  18:53:01  mueller
+# gset autoscale prevents the following error message:
+#    line 0: x range must be greater than 0 for log scale!
+# gset nokey and call to oneplot() added
+#
+# Revision 1.1  1997/11/11  17:31:27  mueller
+# Initial revision
+#
+
+  # check number of input arguments given
+  if (nargin < 1 | nargin > 4)
+    usage("[mag,phase,w] = bode(sys[,w,outputs,inputs])");
+  endif
+  if(nargin < 2)
+    w = [];
+  endif
+  if(nargin < 3)
+    outputs = [];
+  endif
+  if(nargin < 4)
+    inputs = [];
+  endif
+
+  [f, w] = bodquist(sys,w,outputs,inputs,"bode");
+
+  [stname,inname,outname] = sysgetsignals(sys);
+  systsam = sysgettsam(sys);
+
+  # Get the magnitude and phase of f.
+  mag = abs(f);
+  phase = arg(f)*180.0/pi;
+
+  if (nargout < 1),
+    # Plot the information
+    if(gnuplot_has_multiplot)
+      oneplot();
+    endif
+    gset autoscale;
+    if(gnuplot_has_multiplot)
+      gset nokey;
+    endif
+    clearplot();
+    gset data style lines;
+    if(is_digital(sys))
+      xlstr = ["Digital frequency w=rad/sec.  pi/T=",num2str(pi/systsam)];
+      tistr = "(exp(jwT)) ";
+    else
+      xlstr = "Frequency in rad/sec";
+      tistr = "(jw)";
+    endif
+    xlabel(xlstr);
+    ylabel("Gain in dB");
+    if(is_siso(sys))
+      if (gnuplot_has_multiplot)
+        subplot(2,1,1);
+      endif
+      title(["|[Y/U]",tistr,"|, u=", inname, ...
+	", y=",outname]);
+    else
+      title([ "||Y(", tistr, ")/U(", tistr, ")||"]);
+      disp("MIMO plot from")
+      outlist(inname,"	");
+      disp("to")
+      outlist(outname,"	");
+    endif
+    wv = [min(w), max(w)];
+    md = 20*log10(mag);
+
+    axvec = axis2dlim([vec(w),vec(md)]);
+    axvec(1:2) = wv;
+    axis(axvec);
+    grid("on");
+    semilogx(w,md);
+    if (is_siso(sys))
+      if (gnuplot_has_multiplot)
+        subplot(2,1,2);
+      else
+        prompt('Press any key for phase plot');
+      endif
+      axvec = axis2dlim([vec(w),vec(phase)]);
+      axvec(1:2) = wv;
+      axis(axvec);
+      xlabel(xlstr);
+      ylabel("Phase in deg");
+      title([ "phase([Y/U]", tistr, ...
+	 "), u=", (inname),", y=",(outname)]);
+      grid("on");
+      semilogx(w,phase);
+      # This should be the default for subsequent plot commands.
+      if(gnuplot_has_multiplot)
+        oneplot();
+      endif
+    endif
+    mag = phase = w = [];
+  endif
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/bode_bounds.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,87 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [wmin,wmax] = bode_bounds(zer,pol,DIGITAL,tsam)
+# function [wmin,wmax] = bode_bounds(zer,pol,DIGITAL{,tsam})
+# get default range of frequencies for system zeros and poles
+#
+# frequency range is the interval [10^wmin,10^wmax]
+#
+# used internally in freqresp
+
+# $Revision: 1.4 $
+# $Log: bode_bounds.m,v $
+# Revision 1.4  1998/10/05 17:12:56  hodelas
+# various bug changes
+#
+# Revision 1.2  1998/08/18 21:21:19  hodelas
+# updated for simpler interface
+#
+#
+# Revision 1.2  1997/11/24  15:39:38  mueller
+# floating overflow on digital systems fixed
+# The overflow occurs if the system has poles or zeros at 0 (log(0)/tsamp)
+#
+# Revision 1.1  1997/11/24  15:36:31  mueller
+# Initial revision
+#
+
+  # make sure zer,pol are row vectors
+  if(!isempty(pol)) pol = reshape(pol,1,length(pol)); endif
+  if(!isempty(zer)) zer = reshape(zer,1,length(zer)); endif
+
+# check for natural frequencies away from omega = 0
+  if (DIGITAL)
+    # The 2nd conditions prevents log(0) in the next log command
+    iiz = find(abs(zer - 1) > norm(zer) * eps && abs(zer) > norm(zer) * eps);
+    iip = find(abs(pol - 1) > norm(pol) * eps && abs(pol) > norm(pol) * eps);
+
+    # avoid dividing empty matrices, it would work but looks nasty
+    if (!isempty(iiz)) czer = log(zer(iiz))/tsam;
+    else               czer = [];                 endif
+
+    if (!isempty(iip)) cpol = log(pol(iip))/tsam;
+    else 	       cpol = [];                 endif
+
+  else
+    # continuous
+    iip = find((abs(pol)) > (norm(pol) * eps));
+    iiz = find((abs(zer)) > (norm(zer) * eps));
+
+    if(!isempty(zer)) czer = zer(iiz);
+    else              czer = [];                endif
+    if(!isempty(pol)) cpol = pol(iip);
+    else              cpol = [];                endif
+  endif
+
+  if(max(size(iip)) + max(size(iiz)) )
+    wmin = floor(log10(min(abs([cpol,czer]))));
+    wmax = ceil(log10(max(abs([cpol,czer]))));
+  else
+    # no poles/zeros away from omega = 0; pick defaults
+    wmin = -1;
+    wmax = 3;
+  endif
+
+  # expand to show the entirety of the "interesting" portion of the plot
+  wmin--;
+  wmax++;
+
+  # run digital frequency all the way to pi
+  if (DIGITAL) wmax = log10(pi/tsam); endif
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/bodquist.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,127 @@
+# Copyright (C) 1996,1998 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [f,w] = bodquist(sys,w,outputs,inputs,rname)
+# [f,w] = bodquist(sys,w,outputs,inputs)
+# used by bode, nyquist
+# inputs:
+#   sys: input system structure
+#   w: range of frequencies; empty if user wants default
+#   outputs:list of outputs; empty if user wants all
+#   inputs: list of inputs; empty if user wants all
+#   rname: name of routine that called bodquist ("bode" or "nyquist")
+# outputs:
+#   w: list of frequencies 
+#   f: frequency response of sys; f(ii) = f(omega(ii))
+#
+# Both bode and nyquist share the same introduction, so the common parts are 
+# in this file bodquist.m.  It contains the part that finds the 
+# number of arguments, determines whether or not the system is SISO, and 
+# computes the frequency response.  Only the way the response is plotted is
+# different between the two functions.
+
+  # check number of input arguments given
+  if (nargin != 5)
+    usage("[f,w] = bodquist(sys,w,outputs,inputs,rname)");
+  endif
+
+  # check each argument to see if it's in the correct form
+  if (!is_struct(sys))
+    error("sys must be a system data structure");
+  endif
+	
+  # let freqresp determine w if it's not already given
+  USEW = freqchkw(w);
+
+  # get initial dimensions (revised below if sysprune is called)
+  [nn,nz,mm,pp ] = sysdimensions(sys);
+
+  # check for an output vector and to see whether it`s correct
+  if (!isempty(outputs))
+    if (isempty(inputs))
+      inputs = 1:mm;			# use all inputs
+      warning([rname,": outputs specified but not inputs"]);
+    endif
+    sys = sysprune(sys,outputs,inputs);
+    [nn,nz,mm,pp ] = sysdimensions(sys);
+  endif
+
+  # for speed in computation, convert local copy of 
+  # SISO state space systems to zero-pole  form
+  if( is_siso(sys) & strcmp( sysgettype(sys), "ss") )
+    [zer,pol,k,tsam,inname,outname] = sys2zp(sys);
+    sys = zp2sys(zer,pol,k,tsam,inname,outname);
+  endif
+
+  # get system frequency response
+  [f,w] = freqresp(sys,USEW,w);   
+
+  phase = arg(f)*180.0/pi;
+
+  if(!USEW)
+    # smooth plots
+    pcnt = 5;		# max number of refinement steps
+    dphase = 5;		# desired max change in phase
+    dmag = 0.2;		# desired max change in magnitude
+    while(pcnt)
+      pd = abs(diff(phase));			# phase variation
+      pdbig = vec(find(pd > dphase));
+
+      lp = length(f);  lp1 = lp-1;		# relative variation
+      fd = abs(diff(f));
+      fm = max(abs([f(1:lp1); f(2:lp)]));
+      fdbig = vec(find(fd > fm/10));
+
+      bigpts = union(fdbig, pdbig);
+
+      if(isempty(bigpts) )
+        pcnt = 0;
+      else
+        pcnt = pcnt - 1;
+        wnew = [];
+        crossover_points = find ( phase(1:lp1).*phase(2:lp) < 0);
+        pd(crossover_points) = abs(359.99+dphase - pd(crossover_points));
+        np_pts = ceil(pd/dphase)+2;		# phase points
+        nm_pts = ceil(log(fd./fm)/log(dmag))+2; 	# magnitude points
+        npts = min(5,max(np_pts, nm_pts));
+        w1 = log10(w(1:lp1));
+        w2 = log10(w(2:lp));
+        for ii=bigpts
+          if(npts(ii))
+            wseg(ii,1:npts(ii)) = logspace(w1(ii),w2(ii),npts(ii));
+          endif
+        endfor
+        wnew = reshape(wseg,1,rows(wseg)*columns(wseg)); # make a row vector
+        wnew = wnew(find(wnew != 0));
+        wnew = sort(wnew);
+        wnew = create_set(wnew);
+        if(isempty(wnew))   # all small crossovers
+          pcnt = 0;
+        else
+          [fnew,wnew] = freqresp(sys,1,wnew);    # get new freq resp points
+          w = [w,wnew];			# combine with old freq resp
+          f = [f,fnew];
+          [w,idx] = sort(w);		# sort into order
+          f = f(idx);
+          phase = arg(f)*180.0/pi;
+        endif
+      endif
+    endwhile
+  endif
+    
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/buildssic.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,299 @@
+# Copyright (C) 1998 Kai P. Mueller
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [sys] = buildssic(Clst,Ulst,Olst,Ilst,s1,s2,s3,s4,s5,s6,s7,s8)
+#
+# [sys] = buildssic(Clst,Ulst,Olst,Ilst,s1,s2,s3,s4,s5,s6,s7,s8)
+#
+# Form an arbitrary complex (open or closed loop) system in
+# state-space form from several systems. "buildssic" can
+# easily (despite it's cryptic syntax) integrate transfer functions
+# from a complex block diagram into a single system with one call.
+# This function is especially useful for building open loop
+# interconnections for H_infinity and H2 designs or for closing
+# loops with these controllers.
+#
+# Although this function is general purpose, the use of "sysgroup"
+# "sysmult", "sysconnect" and the like ist recommended for standard
+# operations since they can handle mixed discrete and continuous
+# systems and also the names of inputs, outputs, and states.
+# 
+# The parameters consist of 4 lists which describe the connections
+# outputs and inputs and up to 8 systems s1-s8.
+# Format of the lists:
+#
+#     Clst: connection list, describes the input signal of
+#           each system. The maximum number of rows of Clst is
+#           equal to the sum of all inputs of s1-s8.
+#           Example:
+#             [1 2 -1; 2 1 0] ==> new input 1 is old inpout 1
+#             + output 2 - output 1, new input 2 is old input 2
+#             + output 1. The order of rows is arbitrary.
+#
+#     Ulst: if not empty the old inputs in vector Ulst will
+#           be appended to the outputs. You need this if you
+#           want to "pull out" the input of a system. Elements
+#           are input numbers of s1-s8.
+#
+#     Olst: output list, specifiy the outputs of the resulting
+#           systems. Elements are output numbers of s1-s8.
+#           The numbers are alowed to be negative and may
+#           appear in any order. An empty matrix means
+#           all outputs.
+#
+#     Ilst: input list, specifiy the inputs of the resulting
+#           systems. Elements are input numbers of s1-s8.
+#           The numbers are alowed to be negative and may
+#           appear in any order. An empty matrix means
+#           all inputs.
+#
+# Example:  Very simple closed loop system.
+#
+#       w        e  +-----+   u  +-----+
+#        --->o--*-->|  K  |--*-->|  G  |--*---> y
+#            ^  |   +-----+  |   +-----+  |
+#          - |  |            |            |
+#            |  |            +----------------> u
+#            |  |                         |
+#            |  +-------------------------|---> e
+#            |                            |
+#            +----------------------------+
+#
+# The closed loop system GW can be optained by
+#
+#     GW = buildssic([1 2; 2 -1], [2], [1 2 3], [2], G, K);
+#
+# Clst: (1. row) connect input 1 (G) with output 2 (K).
+#       (2. row) connect input 2 (K) with neg. output 1 (G).
+# Ulst: append input of (2) K to the number of outputs.
+# Olst: Outputs are output of 1 (G), 2 (K) and appended
+#       output 3 (from Ulst).
+# Ilst: the only input is 2 (K).
+#
+# Here is a real example:
+#	                         +----+
+#	    -------------------->| W1 |---> v1
+#	z   |                    +----+
+#	----|-------------+                   || GW   ||     => min.
+#	    |             |                        vz   infty
+#	    |    +---+    v      +----+
+#	    *--->| G |--->O--*-->| W2 |---> v2
+#	    |    +---+       |   +----+
+#	    |                |
+#           |                v
+#          u                  y
+#
+# The closed loop system GW from [z; u]' to [v1; v2; y]' can be
+# obtained by (all SISO systems):
+#
+#     GW = buildssic([1 4;2 4;3 1],[3],[2 3 5],[3 4],G,W1,W2,One);
+#
+# where "One" is a unity gain (auxillary) function with order 0.
+# (e.g. One = ugain(1);)
+#
+
+# Written by Kai Mueller April 1998
+# $Revision: 1.2 $
+# $Log: buildssic.m,v $
+# Revision 1.2  1998/10/12  10:04:14  mueller
+# bugfix: build of discrete systems corrected.
+# The previous version did not sum up the discrete states.
+#
+# Revision 1.1  1998/10/12  08:51:49  mueller
+# Initial revision
+#
+# Revision 1.1.1.1  1998/05/19 20:24:05  jwe
+#
+# Revision 1.1  1998/05/05 17:02:56  scotte
+# Initial revision
+#
+# Revision 1.2  1998/05/05  08:19:59  mueller
+# minor corrections
+#
+# Revision 1.1  1998/05/04  15:09:32  mueller
+# Initial revision
+#
+
+  if((nargin < 5) || (nargin > 12))
+    usage("[sys] = buildssic(Clst,Ulst,Olst,Ilst,s1,s2,s3,s4,s5,s6,s7,s8)");
+  endif
+  if (nargin >= 5)
+    if (!is_struct(s1))
+      error("---> s1 must be a structed system.");
+    endif
+    s1 = sysupdate(s1, "ss");
+    [n, nz, m, p] = sysdimensions(s1);
+    if (!n && !nz)
+      error("---> pure static system must not be the first in list.");
+    endif
+    if (n && nz)
+      error("---> cannot handle mixed continuous and discrete systems.");
+    endif
+    D_SYS = (nz > 0);
+    [A,B,C,D,tsam] = sys2ss(s1);
+    nt = n + nz;
+  endif
+  for ii = 6:nargin
+    eval(["ss = s" num2str(ii-4) ";"]);
+    if (!is_struct(ss))
+      error("---> Parameter must be a structed system.");
+    endif
+    ss = sysupdate(ss, "ss");
+    [n1, nz1, m1, p1] = sysdimensions(ss);
+    if (n1 && nz1)
+      error("---> cannot handle mixed continuous and discrete systems.");
+    endif
+    if (D_SYS)
+      if (n1)
+      	error("---> cannot handle mixed cont. and discr. systems.");
+      endif
+      if (tsam != sysgettsam(ss))
+	error("---> sampling time of all systems must match.");
+      endif
+    endif
+    [as,bs,cs,ds] = sys2ss(ss);
+    nt1 = n1 + nz1;
+    if (!nt1)
+      # pure gain (pad B, C with zeros)
+      B = [B  zeros(nt,m1)];
+      C = [C; zeros(p1,nt)];
+    else
+      A = [A  zeros(nt,nt1); zeros(nt1,nt) as];
+      B = [B  zeros(nt,m1);  zeros(nt1,m)  bs];
+      C = [C  zeros(p,nt1);  zeros(p1,nt)  cs];
+    endif
+    D = [D  zeros(p,m1); zeros(p1,m) ds];
+    n = n + n1;
+    nz = nz + nz1;
+    nt = nt + nt1;
+    m = m + m1;
+    p = p + p1;
+  endfor
+
+  # check maximum dimensions
+  [nx, mx] = size(Clst);
+  if (nx > m)
+    error("---> more rows in Clst than total number of inputs.");
+  endif
+  if (mx > p+1)
+    error("---> more cols in Clst than total number of outputs.");
+  endif
+  # empty vector Ulst is OK
+  lul = length(Ulst);
+  if (lul)
+    if (!is_vector(Ulst))
+      error("---> Input u list Ulst must be a vector.");
+    endif
+    if (lul > m)
+      error("---> more values in Ulst than number of inputs.");
+    endif
+  endif
+  if (!length(Olst))  Olst = [1:(p+lul)];  endif
+  if (!length(Ilst))  Ilst = [1:m];        endif
+  if (!is_vector(Olst))
+    error("---> Output list Olst must be a vector.");
+  endif
+  if (!is_vector(Ilst))
+    error("---> Input list Ilst must be a vector.");
+  endif
+
+  # build the feedback "K" from the interconnection data Clst
+  K = zeros(m, p);
+  inp_used = zeros(m,1);
+  for ii = 1:nx
+    xx = Clst(ii,:);
+    iu = xx(1);
+    if ((iu < 1) || (iu > m))
+      error("---> Illegal value in first col of Clst.");
+    endif
+    if (inp_used(iu))
+      error("---> Input specified more than once.");
+    endif
+    inp_used(iu) = 1;
+    for kk = 2:mx
+      it = xx(kk);
+      if (abs(it) > p)
+      	error("---> Illegal row value in Clst.");
+      elseif (it)
+	K(iu,abs(it)) = sign(it);
+      endif
+    endfor
+  endfor
+
+  # form the "closed loop", i.e replace u in
+  # .
+  # x = Ax + Bu
+  #                            ~
+  # y = Cx + Du   by   u = K*y+u
+  #
+  #            -1
+  # R = (I-D*K)   must exist.
+  # 
+  R = eye(p) - D*K;
+  if (rank(R) < m)
+    error("---> singularity in algebraic loop.");
+  else
+    R = inv(R);
+  endif
+  A = A + B*K*R*C;
+  B = B + B*K*R*D;
+  C = R*C;
+  D = R*D;
+
+  # append old inputs u to the outputs (if lul > 0)
+  kc = K*C;
+  kdi = eye(m) + K*D;
+  for ii = 1:lul
+    it = Ulst(ii);
+    if ((it < 1) || (it > m))
+      error("---> Illegal value in Ulst.");
+    endif
+    C = [C; kc(it,:)];
+    D = [D; kdi(it,:)];
+  endfor
+
+  # select and rearrange outputs
+  nn = length(A);
+  lol = length(Olst);
+  Cnew = zeros(lol,nn);
+  Dnew = zeros(lol,m);
+  for ii = 1:lol
+    iu = Olst(ii);
+    if (!iu || (abs(iu) > p+lul))
+      error("---> Illegal value in Olst.");
+    endif
+    Cnew(ii,:) = sign(iu)*C(abs(iu),:);
+    Dnew(ii,:) = sign(iu)*D(abs(iu),:);
+  endfor
+  C = Cnew;
+  D = Dnew;
+  lil = length(Ilst);
+  Bnew = zeros(nn,lil);
+  Dnew = zeros(lol,lil);
+  for ii = 1:lil
+    iu = Ilst(ii);
+    if (!iu || (abs(iu) > m))
+      error("---> Illegal value in Ilst.");
+    endif
+    Bnew(:,ii) = sign(iu)*B(:,abs(iu));
+    Dnew(:,ii) = sign(iu)*D(:,abs(iu));
+  endfor
+
+  sys = ss2sys(A, Bnew, C, Dnew, tsam, n, nz);
+
+endfunction
--- a/scripts/control/c2d.m	Thu Nov 05 04:24:46 1998 +0000
+++ b/scripts/control/c2d.m	Fri Nov 06 16:16:31 1998 +0000
@@ -1,59 +1,179 @@
-## Copyright (C) 1996, 1997 John W. Eaton
-##
-## 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-1307, USA.
+# Copyright (C) 1993, 1994, 1995 John W. Eaton
+# 
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+function dsys = c2d (sys, opt, T)
 
-## Usage: [Ad, Bd] = c2d (Ac, Bc, T)
-##
-## converts the continuous time system described by:
-##   .
-##   x = Ac x + Bc u
-##
-## into a discrete time equivalent model via the matrix exponential
-##
-##   x[n+1] = Ad x[n] + Bd u[n]
-##
-## assuming a zero-order hold on the input and sample time T.
+# Usage: dsys = c2d (sys[, T])
+# Usage: dsys = c2d (sys[, opt[, T]])
+# inputs:
+#   sys: system data structure (may be mixed discrete/continiuous time)
+#   optional arguments:
+#     opt: conversion option: 
+#          "ex" - use the matrix exponential (default)
+#          "bi" - use the bilinear transformation
+#                   2(z-1)
+#               s = -----
+#                   T(z+1)
+#               FIXME: This option exits with an error if sys is not purely 
+#               continuous. (The ex can handle mixed systems.)
+#
+#     T: sampling time; required if sys is purely continuous.
+# outputs: 
+#   dsys: discrete time equivalent via zero-order hold, sample each T sec.
+#
+# converts the system described by:
+#   .
+#   x = Ac x + Bc u
+#
+# into a discrete time equivalent model via the matrix exponential
+#
+#   x[n+1] = Ad x[n] + Bd u[n]
+#
+# Note: This function adds _d to the names of the new discrete states.   
 
-## Author: R.B. Tenison <btenison@eng.auburn.edu>
-## Created: October 1993
-## Adapted-By: jwe
+# Written by R.B. Tenison (btenison@eng.auburn.edu)
+# October 1993
+# Updated by John Ingram for system data structure August 1996
+# SYS_INTERNAL accesses members of system data structure
+# $Log: c2d.m,v $
+# Revision 1.13  1998-11-06 16:15:36  jwe
+# *** empty log message ***
+#
+# Revision 1.3  1998/07/21 14:53:08  hodelas
+# use isempty instead of size tests; use sys calls to reduce direct
+# access to system structure elements
+#
+# Revision 1.2  1998/07/01 16:23:35  hodelas
+# Updated c2d, d2c to perform bilinear transforms.
+# Updated several files per bug updates from users.
+#
+# $Revision: 1.13 $
 
-function [Ad, Bd] = c2d (Ac, Bc, T)
+  save_val = implicit_str_to_num_ok;	# save for later
+  implicit_str_to_num_ok = 1;
 
-  ## check args
-  if (nargin != 3)
-    usage ("c2d (Ac, Bc, T)");
+# parse input arguments
+  if(nargin < 1 | nargin > 3)
+    usage("dsys=c2d(sys[,T])");
+  elseif (!is_struct(sys))
+    error("sys must be a system data structure");
+  elseif (nargin == 1)
+    opt = "ex";
+  elseif (nargin == 2 & !isstr(opt) )
+    T = opt;
+    opt = "ex";
   endif
 
-  [ma, na] = size (Ac);
-  [mb, nb] = size (Bc);
+  # check if sampling period T was passed.
+  Ts = sysgettsam(sys);
+  if(!exist("T"))
+    T = Ts;
+    if(T == 0)
+      error("sys is purely continuous; no sampling period T provided");
+    endif
+  elseif (T != Ts & Ts > 0)
+    warning(["c2d: T=",num2str(T),", system tsam==",num2str(Ts), ...
+      ": using T=", num2str(min(T,Ts))]);
+    T = min(T,Ts);
+  endif
 
-  if (ma != na)
-    error ("c2d: Ac must be square");
+  if (!is_sample(T))
+    error("sampling period T must be a postive, real scalar");
+  elseif( ! (strcmp(opt,"ex") | strcmp(opt,"bi") ) )
+    error(["illegal option passed: ",opt])
   endif
 
-  if (ma != mb)
-    error ("c2d: Ac and Bc must have the same number of rows");
-  endif
+  sys = sysupdate(sys,"ss");
+  [n,nz,m,p] = sysdimensions(sys);
+
+  if (n == 0)
+    warning("c2d: sys has no continuous states; setting outputs to discrete");
+    dsys = syschnames(sys,"yd",1:p,ones(1:p));
+  elseif(strcmp(opt,"ex"))
+    # construct new state-space (a,b,c,d) for continuous subsystem
+    [csys,Acd] = syscont(sys);   	# extract continuous subsystem
+    [csys_a, csys_b, csys_c, csys_d] = sys2ss(csys);
+    [ sys_a,  sys_b,  sys_c,  sys_d] = sys2ss( sys);
+    if(isempty(Acd))
+      Bmat = sys_b;
+    elseif(isempty(csys_b))
+      Bmat = Acd;
+    else
+      Bmat = [Acd csys_b];
+    endif
+    
+    row_zer = columns(Bmat);
+    col_zer = csys.n + row_zer;
+
+    if(isempty(Bmat) )
+      warning("c2d: no inputs to continuous subsystem.");
+      mat = csys.a;
+    else
+      mat = [csys.a Bmat ; zeros( row_zer,col_zer) ];
+    endif
+
+    matexp = expm(mat * T);
+  
+    Abar = matexp( 1:csys.n , 1:(csys.n + columns(Acd)) );  
+    Bbar = matexp( 1:csys.n , (columns(Abar) + 1):columns(matexp) );
+
+    dsys = sys;
+
+    dsys.a(1:csys.n , : ) = Abar;
+    dsys.b(1:csys.n , : ) = Bbar;
 
-  matexp = expm ([[Ac, Bc] * T; (zeros (nb, na+nb))]);
+    dsys.sys = [2 0 0 1];
+
+    dsys.tsam = T;
+    dsys.n = 0;
+    dsys.nz = rows(dsys.a);
+
+    dsys.yd = ones(1,rows(dsys.c));
+
+    for ii = 1:csys.n
+      strval = [dezero((dsys.stname(ii,:))),"_d"];
+      dsys.stname(ii,(1:length(strval))) = [strval];
+    endfor
 
-  Ad = matexp (1:na, 1:na);
-  Bd = matexp (1:na, na+1:na+nb);
+  elseif(strcmp(opt,"bi"))
+    if(is_digital(sys))
+      error("c2d: system is already digital")
+    else
+      # convert with bilinear transform
+      [a,b,c,d,tsam,n,nz,stname,inname,outname,yd] = sys2ss(sys);
+      IT = (2/T)*eye(size(a));
+      A = (IT+a)/(IT-a);
+      iab = (IT-a)\b;
+      tk=2/sqrt(T);
+      B = tk*iab;
+      C = tk*(c/(IT-a));
+      D = d + (c*iab);
+      stnamed="";
+      for kk=1:rows(stname)
+        tmp =  [dezero(stname(kk,:)),"_d"];
+        stnamed(kk,1:length(tmp)) = tmp;
+      endfor
+      dsys = ss2sys(A,B,C,D,T,0,rows(A),stnamed,inname,outname);
+    endif
+  else
+    error(["Bad option=",opt])
+  endif
+  
+  implicit_str_to_num_ok = save_val;	# restore value
 
 endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/com2str.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,76 @@
+# Copyright (C) 1998 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function retval = com2str(zz,flg)
+# usage retval = com2str(zz{,flg})
+#  
+# convert complex number to a string
+# zz: complex number
+# flg: format flag
+#      0 (default):            -1, 0, 1,   1i,   1 + 0.5i
+#      1 (for use with zpout): -1, 0, + 1, + 1i, + 1 + 0.5i
+#
+# $Revision: 1.1 $
+
+  if (nargin < 1 | nargin > 2)
+    usage("com2str(zz{,flg})");
+  endif
+  if(nargin == 1)
+    flg = 0;
+  endif
+ 
+  if( !(is_scalar(zz) & is_scalar(flg) ) )
+    error("com2str: arguments must be a scalar.");
+  endif
+
+  if(flg != 0 & flg != 1)
+    error(["Illegal flg value: ",num2str(flg)]);
+  endif
+
+  sgns = "+-";
+  rz = real(zz);
+  iz = imag(zz);
+  az = abs(zz);
+  if(iz == 0)
+    # strictly a real number
+    switch(flg)
+    case(0)
+      retval = num2str(rz);
+    case(1)
+      retval = [ sgns(1+(rz< 0))," ", num2str(abs(rz))];
+    endswitch
+  elseif(rz == 0)
+    # strictly an imaginary number
+    switch(flg)
+    case(0)
+      retval = num2str(iz);
+    case(1)
+      retval = [ sgns(1+(iz< 0))," ", num2str(abs(iz)),"i"];
+    endswitch
+  else
+    # complex number
+    # strictly an imaginary number
+    switch(flg)
+    case(0)
+      retval = [num2str(rz)," ",com2str(i*iz,1)];
+    case(1)
+      retval = [ sgns(1+(rz< 0))," ", num2str(abs(rz))," ",com2str(i*iz,1)];
+    endswitch
+  endif
+  
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/controldemo.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,61 @@
+# Copyright (C) 1996 A. Scottedward Hodel
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+function DEMOcontrol()
+# Controls toolbox demo.
+# Demo programs: bddemo.m, frdemo.m, analdemo.m, moddmeo.m, rldemo.m
+#  
+# Written by David Clem August 15, 1994
+# $Revision: 1.1 $    
+
+  disp(' O C T A V E    C O N T R O L   S Y S T E M S   T O O L B O X')
+
+  while (1)
+    clc
+    k = 0;
+    while (k > 8 || k < 1),
+      k = menu("Octave Controls System Toolbox Demo", ...
+	'System representation', ...
+    	'Block diagram manipulations ', ...
+    	'Frequency response functions ', ...
+    	'State space analysis functions ', ...
+    	'System model manipulations ', ...
+    	'Root locus functions ', ...
+	'LQG/H2/Hinfinity functions ', ...
+    	'End');
+
+    endwhile
+    if(k == 1)
+      sysrepdemo
+    elseif (k == 2)
+      bddemo
+    elseif (k == 3)
+      frdemo
+    elseif (k == 4)
+      analdemo
+    elseif (k == 5)
+      moddemo
+    elseif (k == 6)
+      rldemo
+    elseif (k == 7)
+      dgkfdemo
+    elseif (k == 8)
+      return
+    endif
+  endwhile
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/ctrb.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,72 @@
+# Copyright (C) 1997 Kai P. Mueller
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+
+function Qs = ctrb(sys, b)
+  # ------------------------------------------------------
+  # Qs = ctrb(sys [, b])
+  # Build controllability matrix
+  #
+  #                  2       n-1
+  #     Qs = [ B AB A B ... A   B
+  #
+  # of a system data structure or the pair (A, B).
+  #
+  # Note: ctrb() forms the controllability matrix.
+  #       The numerical properties of is_controllable()
+  #       are much better for controllability tests.
+  # See also: obsv, is_observable, is_controllable
+  # ------------------------------------------------------
+
+  # Written by Kai P. Mueller November 4, 1997
+  # based on is_controllable.m of Scottedward Hodel
+  # modified by
+  # $Revision: 1.1.1.1 $
+  # $Log: ctrb.m,v $
+  # Revision 1.1.1.1  1998/05/19 20:24:06  jwe
+  #
+  # Revision 1.2  1997/12/01 16:51:50  scotte
+  # updated by Mueller 27 Nov 97
+  #
+# Revision 1.2  1997/11/25  11:15:54  mueller
+# name confict with function mb removed
+#
+
+  if (nargin == 2)
+    a = sys;
+  elseif (nargin == 1 && is_struct(sys))
+    sysupdate(sys,"ss");
+    a = sys.a;
+    b = sys.b;
+  else
+    usage("ctrb(sys [, b])")
+  endif
+
+  if (!is_abcd(a,b))
+    Qs = [];
+  else
+    # no need to check dimensions, we trust is_abcd().
+    [na, ma] = size(a);
+    # using imb avoids name conflict with the "mb" function
+    [inb, imb] = size(b);
+    Qs = zeros(na, ma*imb);
+    for i = 1:na
+      Qs(:, (i-1)*imb+1:i*imb) = b;
+      b = a * b;
+    endfor
+  endif
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/d2c.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,243 @@
+# Copyright (C) 1996,1998 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function csys = d2c(sys,opt)
+# csys = d2c(sys[,tol])
+# csys = d2c(sys,opt)
+#
+# inputs: 
+#   sys: system data structure with discrete components
+#   tol: tolerance for convergence of default "log" option (see below)
+#
+#   opt: conversion option.  Choose from:
+#        "log":  (default) Conversion is performed via a matrix logarithm.
+#                Due to some problems with this computation, it is
+#                followed by a steepest descent to identify continuous time 
+#                A, B, to get a better fit to the original data.  
+#
+#                If called as d2c(sys,tol), tol=positive scalar, the log
+#                option is used.  The default value for tol is 1e-8.
+#        "bi": Conversion is performed via bilinear transform
+#                  1 + s T/2
+#              z = ---------
+#                  1 - s T/2
+#              where T is the system sampling time (see syschtsam).
+#
+#              FIXME: exits with an error if sys is not purely discrete
+#
+# D2C converts the real-coefficient discrete time state space system
+#
+#        x(k+1) = A x(k) + B u(k)
+#
+# to a continuous time state space system
+#        .
+#        x = A1 x + B1 u
+#
+# The sample time used is that of the system. (see syschtsam).
+  
+# Written by R. Bruce Tenison August 23, 1994
+# Updated by John Ingram for system data structure  August 1996
+# SYS_INTERNAL accesses members of system data structure
+# $Revision: 1.3 $ 
+# $Log: d2c.m,v $
+# Revision 1.3  1998/08/13 16:27:21  hodelas
+# Fixed warning message
+#
+# Revision 1.2  1998/07/01 16:23:36  hodelas
+# Updated c2d, d2c to perform bilinear transforms.
+# Updated several files per bug updates from users.
+#
+# Revision 1.4  1997/02/20 16:18:52  hodel
+# added warning about poles near 1.
+#
+# Revision 1.3  1997/02/20 16:07:26  hodel
+# Added gradient descent code so that d2c returns the same function
+# as c2d started with		a.s.hodel@eng.auburn.edu
+#
+
+  save_val = implicit_str_to_num_ok;	# save for later
+  implicit_str_to_num_ok = 1;
+
+  if( (nargin != 1) & (nargin != 2) )
+    usage("csys = d2c(sys[,tol]), csys = d2c(sys,opt)");
+  elseif (!is_struct(sys))
+    error("sys must be in system data structure");
+  elseif(nargin == 1)
+    opt = "log";
+    tol = 1e-12;
+  elseif(isstr(opt))   # all remaining cases are for nargin == 2
+    tol = 1e-12;
+    if( !(strcmp(opt,"log") | strcmp(opt,"bi") ) )
+      error(["d2c: illegal opt passed=",opt]);
+    endif
+  elseif(!is_sample(opt))
+    error("tol must be a postive scalar")
+  elseif(opt > 1e-2)
+    warning(["d2c: ridiculous error tolerance passed=",num2str(opt); ...
+	", intended c2d call?"])
+  else
+    tol = opt;
+    opt = "log";
+  endif
+  T = sys.tsam;
+
+  if(opt == "bi")
+    # bilinear transform
+    # convert with bilinear transform
+    if (! is_digital(sys) )
+       error("d2c requires a discrete time system for input")
+    endif
+    [a,b,c,d,tsam,n,nz,stname,inname,outname,yd] = sys2ss(sys);
+
+    poles = eig(a);
+    if( find(abs(poles-1) < 200*(n+nz)*eps) )
+      warning("d2c: some poles very close to one.  May get bad results.");
+    endif
+
+    I = eye(size(a));
+    tk = 2/sqrt(T);
+    A = (2/T)*(a-I)/(a+I);
+    iab = (I+a)\b;
+    B = tk*iab;
+    C = tk*(c/(I+a));
+    D = d- (c*iab);
+    stnamed="";
+    for kk=1:rows(stname)
+      tmp =  [dezero(stname(kk,:)),"_c"];
+      stnamec(kk,1:length(tmp)) = tmp;
+    endfor
+    csys = ss2sys(A,B,C,D,0,rows(A),0,stnamec,inname,outname);
+  elseif(opt == "log")
+    sys = sysupdate(sys,"ss");
+    [n,nz,m,p] = sysdimensions(sys);
+  
+    if(nz == 0)
+      warning("d2c: all states continuous; setting outputs to agree");
+      csys = syschnames(sys,"yd",1:p,zeros(1,1:p));
+      return;
+    elseif(n != 0)
+      warning(["d2c: n=",num2str(n),">0; performing c2d first"]);
+      sys = c2d(sys,T);
+    endif
+    [a,b] = sys2ss(sys);
+  
+    [ma,na] = size(a);
+    [mb,nb] = size(b);
+  
+    if(isempty(b) )
+      warning("d2c: empty b matrix");
+      Amat = a;
+    else
+      Amat = [a, b; zeros(nb, na) eye(nb)];
+    endif
+  
+    poles = eig(a);
+    if( find(abs(poles) < 200*(n+nz)*eps) )
+      warning("d2c: some poles very close to zero.  logm not performed");
+      Mtop = zeros(ma, na+nb);
+    elseif( find(abs(poles-1) < 200*(n+nz)*eps) )
+      warning("d2c: some poles very close to one.  May get bad results.");
+      logmat = real(logm(Amat)/T);
+      Mtop = logmat(1:na,:);
+    else
+      logmat = real(logm(Amat)/T);
+      Mtop = logmat(1:na,:);
+    endif
+  
+    # perform simplistic, stupid optimization approach.
+    # should re-write with a Davidson-Fletcher CG approach
+    mxthresh = norm(Mtop);
+    if(mxthresh == 0)
+      mxthresh = 1;
+    endif
+    eps1 = mxthresh;	#gradient descent step size
+    cnt = max(20,(n*nz)*4);	#max number of iterations
+    newgrad=1;	#signal for new gradient
+    while( (eps1/mxthresh > tol) & cnt)
+      cnt = cnt-1;
+      # calculate the gradient of error with respect to Amat...
+      geps = norm(Mtop)*1e-8;
+      if(geps == 0)
+        geps = 1e-8;
+      endif
+      DMtop = Mtop;
+      if(isempty(b))
+        Mall = Mtop;
+        DMall = DMtop;
+      else
+        Mall = [Mtop; zeros(nb, na+nb)];
+        DMall = [DMtop; zeros(nb, na+nb) ];
+      endif
+  
+      if(newgrad)
+        GrMall = zeros(size(Mall));
+        for ii=1:rows(Mtop)
+          for jj=1:columns(Mtop)
+  	  DMall(ii,jj) = Mall(ii,jj) + geps;
+            GrMall(ii,jj) = norm(Amat - expm(DMall*T),'fro') ...
+  	    - norm(Amat-expm(Mall*T),'fro');
+      	  DMall(ii,jj) = Mall(ii,jj);
+          endfor
+        endfor
+        GrMall = GrMall/norm(GrMall,1);
+        newgrad = 0;
+      endif
+  
+      #got a gradient, now try to use it
+      DMall = Mall-eps1*GrMall;
+  
+      FMall = expm(Mall*T);
+      FDMall = expm(DMall*T);
+      FmallErr = norm(Amat - FMall);
+      FdmallErr = norm(Amat - FDMall);
+      if( FdmallErr < FmallErr)
+        Mtop = DMall(1:na,:);
+        eps1 = min(eps1*2,1e12);
+        newgrad = 1;
+      else
+        eps1 = eps1/2;
+      endif
+  
+      if(FmallErr == 0)
+        eps1 = 0;
+      endif
+      
+    endwhile
+  
+    csys = sys;
+    csys.a = Mall(1:na,1:na);
+    if(!isempty(b))
+      csys.b = Mall(1:na,(na+1):(na+nb));
+    endif
+    
+    csys.n = na;
+    csys.nz = 0;
+  
+    csys.sys = [2 0 0 1];
+  
+    csys.yd = zeros(1,rows(csys.c));
+    
+    for ii = (sys.n + 1):rows(sys.stname)
+      strval = [(csys.stname(ii,:)),"_c"];
+      csys.stname(ii,(1:length(strval))) = [strval];
+    endfor
+    csys = syschtsam(csys,0);
+  endif
+
+  implicit_str_to_num_ok = save_val;	# restore value
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/damp.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,93 @@
+# Copyright (C) 1993, 1994, 1995 John W. Eaton
+# 
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+function damp(p, tsam)
+# Usage: damp(p[, tsam])
+#      Displays eigenvalues, natural frequencies and damping ratios
+#      of the eigenvalues of a matrix p or the A-matrix of a
+#      system p, respectively.
+#      If p is a system, tsam must not be specified.
+#      If p is a matrix and tsam is specified, eigenvalues
+#      of p are assumed to be in z-domain.
+#
+# See also: eig
+
+# Written by Kai P. Mueller September 29, 1997.
+# Update
+# $Revision: 1.1.1.1 $
+# $Log: damp.m,v $
+# Revision 1.1.1.1  1998/05/19 20:24:06  jwe
+#
+# Revision 1.3  1997/12/01 16:51:50  scotte
+# updated by Mueller 27 Nov 97
+#
+# Revision 1.1  1997/11/11  17:32:13  mueller
+# Initial revision
+#
+
+  # assume a continuous system
+  DIGITAL = 0;
+  if(nargin < 1 || nargin > 2)
+    usage("damp(p,[ tsamp])")
+  endif
+  if(is_struct(p))
+    if (nargin != 1)
+      error("damp: when p is a system, tsamp parameter is not allowed.");
+    endif
+    [aa, b, c, d, t_samp] = sys2ss(p);
+    DIGITAL = is_digital(p);
+  else
+    aa = p;
+    if (nargin == 2)
+        DIGITAL = 1;
+        t_samp = tsam;
+    endif
+  endif
+  if (!is_square(aa))
+    error("damp: Matrix p is not square.")
+  endif
+  if (DIGITAL && t_samp <= 0.0)
+    error("damp: Sampling time tsam must not be <= 0.")
+  endif
+
+  # all checks done.
+  e = eig(aa);
+  [n, m] = size(aa);
+  if (DIGITAL)
+    printf("  (discrete system with sampling time %f)\n", t_samp);
+  endif
+  printf("............... Eigenvalue ...........     Damping     Frequency\n");
+  printf("--------[re]---------[im]--------[abs]----------------------[Hz]\n");
+  for i = 1:n
+    pole = e(i);
+    cpole = pole;
+    if (DIGITAL)
+      cpole = log(pole) / t_samp;
+    endif
+    d0 = -cos(atan2(imag(cpole), real(cpole)));
+    f0 = 0.5 / pi * abs(cpole);
+    if (abs(imag(cpole)) < eps)
+      printf("%12f         ---  %12f  %10f  %12f\n",
+             real(pole), abs(pole), d0, f0);
+    else
+      printf("%12f %12f %12f  %10f  %12f\n",
+             real(pole), imag(pole), abs(pole), d0, f0);
+    endif
+  endfor
+
+endfunction
--- a/scripts/control/dare.m	Thu Nov 05 04:24:46 1998 +0000
+++ b/scripts/control/dare.m	Fri Nov 06 16:16:31 1998 +0000
@@ -32,8 +32,8 @@
 ##
 ## If c is not square, then the function attempts to use c'*c instead.
 ##
-## Solution method: Laub's Schur method (IEEE Trans Auto Contr, 1979) applied
-## to the appropriate symplectic matrix.
+## Solution method: Generalized eigenvalue approach (Van Dooren; SIAM J.
+## Sci. Stat. Comput., Vol 2) applied  to the appropriate symplectic pencil.
 ##
 ## See also: Ran and Rodman, "Stable Hermitian Solutions of Discrete
 ## Algebraic Riccati Equations," Mathematics of Control, Signals and
@@ -47,10 +47,15 @@
 ## Author: A. S. Hodel <scotte@eng.auburn.edu>
 ## Created: August 1993
 ## Adapted-By: jwe
+## $Revision: 1.15 $
+## $Log: dare.m,v $
+## Revision 1.15  1998-11-06 16:15:36  jwe
+## *** empty log message ***
+##
 
 function x = dare (a, b, c, r, opt)
 
-  if (nargin == 4 || nargin == 5)
+  if (nargin == 4 | nargin == 5)
     if (nargin == 5)
       if (opt != "N" || opt != "P" || opt != "S" || opt != "B")
 	warning ("dare: opt has an invalid value -- setting to B");
@@ -60,26 +65,10 @@
       opt = "B";
     endif
 
-    ## Check a matrix dimensions
-    if ((n = is_square (a)) == 0)
-      error ("dare: a is not square");
-    endif
-
-    ## Check a,b compatibility.
-
-    [n1, m] = size (b);
-
-    if (n1 != n)
-      warning ("dare: a,b are not conformable");
-    endif
-
+    # dimension checks are done in is_controllable, is_observable
     if (is_controllable (a, b) == 0)
       warning ("dare: a,b are not controllable");
-    endif
-
-    ## Check a,c compatibility.
-
-    if (is_observable (a, c) == 0)
+    elseif (is_observable (a, c) == 0)
       warning ("dare: a,c are not observable");
     endif
 
@@ -88,22 +77,19 @@
       p = rows (c);
     endif
 
-    if (n != p)
-      error ("dare: a,c are not conformable");
-    endif
-
     ## Check r dimensions.
-
+    n = rows(a);
+    m = columns(b);
     if ((m1 = is_square (r)) == 0)
       warning ("dare: r is not square");
     elseif (m1 != m)
       warning ("b,r are not conformable");
     endif
 
-    brb = (b/r)*b';
-    atc = a'\c;
-    [d, sy] = balance ([a + brb*atc, -brb/(a'); -atc, (inv (a'))], opt);
-    [u, s] = schur (sy, 'D');
+    s1 = [a, zeros(n) ; -c, eye(n)];
+    s2 = [eye(n), (b/r)*b' ; zeros(n), a'];
+    [c,d,s1,s2] = balance(s1,s2,opt);
+    [aa,bb,u,lam] = qz(s1,s2,"S");
     u = d*u;
     n1 = n+1;
     n2 = 2*n;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/dcgain.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,57 @@
+# Copyright (C) 1993, 1994, 1995 John W. Eaton
+# 
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+function gm = dcgain(sys, tol)
+# Usage: gm = dcgain(sys[, tol])
+#      Returns dc-gain matrix. If dc-gain is infinity
+#      an empty matrix is returned.
+#      The argument tol is an optional tolerance for the condition
+#      number of A-Matrix in sys (default tol = 1.0e-10)
+#
+# See also: (nothing)
+
+# Written by Kai P Mueller (mueller@ifr.ing.tu-bs.de) October 1, 1997
+# Updated
+# $Revision: 1.1.1.1 $
+# $Log: dcgain.m,v $
+# Revision 1.1.1.1  1998/05/19 20:24:06  jwe
+#
+# Revision 1.3  1997/12/01 16:51:50  scotte
+# updated by Mueller 27 Nov 97
+#
+# Revision 1.1  1997/11/11  17:32:46  mueller
+# Initial revision
+#
+
+  if((nargin < 1) || (nargin > 2) || (nargout > 1))
+    usage("[gm, ok] = dcgain(sys[, tol])");
+  endif
+  if(!is_struct(sys))
+    error("dcgain: first argument is not a system data structure.")
+  endif
+  sys = sysupdate(sys, "ss");
+  aa = sys.a;
+  if (is_digital(sys))  aa = aa - eye(size(aa));  endif
+  if (nargin == 1)  tol = 1.0e-10;  endif
+  r = rank(aa, tol);
+  if (r < rows(aa))
+    gm = [];
+  else
+    gm = -sys.c / aa * sys.b + sys.d;
+  endif
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/demomarsyas.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,116 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+page_screen_output = 1;
+opt = 0;
+QUITOPT = 7;
+while (opt != QUITOPT)
+  opt = menu("Marsyas interface update demo:", ...
+	"run Marsyas on the magnetically suspended ball example", ...
+        "load continuous time marsyas example system", ...
+	"load discrete-time marsyas example system", ...
+	"bode plot of loaded system (MIMO)", ...
+        "bode plot of loaded system (SISO)", ...
+	"Design example", ...
+	"Quit");
+
+  if(opt == 1)
+    cmd = "system(""marsyas mag1d.mar"")";
+    run_cmd
+    cmd = "system(""marplot -i"")";
+    run_cmd
+  elseif(opt == 2)
+    cmd = "ballsys = margetsys();";
+    run_cmd;
+    cmd = "sysout(ballsys);"
+    run_cmd
+  elseif(opt == 3)
+    cmd = "ballsys = margetsys(""disc"");";
+    run_cmd
+    cmd = "sysout(ballsys);"
+    run_cmd
+  elseif(opt == 4)
+    cmd = "bode(ballsys);";
+    run_cmd
+  elseif(opt == 5)
+    cmd = "bode(ballsys,[],1,1);";
+    run_cmd
+  elseif(opt == 6)
+    if(!exist("ballsys"))
+      warning("You didn't load a system yet (option 2 or 3)");
+    else
+      disp("Design LQG controller");
+      cmd = "sysout(ballsys)";
+      run_cmd
+      disp("add noise inputs to system...")
+      if(ballsys.n)
+        disp("continuous system:")
+        cmd = "ballsys1 = sysappend(ballsys,eye(ballsys.n));";
+      else
+        disp("discrete system:")
+        cmd = "ballsys1 = sysappend(ballsys,eye(ballsys.nz));";
+      endif
+      run_cmd
+      cmd = "sysout(ballsys1)";
+      run_cmd
+      disp("Notice the two additional inputs, u_2, and u_3.  These are the ");
+      disp("""entry points"" for the gaussian noise disturbance.");
+      disp(" ");
+      disp("We'll design the controller to use only position feedback:")
+      cmd = "ballsys1=sysprune(ballsys1,1,[]);";
+      run_cmd
+      cmd = "sysout(ballsys1)";
+      run_cmd
+      disp("Now design an LQG controller: Sigw: input noise")
+      Sigw = eye(2)
+      disp("Now design an LQG controller: Sigv: measurement noise")
+      Sigv = eye(rows(ballsys1.c))
+      disp("State and input penalties:")
+      Q = eye(2)
+      R = 1
+      disp("Controlled input is input 1");
+      cmd="Ksys = lqg(ballsys1,Sigw,Sigv,Q,R,1);";
+      run_cmd
+      disp("sysout(Ksys);");
+      sysout(Ksys);
+      
+      disp("marsyas conversion: output in scalar form:")
+      cmd = "maroutsys(Ksys, ""ball_controller"",""scalar"");";
+      run_cmd
+      disp("here's the output file:")
+      prompt
+      system("more ball_controller.mar");
+      
+      disp("marsyas conversion: output in state space form: (default option;")
+      disp("the ""ss"" in the command below is not needed)")
+      cmd = "maroutsys(Ksys, ""ball_controller_ss"",""ss"");";
+      run_cmd
+      disp("here's the output file:")
+      prompt
+      system("more ball_controller_ss.mar");
+      
+      disp("marsyas conversion: output in transfer function form:")
+      cmd = "maroutsys(Ksys, ""ball_controller_tf"",""tf"")"
+      run_cmd
+      disp("here's the output file:")
+      prompt
+      system("more ball_controller_tf.mar");
+  
+    endif
+  endif
+endwhile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/dezero.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,88 @@
+## Copyright (C) 1996 Kurt Hornik
+##
+## 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-1307, USA.
+
+## usage:  dezero (s)
+##
+## Remove trailing blank entries and all zero entries from the string s.
+
+## Author: Kurt Hornik <Kurt.Hornik@ci.tuwien.ac.at>
+## Adapted-By: jwe
+## Adapted from deblank by A. S. Hodel (a.s.hodel@eng.auburn.edu)
+## 	(the name dezero is a reference to the Fermilab D0 experiment,
+##      where my sister did her PhD research) 
+## $Revision: 1.1.1.1 $
+## $Log: dezero.m,v $
+## Revision 1.1.1.1  1998/05/19 20:24:13  jwe
+##
+## Revision 1.3  1997/03/11 14:42:41  scotte
+## fixed implicit_str_to_num_ok bug a.s.hodel@eng.auburn.edu
+##
+## Revision 1.2  1997/03/03 22:52:20  hodel
+## fixed problem with conversion to/from numerical value
+## a.s.hodel@eng.auburn.edu
+##
+## Revision 1.1  1997/02/12 11:34:56  hodel
+## Initial revision
+##
+## Revision 1.3  1997/02/07 15:24:35  scotte
+## fixed to remove all null characters, then call deblank
+##
+
+function t = dezero (s)
+
+  if (nargin != 1)
+    usage ("dezero (s)");
+  elseif (isstr (s))
+
+    save_val = implicit_str_to_num_ok;
+    implicit_str_to_num_ok = 1;
+
+    #disp("dezero: entry, s=")
+    #s
+    #disp("/dezero")
+
+    [nr, nc] = size (s);
+    len = nr * nc;
+
+    if (len == 0)
+      t = s;
+    else
+
+      #disp("dezero: 1, s=")
+      #s
+      #disp("/dezero")
+
+      s = reshape (s, 1, len);
+
+      #disp("dezero: 2, s=")
+      #s
+      #disp("/dezero")
+
+      # need to remove zeros first, then call deblank
+      s = 1*s;
+      t = deblank(setstr(s(find(s != 0) )));
+    endif
+
+    implicit_str_to_num_ok = save_val;
+
+  else
+    error ("dezero: expecting string argument");
+  endif
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/dgkfdemo.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,363 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function dgkfdemo()
+# Octave Controls toolbox demo: H2/Hinfinity options demos
+# Written by A. S. Hodel June 1995
+# $Revision: 1.2 $
+# $Log: dgkfdemo.m,v $
+# Revision 1.2  1998/08/24 15:50:06  hodelas
+# updated documentation
+#
+# Revision 1.1.1.1  1998/05/19 20:24:06  jwe
+#
+# Revision 1.5  1998/05/05 17:03:18  scotte
+# update 5 May 1998 by Kai Mueller
+#
+# Revision 1.2  1998/05/05  10:02:46  mueller
+# new H_inf demo (jet707 MIMO design)
+#
+# Revision 1.1  1998/05/05  09:59:28  mueller
+# Initial revision
+#
+ 
+  save_val = page_screen_output;
+  page_screen_output = 1;
+  while (1)
+    clc
+    menuopt=0;
+    while(menuopt > 10 || menuopt < 1)
+      menuopt = menu('Octave H2/Hinfinity options demo', ...
+	    'LQ regulator', ...
+	    'LG state estimator', ...
+	    'LQG optimal control design', ...
+	    'H2 gain of a system', ...
+	    'H2 optimal controller of a system', ...
+	    'Hinf gain of a system', ...
+	    'Hinf optimal controller of a SISO system', ...
+	    'Hinf optimal controller of a MIMO system', ...
+	    'Discrete-time Hinf optimal control by bilinear transform', ...
+	    'Return to main demo menu');
+    endwhile
+    if (menuopt == 1)
+      disp('Linear/Quadratic regulator design:')
+      disp('Compute optimal state feedback via the lqr command...')
+      help lqr
+      disp(' ')
+      disp('Example:')
+      A = [0 1; -2 -1]
+      B = [0; 1]
+      Q = [1 0; 0 0]
+      R = 1
+      disp("Q = state penalty matrix; R = input penalty matrix")
+      prompt
+      disp('Compute state feedback gain k, ARE solution P, and closed-loop')
+      disp('poles as follows:');
+      cmd = "[k p e] = lqr(A,B,Q,R)";
+      run_cmd
+      prompt
+      disp("A similar approach can be used for LTI discrete-time systems")
+      disp("by using the dlqr command in place of lqr (see LQG example).")
+    elseif (menuopt == 2)
+      disp('Linear/Gaussian estimator design:')
+      disp('Compute optimal state estimator via the lqe command...')
+      help lqe
+      disp(' ')
+      disp('Example:')
+      A = [0 1; -2 -1]
+      disp("disturbance entry matrix G")
+      G = eye(2)
+      disp("Output measurement matrix C")
+      C = [0  1]
+      SigW = [1 0; 0 1]
+      SigV = 1
+      disp("SigW = input disturbance intensity matrix;")
+      disp("SigV = measurement noise intensity matrix")
+      prompt
+      disp('Compute estimator feedback gain k, ARE solution P, and estimator')
+      disp('poles via the command: ')
+      cmd = "[k p e] = lqe(A,G,C,SigW,SigV)";
+      run_cmd
+      disp("A similar approach can be used for LTI discrete-time systems")
+      disp("by using the dlqe command in place of lqe (see LQG example).")
+    elseif (menuopt == 3)
+      disp('LQG optimal controller of a system:')
+      disp('Input accepted as either A,B,C matrices or in system data structure form')
+      disp('in both discrete and continuous time.')
+      disp("Example 1: continuous time design:")
+      prompt
+      help lqg
+      disp("Example system")
+      A = [0 1; .5 .5];
+      B = [0 ; 2];
+      G = eye(2)
+      C = [1 1];
+      sys = ss2sys(A,[B G],C);
+      sys = syschnames(sys,"in",1:3, \
+		       ["control input"; "disturbance 1"; "disturbance 2"]);
+      sysout(sys)
+      prompt
+      disp("Filtering/estimator parameters:")
+      SigW = eye(2)
+      SigV = 1
+      prompt
+      disp("State space (LQR) parameters Q and R are:")
+      Q = eye(2)
+      R = 1
+      cmd = "[K,Q1,P1,Ee,Er] = lqg(sys,SigW,SigV,Q,R,1);";
+      run_cmd
+      disp("Check: closed loop system A-matrix is")
+      disp(" [A      B*Cc]")
+      disp(" [Bc*C   Ac  ]")
+      cmd = "[Ac,Bc,Cc] = sys2ss(K);";
+      run_cmd
+      cmd = "Acl = [A , B*Cc ; Bc*C  Ac]";
+      run_cmd
+      disp("Check: poles of Acl:")
+      Acl_poles = sortcom(eig(Acl))
+      disp("Predicted poles from design = union(Er,Ee)")
+      cmd = "pred_poles = sortcom([Er;Ee])";
+      run_cmd
+      disp("Example 2: discrete-time example")
+      cmd1 = "Dsys = ss2sys(A,[G B],C,[0 0 0],1);";
+      cmd2 = "[K,Q1,P1,Ee,Er] = lqg(Dsys,SigW, SigV,Q,R);";
+      disp("Run commands:")
+      cmd = cmd1;
+      run_cmd
+      cmd = cmd2;
+      run_cmd
+      prompt
+      disp("Check: closed loop system A-matrix is")
+      disp(" [A      B*Cc]")
+      disp(" [Bc*C   Ac  ]")
+      [Ac,Bc,Cc] = sys2ss(K);
+      Acl = [A , B*Cc ; Bc*C  Ac]
+      prompt
+      disp("Check: poles of Acl:")
+      Acl_poles = sortcom(eig(Acl))
+      disp("Predicted poles from design = union(Er,Ee)")
+      pred_poles = sortcom([Er;Ee])
+    elseif (menuopt == 4)
+      disp('H2 gain of a system: (Energy in impulse response)')
+      disp('Example 1: Stable plant:')
+      cmd = "A = [0 1; -2 -1]; B = [0 ; 1]; C = [1 0]; sys_poles = eig(A)";
+      run_cmd
+      disp("Put into Packed system form:")
+      cmd = "Asys = ss2sys(A,B,C);";
+      run_cmd
+      disp("Evaluate system 2-norm (impulse response energy):");
+      cmd = "AsysH2 = h2norm(Asys)";
+      run_cmd
+      disp("Compare with a plot of the system impulse response:")
+      tt = 0:0.1:20;
+      for ii=1:length(tt)
+        ht(ii) = C*expm(A*tt(ii))*B;
+      endfor
+      plot(tt,ht)
+      title("impulse response of example plant")
+      prompt
+      disp('Example 2: unstable plant')
+      cmd = "A = [0 1; 2 1]";
+      eval(cmd);
+      cmd = "B = [0 ; 1]";
+      eval(cmd);
+      cmd = "C = [1 0]";
+      eval(cmd);
+      cmd = "sys_poles = eig(A)";
+      run_cmd
+      prompt
+      disp('Put into system data structure form:')
+      cmd="Bsys = ss2sys(A,B,C);";
+      run_cmd
+      disp('Evaluate 2-norm:')
+      cmd = "BsysH2 = h2norm(Bsys)";
+      run_cmd
+      disp(' ')
+      prompt('NOTICE: program returns a value without an error signal.')
+      disp('')
+
+    elseif (menuopt == 5)
+      disp('H2 optimal controller of a system: command = h2syn:')
+      prompt
+      help h2syn
+      prompt
+      disp("Example system: double integrator with output noise and")
+      disp("input disturbance:")
+      disp(" ");
+      disp("       -------------------->y2");
+      disp("       |   _________");
+      disp("u(t)-->o-->| 1/s^2 |-->o-> y1");
+      disp("       ^   ---------   ^");
+      disp("       |               |");
+      disp("      w1(t)           w2(t)");
+      disp(" ")
+      disp("w enters the system through B1, u through B2")
+      disp("z = [y1 ; y2] is obtained through C1, y=y1 through C2");
+      disp(" ")
+      cmd = "A = [0 1; 0 0]; B1 = [0 0;1 0]; B2 = [0;1];";
+      disp(cmd)
+      eval(cmd);
+      cmd = "C1 = [1 0; 0 0]; C2 = [1 0]; D11 = zeros(2);";
+      disp(cmd)
+      eval(cmd);
+      cmd = "D12 = [0;1]; D21 = [0 1]; D22 = 0; D = [D11 D12; D21 D22];";
+      disp(cmd)
+      eval(cmd);
+      disp("Design objective: compute U(s)=K(s)Y1(s) to minimize the closed")
+      disp("loop impulse response from w(t) =[w1; w2] to z(t) = [y1; y2]");
+      prompt
+      disp("First: pack system:")
+      cmd="Asys = ss2sys(A,[B1 B2], [C1;C2] , D);";
+      run_cmd
+      disp("Open loop multivariable Bode plot: (will take a moment)")
+      cmd="bode(Asys);";
+      run_cmd
+      prompt("Press a key to close plot and continue");
+      closeplot
+      disp("Controller design command: (only need 1st two output arguments)")
+      cmd="[K,gain, Kc, Kf, Pc,  Pf] = h2syn(Asys,1,1);";
+      run_cmd
+      disp("Controller is:")
+      cmd = "sysout(K)";
+      run_cmd
+      disp(["returned gain value is: ",num2str(gain)]);
+      disp("Check: close the loop and then compute h2norm:")
+      prompt
+      cmd="K_loop = sysgroup(Asys,K);";
+      run_cmd
+      cmd = "Kcl = sysconnect(K_loop,[3,4],[4,3]);";
+      run_cmd
+      cmd = "Kcl = sysprune(Kcl,[1,2],[1,2]);";
+      run_cmd
+      cmd="gain_Kcl = h2norm(Kcl)";
+      run_cmd
+      cmd="gain_err = gain_Kcl - gain";
+      run_cmd
+      disp("Check: multivarible bode plot:")
+      cmd="bode(Kcl);";
+      run_cmd
+      prompt
+      disp("Related functions: is_dgkf, is_controllable, is_stabilizable,")
+      disp("                is_observable, is_detectable")
+    elseif (menuopt == 6)
+      disp('Hinfinity gain of a system: (max gain over all j-omega)')
+      disp('Example 1: Stable plant:')
+      cmd = "A = [0 1; -2 -1]; B = [0 ; 1]; C = [1 0]; sys_poles = eig(A)";
+      run_cmd
+      disp('Pack into system format:')
+      cmd = "Asys = ss2sys(A,B,C);";
+      run_cmd
+      disp('The infinity norm must be computed iteratively by')
+      disp('binary search.  For this example, we select tolerance tol = 0.01, ')
+      disp('min gain gmin = 1e-2, max gain gmax=1e4.')
+      disp('Search quits when upper bound <= (1+tol)*lower bound.')
+      cmd = "tol = 0.01; gmin = 1e-2; gmax = 1e+4;";
+      run_cmd
+      cmd = "AsysH2 = hinfnorm(Asys,tol,gmin,gmax)"
+      run_cmd
+      disp("Check: look at max value of magntude Bode plot of Asys:");
+      [M,P,w] = bode(Asys);
+      loglog(w,M);
+      xlabel('Omega')
+      ylabel('|Asys(j omega)|')
+      disp(["Max magnitude is ",num2str(max(M)), ...
+	", compared with gmin=",num2str(gmin)," and gmax=", ...
+        num2str(gmax),"."])
+      prompt
+      disp('Example 2: unstable plant')
+      cmd = "A = [0 1; 2 1]; B = [0 ; 1]; C = [1 0]; sys_poles = eig(A)";
+      run_cmd
+      disp("Pack into system format:")
+      cmd = "Bsys = ss2sys(A,B,C);";
+      run_cmd
+      disp('Evaluate with BsysH2 = hinfnorm(Bsys,tol,gmin,gmax)')
+      BsysH2 = hinfnorm(Bsys,tol,gmin,gmax)
+      disp(' ')
+      disp('NOTICE: program returns a value without an error signal.')
+      disp('')
+
+    elseif (menuopt == 7)
+      disp('Hinfinity optimal controller of a system: command = hinfsyn:')
+      prompt
+      help hinfsyn
+      prompt
+      disp("Example system: double integrator with output noise and")
+      disp("input disturbance:")
+      A = [0 1; 0 0]
+      B1 = [0 0;1 0]
+      B2 = [0;1]
+      C1 = [1 0; 0 0]
+      C2 = [1 0]
+      D11 = zeros(2);
+      D12 = [0;1];
+      D21 = [0 1];
+      D22 = 0;
+      D = [D11 D12; D21 D22]
+      prompt
+      disp("First: pack system:")
+      cmd="Asys = ss2sys(A,[B1 B2], [C1;C2] , D)";
+      run_cmd
+      prompt
+      disp("Open loop multivariable Bode plot: (will take a moment)")
+      cmd="bode(Asys);";
+      run_cmd
+      prompt
+      disp("Controller design command: (only need 1st two output arguments)")
+      gmax = 1000
+      gmin = 0.1
+      gtol = 0.01
+      cmd="[K,gain] = hinfsyn(Asys,1,1,gmin,gmax,gtol)";
+      run_cmd
+      disp("Check: close the loop and then compute h2norm:")
+      prompt
+      cmd="K_loop = sysgroup(Asys,K);";
+      run_cmd
+      cmd = "Kcl = sysconnect(K_loop,[3,4],[4,3]);";
+      run_cmd
+      cmd = "Kcl = sysprune(Kcl,[1,2],[1,2]);";
+      run_cmd
+      cmd="gain_Kcl = hinfnorm(Kcl)";
+      run_cmd
+      cmd="gain_err = gain_Kcl - gain";
+      run_cmd
+      disp("Check: multivarible bode plot:")
+      cmd="bode(Kcl);";
+      run_cmd
+      prompt
+      disp("Related functions: is_dgkf, is_controllable, is_stabilizable,")
+      disp("                   is_observable, is_detectable, buildssic")
+    elseif (menuopt == 8)
+      disp('Hinfinity optimal controller of MIMO system: command = hinfsyn:')
+      prompt
+      help hinfsyn
+      prompt
+      disp("Example system: Boeing 707-321 airspeed/pitch angle control")
+      disp(" ")
+      hinfdemo
+    elseif (menuopt == 9)
+      disp("Discrete time H-infinity control via bilinear transform");
+      prompt
+      dhinfdemo
+    elseif (menuopt == 10)
+      return
+    endif
+    prompt
+  endwhile  
+  page_screen_output = save_val;
+endfunction
+
--- a/scripts/control/dgram.m	Thu Nov 05 04:24:46 1998 +0000
+++ b/scripts/control/dgram.m	Fri Nov 06 16:16:31 1998 +0000
@@ -1,38 +1,32 @@
-## Copyright (C) 1996, 1997 John W. Eaton
-##
-## 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-1307, USA.
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function m = dgram(a,b)
+  # m = dgram(a,b)
+  # Return controllability grammian of discrete time system
+  #
+  #  x(k+1) = a x(k) + b u(k)
+  #
+  # a m a' - m + b*b' = 0 
 
-##  Usage: gramian = dgram (A, B)
-##
-##  Returns the discrete controllability and observability gramian.
-##
-##  dgram (A, B)   returns the discrete controllability gramian.
-##  dgram (A', C') returns the observability gramian.
+  # Written by A. S. Hodel July 1995
+  # $Revision: 1.11 $
 
-## Author: R. Bruce Tenison <btenison@eng.auburn.edu>
-## Created: October 1993
-## Adapted-By: jwe
-
-
-function gramian = dgram (A, B)
-
-  [U, Sig, V] = svd (B);
-
-  gramian = U * dlyap (U'*A*U, Sig*Sig') * U';
-
+  # let dlyap do the error checking...
+  m = dlyap(a,b*b');
 endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/dhinfdemo.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,127 @@
+# ------------------------------------------------------------
+# dhinfdemo   Design of a discrete H_infinity controller.
+#             This is not a true discrete design. The design
+#             is carried out in continuous time while the
+#             effect of sampling is described by a bilinear
+#             transformation of the sampled system.
+#             This method works quite well if the sampling
+#             period is "small" compared to the plant time
+#             constants.
+#
+# This is a script file for OCTAVE.
+# ------------------------------------------------------------
+#
+# continuous plant:
+#	             1
+#	G(s) = --------------
+#	       (s + 2)(s + 1)
+#
+# discretised plant with ZOH (Sampling period = Ts = 1 second)
+#
+#	           0.39958z + 0.14700
+#	G(s) = --------------------------
+#	       (z - 0.36788)(z - 0.13533)
+#
+#	                         +----+
+#	    -------------------->| W1 |---> v1
+#	z   |                    +----+
+#	----|-------------+                   || T   ||     => min.
+#	    |             |                       vz   infty
+#	    |    +---+    v      +----+
+#	    *--->| G |--->O--*-->| W2 |---> v2
+#	    |    +---+       |   +----+
+#	    |                |
+#	    |    +---+       |
+#	    -----| K |<-------
+#	         +---+
+#
+#	W1 and W2 are the robustness and performancs weighting
+#       functions
+
+# K. Mueller, <mueller@ifr.ing.tu-bs.de>
+# Technical University of Braunschweig, IfR
+# $Revision: 1.2 $  $Date: 1998/10/12 10:11:13 $
+#
+
+echo off
+disp(" ");
+disp("    --------------------------------------------------");
+disp("    Discrete H_infinity optimal control for the plant:");
+disp(" ");
+disp("	                   0.39958z + 0.14700");
+disp("	        G(s) = --------------------------");
+disp("	               (z - 0.36788)(z - 0.13533)");
+disp("    --------------------------------------------------");
+disp(" ");
+
+disp("sampling time:")
+cmd = "Ts = 1.0;";
+disp(cmd);
+eval(cmd);
+disp("weighting on actuator value u");
+cmd = "W1 = wgt1o(0.1, 200.0, 50.0);";
+disp(cmd);
+eval(cmd);
+disp("weighting on controlled variable y");
+cmd = "W2 = wgt1o(350.0, 0.05, 0.0002);";
+disp(cmd);
+eval(cmd);
+# omega axis (column vector)
+ww = vec(logspace(-4.99, 3.99, 100));
+
+disp("Create ZOH equivalent model of a continuous plant");
+cmd = "G = tf2sys(2,[1 3 2]);  Gd = c2d(G, Ts);";
+run_cmd
+
+# w-plane (continuous representation of the sampled system)
+disp("W-plane transform of discrete time system:");
+cmd = "Gw = d2c(Gd, \"bi\");";
+run_cmd
+
+disp(" ");
+disp(" o building P...");
+# need One as the pseudo transfer function One = 1
+cmd = "One = ugain(1);";
+disp(cmd);
+eval(cmd);
+cmd = " psys = buildssic([1 4;2 4;3 1],[3],[2 3 5],[3 4],Gw,W1,W2,One);";
+run_cmd;
+disp(" o controller design...");
+cmd = "[K, gfin, GWC] = hinfsyn(psys, 1, 1, 0.1, 10.0, 0.02);";
+run_cmd
+
+disp(" ");
+fig_n = 1;
+yn = input(" * Plot magnitudes of W1KS and W2S? [n]: ","S");
+if (length(yn) >= 1)
+  if ((yn(1) == "y") || (yn(1) == 'Y'))
+    disp(" o magnitudes of W1KS and W2S...");
+    gwx = sysprune(GWC, 1, 1);
+    mag1 = bode(gwx, ww);
+    if (columns(mag1) > 1);  mag1 = mag1';  endif
+    gwx = sysprune(GWC, 2, 1);
+    mag2 = bode(gwx, ww);
+    if (columns(mag2) > 1);  mag2 = mag2';  endif
+    figure(fig_n)
+    fig_n = fig_n + 1;
+    gset grid
+    loglog(ww, [mag1 mag2]);
+  endif
+endif
+
+Kd = c2d(K, "bi", Ts);
+GG = buildssic([1 2; 2 1], [], [1 2], [-2], Gd, Kd);
+disp(" o closed loop poles...");
+damp(GG);
+
+disp(" ");
+yn = input(" * Plot closed loop step responses? [n]: ","S");
+if (length(yn) >= 1)
+  if ((yn(1) == "y") || (yn(1) == 'Y'))
+    disp(" o step responses of T and KS...");
+    figure(fig_n)
+    step(GG, 1, 10);
+  endif
+endif
+
+# --------- End of dhinfdemo/kpm
--- a/scripts/control/dlqe.m	Thu Nov 05 04:24:46 1998 +0000
+++ b/scripts/control/dlqe.m	Fri Nov 06 16:16:31 1998 +0000
@@ -1,67 +1,66 @@
-## Copyright (C) 1996, 1997 John W. Eaton
-##
-## 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-1307, USA.
+# Copyright (C) 1993, 1994, 1995 John W. Eaton
+# 
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+function [l, m, p, e] = dlqe (a, g, c, sigw, sigv, s)
 
-## Usage: [l, m, p, e] = dlqe (A, G, C, SigW, SigV {,Z})
-##
-## Linear quadratic estimator (Kalman filter) design for the
-## discrete time system
-##
-##  x[k+1] = A x[k] + B u[k] + G w[k]
-##    y[k] = C x[k] + D u[k] + w[k]
-##
-## where w, v are zero-mean gaussian noise processes with respective
-## intensities SigW = cov (w, w) and SigV = cov (v, v).
-##
-## Z (if specified) is cov(w,v); otherwise cov(w,v) = 0.
-##
-## Observer structure is
-##     z[k+1] = A z[k] + B u[k] + k(y[k] - C z[k] - D u[k]).
-##
-## Returns:
-##
-##   l = observer gain, (A - A L C) is stable
-##   m = Ricatti equation solution
-##   p = the estimate error covariance after the measurement update
-##   e = closed loop poles of (A - A L C)
+# Usage: [l, m, p, e] = dlqe (A, G, C, SigW, SigV {,S})
+#
+# Linear quadratic estimator (Kalman filter) design for the 
+# discrete time system
+#
+#  x[k+1] = A x[k] + B u[k] + G w[k]
+#    y[k] = C x[k] + D u[k] + w[k]
+#
+# where w, v are zero-mean gaussian noise processes with respective
+# intensities SigW = cov (w, w) and SigV = cov (v, v).
+#
+# S (if specified) is cov(w,v); otherwise cov(w,v) = 0.
+#
+# Observer structure is 
+#     z[k+1] = A z[k] + B u[k] + k(y[k] - C z[k] - D u[k]).
+#
+# Returns:
+#
+#   l = observer gain, (A - L C) is stable
+#   m = Ricatti equation solution
+#   p = the estimate error covariance after the measurement update
+#   e = closed loop poles of (A - L C)
 
-## Author: A. S. Hodel <scotte@eng.auburn.edu>
-##         R. Bruce Tenison <btenison@eng.auburn.edu>
-## Created: August 1993
-## Adapted-By: jwe
+# Written by A. S. Hodel (scotte@eng.auburn.edu) August, 1993.
+# Modified for discrete time by R. Bruce Tenison (btenison@eng.auburn.edu)
+# October, 1993
 
-function [l, m, p, e] = dlqe (a, g, c, sigw, sigv, zz)
+# $Revision: 1.14 $
 
   if (nargin != 5 && nargin != 6)
     error ("dlqe: invalid number of arguments");
   endif
 
-  ## The problem is dual to the regulator design, so transform to lqr
-  ## call.
+# The problem is dual to the regulator design, so transform to dlqr call.
 
   if (nargin == 5)
     [k, p, e] = dlqr (a', c', g*sigw*g', sigv);
-    m = p';
-    l = (m*c')/(c*m*c'+sigv);
+    m = p;
+    l = k';
   else
-    [k, p, e] = dlqr (a', c', g*sigw*g', sigv, g*zz);
-    m = p';
-    l = (m*c'+a\g)/(c*m*c'+sigv);
+    [k, p, e] = dlqr (a', c', g*sigw*g', sigv, g*s);
+    m = p;
+    l = k';
     a = a-g*t/sigv*c;
     sigw = sigw-t/sigv;
   endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/dlqg.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,125 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [K,Q,P,Ee,Er] = dlqg(A,B,C,G,Sigw, Sigv,Q,R)
+#
+#
+#  O B S O L E T E * * * D O   N O T   U S E!
+#
+#  Use lqg instead.
+#
+# function [K,Q,P,Ee,Er] = dlqg(A,B,C,G,Sigw,Sigv,Q,R)
+# function [K,Q,P,Ee,Er] = dlqg(Sys,Sigw,Sigv,Q,R)
+# 
+# design a discrete-time linear quadratic gaussian optimal controller
+# for the system
+#
+#  x(k+1) = A x(k) + B u(k) + G w(k)       [w]=N(0,[Sigw 0    ])
+#    y(k) = C x(k) + v(k)                  [v]  (    0   Sigv ])
+#
+# Outputs:
+#    K: system data structure format LQG optimal controller
+#    P: Solution of control (state feedback) algebraic Riccati equation
+#    Q: Solution of estimation algebraic Riccati equation
+#    Ee: estimator poles
+#    Es: controller poles
+# inputs:
+#  A,B,C,G, or Sys: state space representation of system.  
+#  Sigw, Sigv: covariance matrices of independent Gaussian noise processes 
+#      (as above)
+#  Q, R: state, control weighting matrices for dlqr call respectively.  
+#
+# See also: lqg, dlqe, dlqr
+
+# Written by A. S. Hodel August 1995
+# $Revision: 1.2 $
+
+warning("dlqg: obsolete. use lqg instead (system data structure format)");
+
+if (nargin == 5)
+  # system data structure format
+  
+  # check that it really is system data structure
+  if(! is_struct(A) )
+    error("dlqg: 5 arguments, first argument is not a system data structure structure")
+  endif
+
+  sys = sysupdate(sys,"ss");    # make sure in proper form
+  [ndstates,nin,nout] = abcddim(sys.a, sys.b, sys.c, sys.d);
+  if(ndstates == -1)
+    error("this message should never appear: bad system dimensions");
+  endif
+
+  if(sys.n)
+    error("dlqg: system has continuous-time states (try lqg?)")
+  elseif(sys.nz < 1)
+    error("dlqg: system has no discrete time states")
+  elseif(nin <= columns(Sigw))
+    error(["dlqg: ",num2str(nin)," inputs provided, noise dimension is ", ...
+	num2str(columns(Sigw))])
+  elseif(nout != columns(Sigv))
+    error(["dlqg: number of outputs (",num2str(nout),") incompatible with ", ...
+	"dimension of Sigv (",num2str(columns(Sigv)),")"])
+  endif
+
+  # put parameters into correct variables
+  R = Sigw;
+  Q = G;
+  Sigv = C;
+  Sigw = B;
+  [A,B,C,D] = sys2ss(Sys)
+  [n,m] = size(B)
+  m1 = columns(Sigw);
+  m2 = m1+1;
+  G = B(:,1:m1);
+  B = B(:,m2:m);
+
+elseif (nargin == 8)
+  # state-space format
+  m = columns(B);
+  m1 = columns(G);
+  p = rows(C);
+  n = abcddim(A,B,C,zeros(p,m));
+  n1 = abcddim(A,G,C,zeros(p,m1));
+  if( (n == -1) || (n1 == -1))
+    error("dlqg: A,B,C,G incompatibly dimensioned");
+  elseif(p != columns(Sigv))
+    error("dlqg: C, Sigv incompatibly dimensioned");
+  elseif(m1 != columns(Sigw))
+    error("dlqg: G, Sigw incompatibly dimensioned");
+  endif
+else
+  error("dlqg: illegal number of arguments")
+endif
+
+if (! (is_square(Sigw) && is_square(Sigv) ) )
+  error("dlqg: Sigw, Sigv must be square");
+endif
+
+# now we can just do the design; call dlqr and dlqe, since all matrices
+# are not given in Cholesky factor form (as in h2syn case)
+[Ks P Er] = dlqr(A,B,Q,R);
+[Ke Q jnk Ee] = dlqe(A,G,C,Sigw,Sigv);
+Ac = A - Ke*C - B*Ks;
+Bc = Ke;
+Cc = -Ks;
+Dc = zeros(rows(Cc),columns(Bc));
+K = ss2sys(Ac,Bc,Cc,Dc,1);
+disp("HODEL: need to add names to this guy!")
+
+endfunction
--- a/scripts/control/dlqr.m	Thu Nov 05 04:24:46 1998 +0000
+++ b/scripts/control/dlqr.m	Fri Nov 06 16:16:31 1998 +0000
@@ -1,98 +1,102 @@
-## Copyright (C) 1996, 1997 John W. Eaton
-##
-## 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-1307, USA.
+# Copyright (C) 1993, 1994, 1995 John W. Eaton
+# 
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+function [k, p, e] = dlqr (a, b, q, r, s)
 
-## Usage: [k, p, e] = dlqr (A, B, Q, R {,Z})
-##
-## Linear quadratic regulator design for the discrete time system
-##
-##   x[k+1] = A x[k] + B u[k]
-##
-## to minimize the cost functional
-##
-##  J = Sum { x' Q x + u' R u } 			Z omitted
-##
-## or
-##
-##  J = Sum { x' Q x + u' R u +2 x' Z u}		Z included
-##
-## Returns:
-##
-##   k = state feedback gain, (A - B K) is stable
-##   p = solution of algebraic Riccati equation
-##   e = closed loop poles of (A - B K)
-
-## Author: A. S. Hodel <scotte@eng.auburn.edu>
-##         R. B. Tenison <btenison@eng.auburn.edu>
-## Created: August 1993
-## Adapted-By: jwe
-
-function [k, p, e] = dlqr (a, b, q, r, zz)
+# Usage: [k, p, e] = dlqr (A, B, Q, R {,S})
+#
+# Linear quadratic regulator design for the discrete time system
+#
+#   x[k+1] = A x[k] + B u[k]
+#
+# to minimize the cost functional
+#
+#  J = Sum { x' Q x + u' R u } 			S omitted
+#
+# or
+#
+#  J = Sum { x' Q x + u' R u +2 x' S u}		S included
+#
+# Returns:
+#
+#   k = state feedback gain, (A - B K) is stable
+#   p = solution of algebraic Riccati equation
+#   e = closed loop poles of (A - B K)
+#
+# References:
+#   Anderson and Moore, Optimal Control: Linear Quadratic Methods,
+#     Prentice-Hall, 1990, pp. 56-58
+#   Kuo, Digital Control Systems, Harcourt Brace Jovanovich, 1992, 
+#     section 11-5-2.
+# Written by A. S. Hodel (scotte@eng.auburn.edu) August 1993.
+# Converted to discrete time by R. B. Tenison
+# (btenison@eng.auburn.edu) October 1993
+# $Revision: 1.15 $
 
   if (nargin != 4 && nargin != 5)
     error ("dlqr: invalid number of arguments");
   endif
 
-  ## Check a.
+# Check a.
   if ((n = is_square (a)) == 0)
     error ("dlqr: requires 1st parameter(a) to be square");
   endif
 
-  ## Check b.
+# Check b.
   [n1, m] = size (b);
   if (n1 != n)
     error ("dlqr: a,b not conformal");
   endif
 
-  ## Check q.
-
+# Check q.
+  
   if ((n1 = is_square (q)) == 0 || n1 != n)
     error ("dlqr: q must be square and conformal with a");
   endif
 
-  ## Check r.
+# Check r.
   if((m1 = is_square(r)) == 0 || m1 != m)
     error ("dlqr: r must be square and conformal with column dimension of b");
   endif
 
-  ## Check if n is there.
+# Check if n is there.
   if (nargin == 5)
-    [n1, m1] = size (zz);
+    [n1, m1] = size (s);
     if (n1 != n || m1 != m)
       error ("dlqr: z must be identically dimensioned with b");
     endif
 
-    ## Incorporate cross term into a and q.
+# Incorporate cross term into a and q.
 
-    ao = a - (b/r)*zz';
-    qo = q - (zz/r)*zz';
+    ao = a - (b/r)*s';
+    qo = q - (s/r)*s';
   else
-    zz = zeros (n, m);
+    s = zeros (n, m);
     ao = a;
     qo = q;
   endif
 
-  ## Check that q, (r) are symmetric, positive (semi)definite
+# Check that q, (r) are symmetric, positive (semi)definite
 
   if (is_symmetric (q) && is_symmetric (r) ...
       && all (eig (q) >= 0) && all (eig (r) > 0))
     p = dare (ao, b, qo, r);
-    k = (r+b'*p*b)\b'*p*ao + r\zz';
+    k = (r+b'*p*b)\b'*p*a + r\s';
     e = eig (a - b*k);
   else
     error ("dlqr: q (r) must be symmetric positive (semi) definite");
--- a/scripts/control/dlyap.m	Thu Nov 05 04:24:46 1998 +0000
+++ b/scripts/control/dlyap.m	Fri Nov 06 16:16:31 1998 +0000
@@ -1,43 +1,41 @@
-## Copyright (C) 1996, 1997 John W. Eaton
-##
-## 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-1307, USA.
-
-## Usage: x = dlyap (a, b)
-##
-## Solve a x a' - x + b = 0 (discrete Lyapunov equation) for square
-## matrices a and b.  If b is not square, then the function attempts
-## to solve either
-##
-##  a x a' - x + b b' = 0
-##
-## or
-##
-##  a' x a - x + b' b = 0
-##
-## whichever is appropriate.  Uses Schur decomposition as in Kitagawa
-## (1977).
-
-## Author: A. S. Hodel <scotte@eng.auburn.edu>
-## Created: August 1993
-## Adapted-By: jwe
+# Copyright (C) 1993, 1994, 1995 John W. Eaton
+# 
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA.
 
 function x = dlyap (a, b)
 
+# Usage: x = dlyap (a, b)
+#
+# Solve a x a' - x + b = 0 (discrete Lyapunov equation) for square
+# matrices a and b.  If b is not square, then the function attempts 
+# to solve either
+#
+#  a x a' - x + b b' = 0
+#
+# or
+#
+#  a' x a - x + b' b = 0
+#
+# whichever is appropriate.  Uses Schur decomposition as in Kitagawa
+# (1977).
+
+# Written by A. S. Hodel (scotte@eng.auburn.edu) August 1993.
+# $Revision: 1.13 $
+
   if ((n = is_square (a)) == 0)
     warning ("dlyap: a must be square");
   endif
@@ -57,7 +55,7 @@
     warning ("dlyap: a,b not conformably dimensioned");
   endif
 
-  ## Solve the equation column by column.
+  # Solve the equation column by column.
 
   [u, s] = schur (a);
   b = u'*b*u;
@@ -66,7 +64,7 @@
   while (j > 0)
     j1 = j;
 
-    ## Check for Schur block.
+# Check for Schur block.
 
     if (j == 1)
       blksiz = 1;
@@ -97,7 +95,7 @@
 
   endwhile
 
-  ## Back-transform to original coordinates.
+# Back-transform to original coordinates.
 
   x = u*x*u';
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/dmr2d.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,260 @@
+# Copyright (C) 1998 A. S. Hodel
+# 
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+function [dsys,fidx] = dmr2d (sys, idx, sprefix, Ts2,cuflg)
+
+# Usage: [dsys,fidx] = dmr2d (sys, idx, sprefix, Ts2 {,cuflg})
+# convert a multirate digital system to a single rate digital system
+# states specified by idx, sprefix are sampled at Ts2, all others
+# are sampled at Ts1 = sysgettsam(sys).
+# inputs:
+#   sys: discrete time system;
+#        dmr2d exits with an error if sys is not discrete
+#   idx: list of states with sampling time sys.tsam (may be empty)
+#   sprefix: string prefix of states with sampling time sys.tsam (may be empty)
+#   Ts2: sampling time of states not specified by idx, sprefix
+#        must be an integer multiple of sys.tsam
+#   cuflg: "constant u flag" if cuflg is nonzero then the system inputs are 
+#        assumed to be constant over the revised sampling interval Ts2.
+#        Otherwise, since the inputs can change during the interval
+#        t in [k Ts2, (k+1) Ts2], an additional set of inputs is
+#        included in the revised B matrix so that these intersample inputs
+#        may be included in the single-rate system.
+#        default: cuflg = 1.
+#
+# outputs: 
+#   dsys: equivalent discrete time system with sampling time Ts2.
+#
+#         The sampling time of sys is updated to Ts2.
+#
+#         if cuflg=0 then a set of additional inputs is added to
+#         the system with suffixes _d1, ..., _dn to indicate their
+#         delay from the starting time k Ts2, i.e.
+#         u = [u_1; u_1_d1; ..., u_1_dn] where u_1_dk is the input
+#             k*Ts1 units of time after u_1 is sampled. (Ts1 is
+#             the original sampling time of discrete time sys and
+#             Ts2 = (n+1)*Ts1)
+#
+#   fidx: indices of "formerly fast" states specified by idx and sprefix;
+#         these states are updated to the new slower) sampling interval
+#
+#
+#  WARNING: Not thoroughly tested yet; especially when cuflg == 0.
+
+# Adapted from c2d by a.s.hodel@eng.auburn.edu
+# $Log: dmr2d.m,v $
+# Revision 1.1  1998/07/21 14:40:55  hodelas
+# First attempt at multirate systems analysis
+#
+# Revision 1.2  1998/07/21 14:13:44  hodel
+# squaring A  to get a11^nstp
+#
+# Revision 1.1  1998/07/21 12:41:46  hodel
+# Initial revision
+#
+#
+  save_val = implicit_str_to_num_ok;	# save for later
+  implicit_str_to_num_ok = 1;
+
+  # parse input arguments
+  if(nargin != 4 | nargout > 2)
+    usage("[dsys,fidx] = dmr2d (sys, idx, sprefix, Ts2 {,cuflg})");
+
+  elseif (!is_struct(sys))
+    error("sys must be in system data structure form");
+
+  elseif(!is_digital(sys))
+    error("sys must be discrete-time; continuous time passed");
+
+  elseif (!(is_vector(idx) | isempty(idx)))
+    error(["idx(",num2str(rows(idx)),"x",num2str(columns(idx)), ...
+      ") must be a vector"]);
+
+  elseif (any(idx <= 0))
+    idv = find(idx <= 0);
+    ii = idv(1);
+    error(["idx(",num2str(ii),")=",num2str(idx(ii)), ...
+      "; entries of idx must be positive"]);
+
+  elseif(!(isstr(sprefix) | isempty(sprefix)))
+    error("sprefix must be a string or empty");
+
+  elseif(!is_sample(Ts2))
+    error(["Ts2=",num2str(Ts2),"; invalid sampling time"]);
+
+  endif
+
+  # optional argument: cuflg
+  if(nargin <= 4)
+    cuflg = 1;		# default: constant inputs over Ts2 sampling interv.
+  elseif( !is_scalar(cuflg) )
+    error("cuflg must be a scalar")
+  elseif( cuflg != 0 | cuflg != 1)
+    error(["cuflg = ",num2str(cuflg),", should be 0 or 1"]);
+  endif
+
+  # extract  state space information
+  [da,db,dc,dd,Ts1,nc,nz,stname,inname,outname,yd] = sys2ss(sys);
+
+  # compute number of steps
+  if(Ts1 > Ts2)
+    error(["Current sampling time=",num2str(Ts1),"< Ts2=",num2str(Ts2)]);
+  endif
+  nstp = floor(Ts2/Ts1+0.5);
+  if(abs((Ts2 - Ts1*nstp)/Ts1) > 1e-12)
+    warning(["dmr2d: Ts1=",num2str(Ts1),", Ts2=",num2str(Ts2), ...
+      ", selecting nsteps=",num2str(nstp),"; mismatch"]);
+  endif
+
+  if(isempty(sprefix) & isempty(idx))
+    warning("both sprefix and idx are empty; returning dsys=sys");
+    fidx = [];
+    dsys = sys;
+    return
+  elseif(isempty(sprefix))
+    fidx = idx;
+  else
+    fidx = reshape(idx,1,length(idx));
+    # find states whose name begins with any strings in sprefix.
+    ns = rows(sprefix);
+    for kk=1:ns
+      spk = dezero(sprefix(kk,:));  # get next prefix and length
+      spl = length(spk);
+
+      # check each state name
+      for ii=1:nz
+        sti = dezero(stname(ii,:));  # compare spk with this state name
+        if(length(sti) >= spl)
+          # if the prefix matches and ii isn't already in the list, add ii
+          if(strcmp(sti(1:spl),spk) & !any(fidx == ii) ) 
+            fidx = sort([fidx,ii]);
+          endif
+        endif
+      endfor
+    endfor
+  endif
+
+  if(nstp == 0)
+    warning("dmr2d: nstp = 0; setting tsam and returning");
+    dsys = syschtsam(sys,Ts2);
+    return
+  elseif(nstp < 0)
+    error(["nstp = ", num2str(nstp)," < 0; this shouldn't be!"]);
+  endif
+
+  # permute system matrices
+  pv = sysreorder(nz,fidx);
+  pv = pv(nz:-1:1);          # reverse order to put fast modes in leading block
+
+  # construct inverse permutation
+  Inz = eye(nz);
+  pvi = (Inz(pv,:)'*[1:nz]')';
+
+  # permute A, B (stname permuted for debugging only)
+  da = da(pv,pv);
+  db = db(pv,:);
+  stname = stname(pv,:);
+
+  # partition A, B:
+  lfidx = length(fidx);
+  bki = 1:lfidx;
+  a11 = da(bki,bki);
+  b1 = db(bki,:);
+
+  if(lfidx < nz)
+    lfidx1 = lfidx+1;
+    bki2 = (lfidx1):nz;
+    a12 = da(bki,bki2);
+    b2 = db(bki2,:);
+  else
+    warning("dmr2d: converting entire A,B matrices to new sampling rate");
+    lfidx1 = -1;
+    bki2 = [];
+  endif
+
+  #####################################
+  # begin system conversion: nstp steps
+  #####################################
+
+  # compute abar_{n-1}*a12 and appropriate b matrix stuff
+  a12b = a12;      # running  total of abar_{n-1}*a12
+  a12w = a12;      # current a11^n*a12  (start with n = 0)
+  if(cuflg)
+    b1b = b1;
+    b1w = b1;
+  else
+    # cuflg == 0, need to keep track of intersample inputs too
+    nzdx = find(max(abs(b1)) != 0);  # FIXME: check tolerance relative to ||b1||
+    b1w = b1(nzdx);
+    innamenz = inname(nzdx);
+    b1b = b1;                        # initial b1 must match columns in b2
+  endif
+
+  ######################################
+  # compute a11h = a11^nstp by squaring
+  a11h = eye(size(a11));
+  p2 = 1;
+  a11p2 = a11;        #a11^p2
+
+  nstpw = nstp;       # workspace for computing a11^nstp
+  while(nstpw > 0.5)
+    oddv = rem(nstpw,2);
+    if(oddv)
+      a11h = a11h*a11p2;
+    endif
+    nstpw = (nstpw-oddv)/2;
+    if(nstpw > 0.5)
+      a11p2 = a11p2*a11p2;    # a11^(next power of 2)
+    endif
+  endwhile
+  
+  # FIXME: this part should probably also use squaring, but
+  # that would require exponentially growing memory.  What do do?
+  for kk=2:nstp
+    # update a12 block to sum(a12 + ... + a11^(kk-1)*a12)
+    a12w = a11*a12w;
+    a12b = a12b + a12w;
+
+    # similar for b1 block (checking for cuflg first!)
+    b1w = a11*b1w;
+    if(cuflg)
+      b1b = b1b + b1w;        # update b1 block just like we did a12
+    else
+      b1b = [b1b, b1w];       # append new inputs
+      newin = strappend(innamenz,["_d",num2str(kk-1)]);
+      inname = str2mat(inname,newin);
+    endif
+  endfor
+
+  # reconstruct system and return
+  da(bki,bki) = a11h;
+  db(bki,1:columns(b1b)) = b1b;
+  if(!isempty(bki2))
+    da(bki,bki2) = a12b;
+  endif
+
+  da = da(pvi,pvi);
+  db = db(pvi,:);
+  stname = stname(pvi,:);
+
+  # construct new system and return
+  dsys = ss2sys(da,db,dc,dd,Ts2,0,nz,stname,inname,outname,find(yd == 1));
+
+  implicit_str_to_num_ok = save_val;	# restore value
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/fir2sys.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,102 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function sys = fir2sys (num,tsam,inname,outname)
+  #
+  # outsys = fir2sys(num,{tsam,inname,outname})
+  # construct a system data structure from FIR description
+  # inputs:
+  #   num: vector of coefficients [c0 c1 ... cn] of the SISO FIR transfer
+  #        function C(z) = c0 + c1*z^{-1} + c2*z^{-2} + ... + znz^{-n}
+  #   tsam: sampling time (default: 1)
+  #   inname: name of input signal 
+  #   outname: name of output signal
+  # outputs:  sys (system data structure)
+   
+  #  Written by R. Bruce Tenison  July 29, 1994
+  #  Name changed to TF2SYS July 1995
+  #  updated for new system data structure format July 1996
+  # adapted from tf2sys july 1996
+  # $Revision: 1.1.1.1 $
+
+  save_val = implicit_str_to_num_ok;
+  implicit_str_to_num_ok = 1;
+
+  #  Test for the correct number of input arguments
+  if ((nargin < 2) || (nargin > 4))
+    usage('sys=fir2sys(num[,tsam,inname,outname])');
+    return
+  endif
+
+  # check input format 
+  if( !is_vector(num) )
+    error(['num (',num2str(rows(num)),'x',num2str(columns(num)), ...
+	') must be a vector'])
+  endif
+
+  den = [1,zeros(1,length(num)-1)];
+
+  # check sampling interval (if any)
+  if(nargin <= 1)
+    tsam = 1;		# default
+  elseif (isempty(tsam))
+    tsam = 1;
+  endif
+  if ( (! (is_scalar(tsam) && (imag(tsam) == 0) )) || (tsam <= 0) )
+    error('fir tsam must be a positive real scalar')
+  endif
+
+  #  Set name of input
+  if(nargin < 3)
+    inname = "u";
+  elseif(isempty(inname))
+    inname = "u";
+  endif
+  if (rows(inname) > 1)
+    warning(['fir2sys:,' num2str(rows(inname)),' input names given, 1st used.'])
+    inname = (inname(1,:));
+  endif
+
+  #  Set name of output
+  if(nargin < 4)
+    outname = "y";
+  elseif(isempty(outname))
+    outname = "y";
+  endif
+  if (rows(outname) > 1)
+    warning(['fir2sys: ',num2str(rows(outname)),...
+      ' output names given, 1st used.'])
+    outname = (outname(1,:));
+  endif
+  
+  sys.num = num;
+  sys.den = den;
+
+  #  Set the system vector:  active = 0(tf), updated = [1 0 0];
+  sys.sys = [0 1 0 0];
+
+  #  Set defaults
+  sys.tsam = tsam;
+  sys.inname = inname;
+  sys.outname = outname;
+  sys.nz = length(den)-1;
+  sys.n = 0;
+  sys.yd = 1;
+
+  implicit_str_to_num_ok = save_val;
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/frdemo.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,583 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function frdemo()
+# Octave Controls toolbox demo: Frequency Response demo
+# Written by David Clem August 15, 1994 
+
+# $Revision: 1.3 $
+# a s hodel: updated to match new order of ss2zp outputs
+# J Ingram:  updated for system data structure format August 1996
+
+  disp("")
+  clc
+  j = 0;
+  while (j != 3)
+    disp("");
+    j = menu("Octave Controls Systems Toolbox Frequency Response Demo",...
+             'Bode analysis (bode)',...
+             'Nyquist analysis (nyquist)',...
+             'Return to main demo menu');
+   
+    if (j == 1)
+      k1 = 0;
+      while (k1 != 4)
+        disp("\n");
+        clc
+
+        k1 = menu("Bode analysis (bode)",...
+                  'Continuous system bode analysis',...
+                  'Discrete system bode analysis',...
+                  'Bode command description', ...
+                  'Return to frdemo menu');
+       
+        if( k1 == 1 )
+          disp(" ")
+          clc  
+          disp("\nContinuous system bode analysis\n");
+          disp("Example #1:")
+          disp("\nConsider the system sys1=");
+          sys1=tf2sys([1 1],[1 0 -1]);
+          sysout(sys1);
+          disp("\nPole-zero form can be obtained as follows:")
+          cmd = "sysout(sys1,""zp"");";
+          run_cmd;
+          disp("The systems bode plot is obtained as follows:");
+          cmd = "bode(sys1);";
+          run_cmd;  
+          disp("\nNotice that bode automatically labels the plots according to")
+          disp("the selected input/output combinations.")
+          disp(" ")
+          disp("If the frequency range is not specified, bode automatically")
+          disp("selects a frequency range based on the natural frequencies of")
+          disp("of all poles away from s=0 (or z=1 in discrete time).  Bode")
+          disp("then checks to make sure that the phase plot is sufficiently")
+          disp("smooth that relevant plot behavior is captured.")
+          disp("")
+          disp("Bode exits with an error if the system is mixed (both continuous")
+          disp("and discrete; see is_digital for conditions)")
+          prompt
+          disp("\nIf the plot magnitude, phase and frequency data is desired, the");
+          disp("user can enter the following command:");
+          disp("\n[Mag,Phase,w] = bode(sys);");
+          disp("\nThis will return three vectors containing the magnitude,");
+          disp("phase and frequency.\n");
+          prompt;
+
+          disp("")
+          clc
+          disp("Example #2, sys2=")
+          cmd = "sys2=zp2sys([1],[-1 -5],10);";
+          eval(cmd);
+          cmd = "sysout(sys2);";
+          eval(cmd);
+          disp("\nThe bode plot command is identical to the tf form:")
+          cmd = "bode(sys2);";
+          run_cmd;  
+          disp("\nThe internal representation of the system is not important;")
+          disp("bode automatically sorts it out internally.")
+          prompt;
+ 
+          disp("")
+          clc
+          disp("Example #3, Consider the following state space system sys3=:\n");
+          cmd = "sys3=ss2sys([0 1; -1000 -1001], [0;1], [0 -891], 1);";
+          eval(cmd);
+          cmd = "sysout(sys3);";
+          eval(cmd);
+          disp("\nOnce again, the bode plot command is the same:");
+          cmd = "bode(sys3);";
+          run_cmd;
+          disp("\nSuppose the user is interested in the response of the system");
+          disp("defined over the input frequency range of 1 - 1000 rad/s.\n");
+          disp("First, a frequency vector is required.  It can be created");
+          disp("with the command:\n");
+          cmd = "wrange = logspace(log10(1),log10(1000),100);";
+          disp(cmd); 
+          eval(cmd);
+          disp("\nThis creates a logarithmically scaled frequency vector with");
+          disp("100 values between 1 and 1000 rad/s\n");
+          disp("Then, the bode command includes wrange in the input arguments");
+          disp("like this:");
+          cmd = "bode(sys3,wrange);";
+          run_cmd;
+          prompt; 
+
+          disp("")
+          clc
+      	  disp("\nExample #4, The state-space system from example 3 will be");
+          disp("grouped with the system from example 2 to form a MIMO system");
+          disp("The commands to do this grouping are as follows:");
+          sys2=sysupdate(sys2,"ss");
+          [nn,nz,mm,pp] = sysdimensions(sys2);
+          sys2 = syschnames(sys2,"out",1:pp,"y_sys2");
+          sys2 = syschnames(sys2,"in",1:mm,"u_sys2");
+          sys2 = syschnames(sys2,"st",1:nn,sysdefioname(nn+nz,"x_sys2"));
+          cmd = "sys_mimo = sysgroup(sys2,sys3);";
+          disp(cmd); 
+          eval(cmd);
+          disp("The resulting state-space system (after changing signal names");
+          disp("in sys2) is");
+          cmd = "sysout(sys_mimo)";
+          eval(cmd);
+          disp("\nNotice that there are now 2 inputs and 2 outputs, and that it did");
+ 	  disp("not matter what form the two systems were in when they were grouped.");
+          disp(["\nTo view the system\'s bode plots, execute the",...
+        	" following command:\n"])
+          cmd = "bode(sys_mimo);";
+          run_cmd;
+          prompt
+          disp("\nTo view the bode plots for selected  channels, the command form changes:")
+          cmd = "wrange = [];";
+          disp(cmd)
+          eval(cmd);
+          cmd = "out = 1;";
+          disp(cmd)
+          eval(cmd);
+          cmd = "in = 1;";
+          disp(cmd)
+          eval(cmd);
+          cmd = "bode(sys_mimo,wrange,out,in);";
+          run_cmd;
+          disp("\nNotice that this bode plot is the same as the plot from example 2.");         
+          prompt
+          closeplot
+
+        elseif( k1 == 2 )
+          disp("")
+          clc
+          disp("\nDiscrete system bode analysis\n");
+          disp("Display bode plots of a discrete SISO system (dbode)\n")
+      	  disp("Example #1, Consider the following discrete transfer");
+          disp(" function:\n");
+          cmd = "sys1 = tf2sys([0.00100502 -0.00099502],[1 -2 1],0.001);";
+          disp(cmd);
+          eval(cmd);
+ 	  cmd = "sysout(sys1)";
+          disp(cmd);
+          eval(cmd);
+      	  disp("\nTo examine open loop zeros and poles of the system,");
+          disp("use the command:\n")
+          cmd = "sysout(sys1,""zp"");";
+          run_cmd;	  
+       	  disp("\nTo view the system's bode plots, execute the following");
+          disp("command:\n")
+      	  cmd = "bode(sys1);";
+          run_cmd;
+          disp("\nNotice (1) the plot label uses exp(jwT) for its title axis. This")
+          disp("           allows the user to determine what kind of system was")
+          disp("           used to generate the bode plot");
+          disp("       (2) the system poles are both at z=1, (break frequency at")
+          disp("           jwT = 0); pure integrator poles like this are discarded")
+          disp("           by Octave when computing the plot frequency range.")
+
+          disp("\nIf magnitude, phase, and frequency data are also desired,");
+          disp(" perform the following command instead:\n"); 		
+          disp("[M,P,w]=dbode(num,den,T,wrange).\n Where:");
+          disp("M => Bode magnitude response data");
+          disp("P => Bode phase response data");
+          disp("w => frequencies that M and P were evaluated at");
+          disp("sys1 => system data structure")
+          disp("T => sample period")
+          disp("wrange => optional vector of frequencies")
+          disp("          if wrange is entered in the argument list, the");  
+          disp("	  system will be evaluated at these specific"); 
+          disp(" 	  frequencies\n"); 
+
+          prompt
+          disp("")
+          clc    
+          disp("Example #2, Consider the following set of discrete poles and"); 
+          disp("zeros:\n")
+ 	  cmd = "sys2 = zp2sys([0.99258;0.99745],[0.99961;0.99242],1,0.001);";
+          disp(cmd);
+ 	  eval(cmd);
+          cmd = "sysout(sys2)";
+          disp(cmd);
+ 	  eval(cmd);
+          disp("\nTo view the system's bode plots, execute the following");
+          disp("command:\n")
+      	  cmd = "bode(sys2);";
+          run_cmd;       	  
+          disp("Notice that the bode command is the same in both of the previous");
+          disp("examples.  The bode command is also the same for the continuous case.");
+          disp("The function, dbode, is no longer used.");
+
+          prompt
+          disp("")
+          clc
+          disp("\nExample #3, Now consider the following state space system:\n");
+          cmd = "sys3 = ss2sys([.857 .0011;0 .99930],[1;1],[-.6318 .0057096],5.2, .001);";
+          disp(cmd);
+          eval(cmd);
+          cmd = "sysout(sys3);";
+          disp(cmd);
+          eval(cmd);
+          disp("\nTo view the system's bode plots, execute the following command:\n")
+      	  cmd = "bode(sys3);";
+       	  run_cmd;
+          disp("\nAgain, notice that the bode command is the same regardless of the form");
+          disp("of the system.");
+          disp("\nSuppose the user is interested in the response of the system");
+          disp("defined over the input frequency range of 1 - 1000 rad/s.\n");
+          disp("First, a frequency vector is required.  It can be created");
+          disp("with the command:\n");
+          cmd = "wrange = logspace(log10(1),log10(1000),100);";
+          disp(cmd); 
+          eval(cmd);
+          disp("\nThis creates a logrithmetically scaled frequency vector with");
+          disp("100 values between 1 and 1000 rad/s\n");
+          disp("Then, the bode command includes wrange in the input arguments");
+          disp("like this:");
+          cmd = "bode(sys3,wrange);";
+          run_cmd;
+          prompt;	  
+          
+          disp("")
+          clc
+          disp("\nExample #4, We will now examine a MIMO state-space system.  Systems");
+          disp("two and three will be grouped.");
+          sys2=sysupdate(sys2,"ss");
+          [nn,nz,mm,pp] = sysdimensions(sys2);
+          sys2 = syschnames(sys2,"out",1:pp,"y_sys2");
+          sys2 = syschnames(sys2,"in",1:mm,"u_sys2");
+          sys2 = syschnames(sys2,"st",1:nn,sysdefioname(nn+nz,"x_sys2"));
+          cmd = "sys_mimo = sysgroup(sys2,sys3);";
+          disp(cmd);
+          eval(cmd);
+          cmd = "sysout(sys_mimo);";
+          disp(cmd);
+          eval(cmd);
+          disp("\nTo view the system's bode plots, execute the following command:\n")
+      	  cmd = "bode(sys_mimo);";
+          run_cmd;
+          prompt
+
+          disp("\nThe bode plot of a single channel is viewed as follows:")
+          cmd = "wrange = [];";
+          disp(cmd)
+          eval(cmd);
+          cmd = "out = 1;";
+          disp(cmd)
+          eval(cmd);
+          cmd = "in = 1;";
+          disp(cmd)
+          eval(cmd);
+          cmd = "bode(sys_mimo,wrange,out,in);";
+          run_cmd;
+          disp("\nNotice that this bode plot is the same as the plot from example 2.");         
+          prompt
+          closeplot
+
+        elseif( k1 == 3 )
+          help bode
+          prompt
+        endif
+      endwhile
+    elseif (j == 2)
+      k2 = 0;
+      disp("");
+      while (k2 != 4)
+        disp("\n");
+        help nyquist
+        prompt;
+        disp("")
+        clc;
+
+        k2 = menu("Nyquist analysis (Nyquist)",...
+                  'Continuous system nyquist analysis',...
+        	  'Discrete system nyquist analysis',...
+        	  'Mixed system nyquist analysis',...
+                  'Return to frdemo menu');
+
+        if( k2 == 1 )
+          disp("")
+          clc
+ 	  disp("\nContinuous system nyquist analysis\n");
+      	  disp("Display Nyquist plots of a SISO system (nyquist)\n")
+      	  disp("Example #1, Consider the following transfer function:\n")
+          cmd = "sys1 = tf2sys([1],[1 0.8 1]);";
+          disp(cmd);
+          eval(cmd);
+          disp("To examine the transfer function, use the command:");
+          cmd = "sysout(sys1);";
+          disp(cmd);
+          eval(cmd);
+          disp("\nTo examine the open loop zeros and poles, use the command:");
+          cmd = "sysout(sys1,""zp"");";
+          run_cmd;
+      	  disp("\nTo view the system""s nyquist plot, execute the following"); 
+          disp("command:\n")
+      	  cmd = "nyquist(sys1);";
+          run_cmd;
+          disp("\nIf the real and imaginary parts of the response are desired,");
+          disp("use the following command:");
+       	  disp("command: [R,I,w]=nyquist(sys1);\n");
+      	  disp("If the user desires to evaluate the response in a certain");
+          disp("frequency range, he may do so by entering the following:");
+          disp("command: [M,P,w]=nyquist(num,den,wrange).\n")
+      	  disp("wrange is a vector of frequencies that spans the desired");
+          disp("viewing range.\n");
+      	  disp("This will be illustrated in the third nyquist example.\n")  
+       	  disp("Variable Description:\n")
+      	  disp("R => real part of response")
+      	  disp("I => imaginary part of response")
+      	  disp("w => frequencies that the transfer function was evaluated at")
+      	  disp("sys1 => system data structure")
+       	  disp("wrange => optional vector of frequencies")
+          disp("          if wrange is entered in the argument list, the");
+          disp("	  system will be evaluated at these specific");
+          disp("          frequencies\n") 
+          prompt 
+          
+          disp("")
+          clc
+          disp("Example #2, Consider the following set of poles and zeros:\n")
+          cmd = "sys2 = zp2sys([-1;-4],[-2+1.4142i;-2-1.4142i],1);";
+          disp(cmd);
+          eval(cmd);
+          disp("\nTo examine the poles and zeros, use the command:");
+          cmd = "sysout(sys2)";
+          disp(cmd);
+          eval(cmd);
+      	  disp("\nTo view the system""s nyquist plot, execute the following");
+          disp("command:\n")
+      	  cmd = "nyquist(sys2);";
+          run_cmd;
+          prompt
+
+          disp("")
+          clc
+          disp("\nExample #3, Consider the following state space system:\n")
+          cmd = "sys3 = ss2sys([0 1 0 0;0 0 1 0;0 0 0 1;0 0 -20 -12],[0;0;0;1],[50 100 0 0],0);";
+          disp(cmd);
+          eval(cmd); 
+          disp("\nTo examine the state-space system, use the command:");
+          cmd = "sysout(sys3)";
+          disp(cmd);
+          eval(cmd); 	 
+          disp("\nTo examine the poles and zeros, use the command:");
+          cmd = "sysout(sys3,""zp"")";
+          run_cmd;
+      	  disp("\nTo view the system""s nyquist plot, execute the following");
+          disp("commands:\n")
+      	  cmd = "nyquist(sys3);";
+          run_cmd;
+          prompt	 
+          
+          disp("Example #3 (continued), If the user wishes to evaluate the");
+          disp("system response over a desired frequency range, he must first");
+          disp("create a frequency vector.\n")
+      	  disp("For example, suppose the user is interested in the response");
+          disp("of the system defined above over input frequency range of");
+          disp("3 - 100 rad/s.\n")
+      	  disp("A frequency vector can be created using the command:\n");
+     	  cmd = "wrange = logspace(log10(3),log10(100),100);";
+          disp(cmd);
+          eval(cmd); 
+          disp("\nNyquist can be run again using the frequency vector as");
+          disp("follows:\n")
+       	  cmd = "nyquist(sys3,wrange);";
+          run_cmd;	  
+          prompt
+
+          disp("")
+          clc
+          disp("Example #4,  Nyquist can be used for MIMO systems if the system has");
+          disp("an equal number of inputs and outputs.  Otherwise, nyquist returns");
+          disp("an error.  To examine a MIMO system, systems 2 and 3 will be grouped");
+          sys2=sysupdate(sys2,"ss");
+          [nn,nz,mm,pp] = sysdimensions(sys2);
+          sys2 = syschnames(sys2,"out",1:pp,"y_sys2");
+          sys2 = syschnames(sys2,"in",1:mm,"u_sys2");
+          sys2 = syschnames(sys2,"st",1:nn,sysdefioname(nn+nz,"x_sys2"));
+          cmd = "sys_mimo = sysgroup(sys2,sys3);";
+          disp(cmd);
+          eval(cmd);
+          cmd = "sysout(sys_mimo);";
+          disp(cmd);
+          eval(cmd);
+          disp("\nTo view the system's nyquist plot, execute the following command:\n")
+      	  cmd = "nyquist(sys_mimo);";
+ 	  run_cmd;
+          prompt
+          disp("\nTo view the nyquist plots for selected  channels, the command form changes:")
+          cmd = "nyquist(sys_mimo,[],1,1);";
+          run_cmd;
+          disp("\nNotice that this bode plot is the same as the plot from example 2.");         
+          prompt
+          closeplot
+
+
+
+        elseif( k2 == 2 )
+          disp("")
+          clc 
+          disp("\nDiscrete system nyquist analysis\n");
+      	  disp("Display Nyquist plots of a discrete SISO system (nyquist)\n")
+          disp("We will first define a sampling time, T");
+          cmd = "T = 0.01;";
+          disp(cmd); 
+          eval(cmd);
+      	  disp("\nExample #1, Consider the following transfer function:\n")
+      	  cmd = "sys1 = tf2sys([2 -3.4 1.5],[1 -1.6 0.8],T);";
+          disp(cmd); 
+          eval(cmd);
+          disp("To examine the transfer function, use the command:");
+          cmd = "sysout(sys1);";
+          disp(cmd);
+          eval(cmd);
+          disp("\nTo examine the open loop zeros and poles, use the command:");
+          cmd = "sysout(sys1,""zp"")";
+          disp(cmd); 
+          eval(cmd); 
+      	  disp("\nTo view the system""s nyquist plot, execute the following"); 
+          disp("command:")
+      	  cmd = "nyquist(sys1);";
+          run_cmd;
+          disp("To change the range used for the frequency, a frequency");
+          disp("is needed.  Suppose the user would like to examine the");
+          disp("nyquist plot in the frequency range of 0.01 - 31.6 rad/s.");
+          disp("\nThe frequency vector needed to do this is created with the");
+          disp("command:");
+          cmd = "wrange = logspace(-2,1.5,200);";
+          disp(cmd); 
+          eval(cmd);	
+          disp("\nNyquist can be run again with this frequency vector");     	
+          cmd = "nyquist(sys1,wrange);";
+          run_cmd;
+      	  disp("\nIf the real and imaginary parts of the response are desired,");
+          disp("perform the following command:\n"); 	
+          disp("[R,I,w]=nyquist(sys,wrange)\n")
+          disp("Variable Description:\n")
+          disp("R => real part of response")
+     	  disp("I => imaginary part of response")
+      	  disp("w => frequencies that the transfer function was evaluated at")
+          disp("sys => The system data structure");
+      	  disp("wrange => optional vector of frequencies")
+      	  disp("          if wrange is entered in the argument list, the");
+          disp("	  system will be evaluated at these specific");
+          prompt
+
+          disp("")
+          clc
+          disp("\nExample #2, Consider the following set of poles and zeros:\n")
+       	  cmd = "sys2 = zp2sys([0.98025 + 0.01397i;0.98025 - 0.01397i],[0.96079;0.99005],1,T);";
+          disp(cmd); 
+          eval(cmd);
+          disp("\nTo examine the open loop zeros and poles, use the command:");
+          cmd = "sysout(sys2)";
+          disp(cmd); 
+          eval(cmd); 
+      	  disp("\nTo view the system's nyquist plot between the frequencies");
+          disp("0.01 - 100 rad/s, execute the following commands:\n")
+      	  cmd = "wrange = logspace(-2,2,100);";
+          disp(cmd); 
+          eval(cmd);
+  	  cmd = "nyquist(sys2,wrange);";
+          run_cmd;
+          prompt;
+        
+          disp("")
+          clc
+          disp("\nExample #3, Consider the following discrete state space");
+          disp("system:\n");
+          disp("This example will use the same system used in the third");
+          disp("example in the continuous nyquist demo.  First, that system");
+          disp("will have to be re-entered useing the following commands:\n");
+          cmd = "sys3 = ss2sys([0 1 0 0;0 0 1 0;0 0 0 1;0 0 -20 -12],[0;0;0;1],[50 100 0 0],0);";
+          disp(cmd); 
+          eval(cmd); 
+          disp("\nTo examine the state-space system, use the command:");
+          cmd = "sysout(sys3)";
+          disp(cmd); 
+          eval(cmd);
+          disp("\nTo examine the poles and zeros, use the command:");
+          cmd = "sysout(sys3,""zp"")";
+          disp(cmd); 
+          eval(cmd);
+          disp("\nTo convert the system to discrete time, we need a sampling");
+          disp("time which can be entered like this:");
+          cmd = "T = 0.01";
+          disp(cmd); 
+          eval(cmd);
+          disp("\nNow the command, c2d, is used to convert the system from");
+          disp("continuous to discrete time, with the following command");
+          cmd = "dsys3 = c2d(sys3,T);";
+          run_cmd;
+          disp("\nTo examine the new discrete state-space system, use the");
+          disp("command");
+          cmd = "sysout(dsys3);";
+          disp(cmd); 
+          eval(cmd);
+ 	  disp("\nTo examine the new discrete poles and zeros, use the command:");
+          cmd = "sysout(dsys3,""zp"")";
+          disp(cmd); 
+          eval(cmd);
+          disp("\nTo view the system's nyquist plot, execute the following");
+          disp("commands:\n");
+ 	  cmd = "gset xrange [-4:2];";
+          disp(cmd); eval(cmd);
+          cmd = "gset yrange [-2.5:2.5];";
+          disp(cmd); eval(cmd);
+          cmd = "nyquist(dsys3);";
+     	  run_cmd;
+	  disp("Notice that the asymptotes swamp out the behavior of the plot")
+          disp("near the origin.  You may use interactive nyquist plots")
+          disp("to \"zoom in\" on a plot as follows:")
+
+          cmd = "atol = 1;";
+          disp(cmd)
+          eval(cmd)
+          cmd = "nyquist(dsys3,[],[],[],atol);";
+          run_cmd
+          prompt
+
+
+          disp("")
+          clc
+          disp("MIMO SYSTEM:  Nyquist cannot be used for discrete MIMO systems");
+          disp("at this time.");
+#	  cmd = "dsys_mimo = sysgroup(sys2,dsys3);";
+#          disp(cmd);
+#	  eval(cmd);
+#	  cmd = "sysout(dsys_mimo);";
+#	  disp(cmd);
+#	  eval(cmd);
+#	  disp("\nTo view the system's nyquist plot, execute the following command:\n")
+#      	  cmd = "nyquist(dsys_mimo);";
+#	  run_cmd; 	  
+#    	  prompt
+# 	  disp("\nTo view the nyquist plots for selected  channels, the command form changes:")
+#          cmd = "nyquist(dsys_mimo,[],1,1);";
+#	  run_cmd;
+#	  disp("\nNotice that this bode plot is the same as the plot from example 2.");         
+          prompt
+          closeplot
+
+               
+        elseif( k2 == 3 )
+          disp("\nMixed system nyquist analysis\n");
+          disp("Nyquist exits with an error if it is passed a ""mixed"" system (one")
+          disp("with both continuous and discrete states).  Use c2d or d2c to")
+          disp("convert the system to either pure digital or pure continuous form");
+        endif
+      endwhile 
+    endif
+  endwhile
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/freqchkw.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,37 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function USEW = freqchkw(w)
+  # function USEW = freqchkw(w)
+  # used by freqresp to check that input frequency vector is legal
+
+  # A S Hodel July 1996
+  # $Revision: 1.1.1.1 $
+
+  if(isempty(w))
+    USEW = 0;
+  elseif(!is_vector(w))
+    error(["w (",num2str(rows(w)),"x",num2str(columns(w)), ...
+      "): must be [], a vector or a scalar"]);
+  elseif( (max(abs(imag(w))) != 0) && (min(real(w)) <= 0) )
+    error("w must have real positive entries");
+  else
+    w = sort(w);
+    USEW = 1;   # vector provided (check values later)
+  endif
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/freqresp.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,118 @@
+# Copyright (C) 1996,1998 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [ff,w] = freqresp(sys,USEW,w);
+  # function [ff,w] = freqresp(sys,USEW{,w});
+  # Frequency response function - used internally by bode, nyquist.
+  # minimal argument checking; "do not attempt to do this at home"
+  # USEW returned by freqchkw 
+  # w: optional, must be present if USEW is given
+  #
+  # returns: ff = vector of finite G(j*w) entries (or || G(j*w) || for MIMO)
+  #          w = vector of frequencies used
+  #      ff and w are both returned as row vectors
+
+  #  Written by: R. Bruce Tenison July 11, 1994
+  # $Revision: 1.6 $
+  # SYS_INTERNAL accesses members of system data structure
+
+  save_val = empty_list_elements_ok;
+  empty_list_elements_ok = 1;
+
+  # Check Args
+  if( (nargin < 2) || (nargin > 4) )
+    usage ("[ff,w] = freqresp(sys,USEW{,w})");
+  elseif( USEW & (nargin < 3) )
+    error("USEW=1 but w was not passed.");
+  elseif( USEW & isempty(w))
+    warning("USEW=1 but w is empty; setting USEW=0");
+    USEW=0;
+  endif
+
+  DIGITAL = is_digital(sys);
+
+  # compute default w if needed
+  if(!USEW)
+    if(is_siso(sys))
+      sys = sysupdate(sys,"zp");
+      [zer,pol] = sys2zp(sys);
+    else
+      zer = tzero(sys);
+      pol = eig(sys2ss(sys));
+    endif
+
+    # get default frequency range
+    [wmin,wmax] = bode_bounds(zer,pol,DIGITAL,sysgettsam(sys));
+    w = logspace(wmin,wmax,50);
+  else
+    w = reshape(w,1,length(w)); 	# make sure it's a row vector
+  endif
+
+  # now get complex values of s or z
+  if(DIGITAL)
+    jw = exp(i*w*sysgettsam(sys));
+  else
+    jw = i*w;
+  endif
+
+  [nn,nz,mm,pp] = sysdimensions(sys);
+
+  # now compute the frequency response - divide by zero yields a warning
+  if (strcmp(sysgettype(sys),"zp"))
+    # zero-pole form (preferred)
+    [zer,pol,sysk] = sys2zp(sys);
+    ff = ones(size(jw));
+    l1 = min(length(zer)*(1-isempty(zer)),length(pol)*(1-isempty(pol)));
+    for ii=1:l1
+      ff = ff .* (jw - zer(ii)) ./ (jw - pol(ii));
+    endfor
+
+    # require proper  transfer function, so now just get poles.
+    for ii=(l1+1):length(pol)
+      ff = ff ./ (jw - pol(ii));
+    endfor
+    ff = ff*sysk;
+
+  elseif (strcmp(sysgettype(sys),"tf"))
+    # transfer function form 
+    [num,den] = sys2tf(sys);
+    ff = polyval(num,jw)./polyval(den,jw);
+  elseif (mm==pp)
+    # The system is square; do state-space form bode plot
+    [sysa,sysb,sysc,sysd,tsam,sysn,sysnz] = sys2ss(sys);
+    n = sysn + sysnz;
+    for ii=1:length(jw);
+      ff(ii) = det(sysc*((jw(ii).*eye(n)-sysa)\sysb)+sysd);
+    endfor;
+  else
+    # Must be state space... bode                            
+    [sysa,sysb,sysc,sysd,tsam,sysn,sysnz] = sys2ss(sys);
+    n = sysn + sysnz;
+    for ii=1:length(jw);
+      ff(ii) = norm(sysc*((jw(ii)*eye(n)-sysa)\sysb)+sysd);
+    endfor
+    
+  endif
+
+  w = reshape(w,1,length(w));
+  ff = reshape(ff,1,length(ff));
+
+  # restore global variable
+  empty_list_elements_ok = save_val;
+endfunction
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/gram.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,32 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+
+function m = gram(a,b)
+  # m = gram(a,b)
+  # Return controllability grammian of continuous time system
+  #
+  #  dx/dt = a x + b u
+  #
+  # a m + a' + b*b' = 0 
+
+  # Written by A. S. Hodel 
+  # $Revision: 1.2 $
+
+  # let lyap do the error checking...
+  m = lyap(a,b*b');
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/h2norm.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,58 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function out = h2norm(sys)
+  # Usage: out = h2norm(sys)
+  #
+  # Computes the H2 norm system data structure (continuous time only)
+  # sys = system data structure [see ss2sys()]
+  # returns out = Inf if system is unstable
+  #
+  # Reference:
+  # Doyle, Glover, Khargonekar, Francis, "State Space Solutions to Standard
+  # H2 and Hinf Control Problems", IEEE TAC August 1989
+  #
+
+  # A. S. Hodel Aug 1995
+  # updated for system data structure by John Ingram November 1996
+  # $Revision: 1.2 $
+
+  if((nargin != 1))
+    usage("out = h2norm(sys)");
+  elseif(!is_struct(sys))
+    error("Sys must be in system data structure");
+  end
+  dflg = is_digital(sys);
+
+  if(!is_stable(sys))
+    warning("h2norm: unstable input system; returning Inf");
+    out = Inf;
+  else
+    # compute gain
+    [a,b,c,d] = sys2ss(sys);
+    if(dflg)
+      M = dlyap(a,b*b');
+    else
+      M = lyap (a,b*b');
+    endif
+    if( min(real(eig(M))) < 0)
+      error("h2norm: grammian not >= 0 (lightly damped modes?)")
+    endif
+    out = sqrt(d'*d + trace(c*M*c'));
+  endif
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/h2syn.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,179 @@
+# Copyright (C) 1996,1998 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [K,gain, Kc, Kf, Pc,  Pf] = h2syn(Asys,nu,ny,tol)
+  #  [K,gain, Kc, Kf, Pc, Pf] = h2syn(Asys,nu,ny,tol)
+  #
+  # Design H2 optimal controller per procedure in 
+  # Doyle, Glover, Khargonekar, Francis, "State Space Solutions to Standard
+  # H2 and Hinf Control Problems", IEEE TAC August 1989
+  #
+  # Discrete time control per Zhou, Doyle, and Glover, ROBUST AND OPTIMAL
+  #   CONTROL, Prentice-Hall, 1996
+  #
+  # inputs: 
+  #   Asys: system data structure.
+  #   nu: number of controlled inputs
+  #   ny: number of measured outputs
+  #   tol: threshhold for 0.  Default: 200*eps
+  # outputs: 
+  #    K: system controller (system data structure)
+  #    gain: optimal closed loop gain (see Kc, Kf warning below)
+  #    Kc: full information control (system data structure)
+  #    Kf: state estimator (system data structure)
+  #       WARNING: incorporation of the is_dgkf nonsingular transformations
+  #       Ru and Ry into Kc and Kf has not been tested.  
+  #    Pc: ARE solution matrix for regulator subproblem
+  #    Pf: ARE solution matrix for filter subproblem
+
+  # Updated for System structure December 1996 by John Ingram
+  # $Revision: 1.2 $
+  # $Log: h2syn.m,v $
+  # Revision 1.2  1998/07/01 16:23:36  hodelas
+  # Updated c2d, d2c to perform bilinear transforms.
+  # Updated several files per bug updates from users.
+  #
+  # Revision 1.4  1997/03/11 15:24:28  scotte
+  # fixed bugs in return system data structure signal names a.s.hodel@eng.auburn.edu
+  #
+  # Revision 1.3  1997/03/03 22:54:42  hodel
+  # fixed details for update to octave 2.0.x
+  # a.s.hodel@eng.auburn.edu
+
+  if ((nargin < 3) | (nargin > 4))
+    usage("[K,gain, Kc, Kf, Pc, Pf] = h2syn(Asys,nu,ny[,tol])");
+  elseif(nargin == 3 )
+    [chkdgkf,dgs] = is_dgkf(Asys,nu,ny);
+  elseif(nargin == 4)
+    [chkdgkf,dgs] = is_dgkf(Asys,nu,ny,tol);
+  endif
+
+  if (!chkdgkf )
+    disp("h2syn: system does not meet required assumptions")
+    help is_dgkf
+    error("h2syn: exit");
+  endif
+
+  # extract dgs information
+  			nw = dgs.nw; 	nu = dgs.nu;
+  A = dgs.A;            Bw = dgs.Bw;    Bu = dgs.Bu;
+  Cz = dgs.Cz;          Dzw = dgs.Dzw;  Dzu = dgs.Dzu;	nz = dgs.nz;
+  Cy = dgs.Cy;          Dyw = dgs.Dyw;  Dyu = dgs.Dyu;	ny = dgs.ny;
+  d22nz = dgs.Dyu_nz;
+  dflg = dgs.dflg;
+
+  if(norm(Dzw,Inf) > norm([Dzw Dzu ; Dyw Dyu],Inf)*1e-12)
+    warning("h2syn: Dzw nonzero; feedforward not implemented")
+    Dzw
+    D = [Dzw Dzu ; Dyw Dyu]
+  endif
+
+  # recover i/o transformations
+  Ru = dgs.Ru;         Ry = dgs.Ry;
+  [ncstates, ndstates, nout, nin] = sysdimensions(Asys);
+  Atsam = sysgettsam(Asys);
+  [Ast, Ain, Aout] = sysgetsignals(Asys);
+
+  if(dgs.dflg == 0)
+    Pc = are(A,Bu*Bu',Cz'*Cz);    # solve control, filtering ARE's
+    Pf = are(A',Cy'*Cy,Bw*Bw');
+    F2 = -Bu'*Pc;		  # calculate feedback gains
+    L2 = -Pf*Cy';
+
+    AF2 = A + Bu*F2;
+    AL2 = A + L2*Cy;
+    CzF2 = Cz + (Dzu/Ru)*F2;
+    BwL2 = Bw+L2*(Ry\Dyw);
+
+  else
+    # discrete time solution
+    error("h2syn: discrete-time case not yet implemented")
+    Pc = dare(A,Bu*Bu',Cz'*Cz);
+    Pf = dare(A',Cy'*Cy,Bw*Bw');
+  endif
+
+  nn = ncstates + ndstates;
+  In = eye(nn);
+  KA = A + Bu*F2 + L2*Cy;
+  Kc1 = ss2sys(AF2,Bw,CzF2,zeros(nz,nw));
+  Kf1 = ss2sys(AL2,BwL2,F2,zeros(nu,nw));
+
+  g1 = h2norm(Kc1);
+  g2 = h2norm(Kf1);
+  
+  # compute optimal closed loop gain
+  gain = sqrt ( g1*g1 + g2*g2 );
+
+  if(nargout)
+    Kst = strappend(Ast,"_K");
+    Kin = strappend(Aout((nout-ny+1):(nout),:),"_K");
+    Kout = strappend(Ain((nin-nu+1):(nin),:),"_K");
+
+    # compute systems for return
+    K = ss2sys(KA,-L2/Ru,Ry\F2,zeros(nu,ny),Atsam,ncstates,ndstates,Kst,Kin,Kout);
+  endif
+
+  if (nargout > 2)
+    #system full information control state names
+    for ii=1:rows(Ast)
+      tmp = [dezero(Ast(ii,:)),"_FI"];
+      stname2(ii,1:length(tmp)) = tmp;
+    endfor
+
+   #system full information control input names
+    for ii=1:rows(Ast)
+      tmp = [dezero(Ast(ii,:)),"_FI_in"];
+      inname2(ii,1:length(tmp)) = tmp;
+    endfor
+ 
+    #system full information control output names
+    for ii=1:(rows(Aout)-ny)
+      tmp = [dezero(Aout(ii,:)),"_FI_out"];
+      outname2(ii,1:length(tmp)) = tmp;
+    endfor
+
+    nz = rows (Cz);
+    nw = columns (Bw);
+
+    Kc = ss2sys(AF2, In, CzF2, zeros(nz,nn), Atsam, ...
+	ncstates, ndstates, stname2, inname2, outname2);
+  endif
+
+  if (nargout >3)
+    #fix system state estimator state names
+    for ii=1:rows(Ast)
+      tmp = [dezero(Ast(ii,:)),"_Kf"];
+      stname3(ii,1:length(tmp)) = tmp;
+    endfor
+
+    #fix system state estimator input names
+    for ii=1:rows(Ast)
+      tmp = [dezero(Ast(ii,:)),"_Kf_noise"];
+      inname3(ii,1:length(tmp)) = tmp;
+    endfor
+
+    #fix system state estimator output names
+    for ii=1:rows(Ast)
+      tmp = [dezero(Ast(ii,:)),"_est"];
+      outname3(ii,1:length(tmp)) = tmp;
+    endfor
+
+    Kf = ss2sys(AL2, BwL2, In, zeros(nn,nw),Atsam,  ...
+      ncstates, ndstates, stname3, inname3,outname3);
+  endif
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/hinf_ctr.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,140 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function K = hinf_ctr(dgs,F,H,Z,g)
+  # K = hinf_ctr(dgs,F,H,Z,g)
+  #
+  # Called by hinfsyn to compute the H_inf optimal controller.
+  # 
+  # inputs:
+  #   dgs: data structure returned by is_dgkf
+  #           F, H:         feedback and filter gain (not partitioned)
+  #           g:            final gamma value
+  # outputs: 
+  #           controller K (system data structure)
+  #
+  # Do not attempt to use this at home; no argument checking performed.
+
+  # A. S. Hodel August 1995
+  # $Revision: 1.2 $
+  # Revised by Kai P Mueller April 1998 to solve the general H_infinity
+  # problem using unitary transformations Q (on w and z)
+  # and non-singular transformations R (on u and y).
+  # $Revision: 1.2 $
+  # $Log: hinf_ctr.m,v $
+  # Revision 1.2  1998/07/10 21:44:31  hodelas
+  # d11 -> D11 (was uninitialized)
+
+  nw = dgs.nw;
+  nu = dgs.nu;
+  nz = dgs.nz;
+  ny = dgs.ny;
+  d22nz = dgs.Dyu_nz;
+  
+  B1  = dgs.Bw;
+  B2  = dgs.Bu;
+  C1  = dgs.Cz;
+  C2  = dgs.Cy;
+  C = [C1; C2];
+  D11 = dgs.Dzw;
+  D12 = dgs.Dzu;
+  D21 = dgs.Dyw;
+  D22 = dgs.Dyu;
+  A = dgs.A;
+  Ru = dgs.Ru;
+  Ry = dgs.Ry;
+
+  nout = nz + ny;
+  nin = nw + nu;
+  nstates = size(A, 1);
+
+  F11 = F(1:(nw-ny),:);
+  F12 = F((nw-ny+1):nw,:);
+  F2  = F((nw+1):nin,:);
+  H11 = H(:,1:(nz-nu));
+  H12 = H(:,(nz-nu+1):nz);
+  H2  = H(:,(nz+1):nout);
+
+  # D11 partitions
+  D1111 = D11(1:(nz-nu),1:(nw-ny));
+  D1112 = D11(1:(nz-nu),(nw-ny+1):nw);
+  D1121 = D11((nz-nu+1):nz,1:(nw-ny));
+  D1122 = D11((nz-nu+1):nz,(nw-ny+1):nw);
+
+  # D11ik may be the empty matrix, don't calculate with empty matrices
+  [nd1111,md1111] = size(D1111);
+  md1112 = length(D1112);
+  md1121 = length(D1121);
+
+  if ((nd1111 == 0) || (md1112 == 0))
+    d11hat = -D1122;
+  else
+    xx = inv(g*g*eye(nz-nu) - D1111*D1111');
+    d11hat = -D1121*D1111'*xx*D1112 - D1122;
+  endif
+  if (md1112 == 0)
+    d21hat = eye(ny);
+  elseif (nd1111 == 0)
+    d21hat = chol(eye(ny) - D1112'*D1112/g/g);
+  else
+    xx = inv(g*g*eye(nz-nu) - D1111*D1111');
+    xx = eye(ny) - D1112'*xx*D1112;
+    d21hat = chol(xx);
+  endif
+  if (md1121 == 0)
+    d12hat = eye(nu);
+  elseif (md1111 == 0)
+    d12hat = chol(eye(nu) - D1121*D1121'/g/g)';
+  else
+    xx = inv(g*g*eye(nw-ny) - D1111'*D1111);
+    xx = eye(nu)-D1121*xx*D1121';
+    d12hat = chol(xx)';
+  endif
+
+  b2hat = (B2+H12)*d12hat;
+  c2hat = -d21hat*(C2+F12)*Z;
+  b1hat = -H2 + (b2hat/d12hat)*d11hat;
+  c1hat =  F2*Z + (d11hat/d21hat)*c2hat;
+  ahat  =  A + H*C + (b2hat/d12hat)*c1hat;
+
+  # rescale controller by Ru and Ry
+  b1hat = b1hat/Ry;
+  c1hat = Ru\c1hat;
+  bhat  = [b1hat b2hat];
+  chat  = [c1hat; c2hat];
+  dhat  = [Ru\d11hat/Ry Ru\d12hat; d21hat/Ry 0*d11hat'];
+
+  # non-zero D22 is a special case
+  if (d22nz)
+    if (rank(eye(nu) + d11hat*D22) < nu)
+      error(" *** cannot compute controller for D22 non-zero.");
+    endif
+
+    d22new = [D22 zeros(ny,ny); zeros(nu,nu) 0*D22'];
+    xx = inv(eye(nu+ny) + d22new*dhat);
+    mhat = inv(eye(nu+ny) + dhat*d22new);
+    ahat = ahat - bhat*((eye(nu+ny)-xx)/dhat)*chat;
+    bhat = bhat*xx;
+    chat = mhat*chat;
+    dhat = dhat*xx;
+
+  endif
+
+  K = ss2sys(ahat,bhat(:,1:ny),chat(1:nu,:),dhat(1:nu,1:ny));
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/hinfdemo.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,328 @@
+# hinfdemo  H_infinity design demos for continuous SISO and MIMO
+#           systems and a discrete system.
+#           The SISO system is difficult to control because
+#           it is non minimum phase and unstable. The second
+#           design example controls the "jet707" plant, the
+#           linearized state space model of a Boeing 707-321
+#           aircraft at v=80m/s (M = 0.26, Ga0 = -3 deg,
+#           alpha0 = 4 deg, kappa = 50 deg).
+#           inputs:  (1) thrust   and (2) elevator angle
+#           outputs: (1) airspeed and (2) pitch angle.
+#           The discrete system is a stable and second order.
+#
+# This is a script file for Octave.
+#
+# SISO plant:
+#
+#	           s - 2
+#	G(s) = --------------
+#	       (s + 2)(s - 1)
+#
+#	                         +----+
+#	    -------------------->| W1 |---> v1
+#	z   |                    +----+
+#	----|-------------+                   || T   ||     => min.
+#	    |             |                       vz   infty
+#	    |    +---+    v   y  +----+
+#	  u *--->| G |--->O--*-->| W2 |---> v2
+#	    |    +---+       |   +----+
+#	    |                |
+#	    |    +---+       |
+#	    -----| K |<-------
+#	         +---+
+#
+#	W1 und W2 are the robustness and performance weighting
+#       functions
+#
+# MIMO plant:
+# The optimal controller minimizes the H_infinity norm of the
+# augmented plant P (mixed-sensitivity problem):
+#
+#      w
+#       1 -----------+
+#                    |                   +----+
+#                +---------------------->| W1 |----> z1
+#      w         |   |                   +----+
+#       2 ------------------------+
+#                |   |            |
+#                |   v   +----+   v      +----+
+#             +--*-->o-->| G  |-->o--*-->| W2 |---> z2
+#             |          +----+      |   +----+
+#             |                      |
+#             ^                      v
+#              u (from                 y (to K)
+#                controller
+#                K)
+#
+#
+#                   +    +           +    +
+#                   | z  |           | w  |
+#                   |  1 |           |  1 |
+#                   | z  | = [ P ] * | w  |
+#                   |  2 |           |  2 |
+#                   | y  |           | u  |
+#                   +    +           +    +
+#
+# DISCRETE SYSTEM:
+#   This is not a true discrete design. The design is carried out
+#   in continuous time while the effect of sampling is described by
+#   a bilinear transformation of the sampled system.
+#   This method works quite well if the sampling period is "small"
+#   compared to the plant time constants.
+#
+# The continuous plant:
+#	              1
+#	G (s) = --------------
+#	 k      (s + 2)(s + 1)
+#
+# is discretised with a ZOH (Sampling period = Ts = 1 second):
+#
+#	          0.199788z + 0.073498
+#	G(s) = --------------------------
+#	       (z - 0.36788)(z - 0.13534)
+#
+#	                         +----+
+#	    -------------------->| W1 |---> v1
+#	z   |                    +----+
+#	----|-------------+                   || T   ||     => min.
+#	    |             |                       vz   infty
+#	    |    +---+    v      +----+
+#	    *--->| G |--->O--*-->| W2 |---> v2
+#	    |    +---+       |   +----+
+#	    |                |
+#	    |    +---+       |
+#	    -----| K |<-------
+#	         +---+
+#
+#	W1 and W2 are the robustness and performancs weighting
+#       functions
+
+
+# Kai P. Mueller 30-APR-1998 <mueller@ifr.ing.tu-bs.de
+# $Revision: 1.3 $
+# $Log: hinfdemo.m,v $
+# Revision 1.3  1998/10/12  13:59:16  mueller
+# discrete examples added
+#
+# Revision 1.2  1998/10/12  10:09:40  mueller
+# SISO example added, the augmented plant has one input
+# and two output.
+#
+# Revision 1.1  1998/10/12  08:52:21  mueller
+# Initial revision
+#
+# Revision 1.1.1.1  1998/05/19 20:24:06  jwe
+#
+# Revision 1.1  1998/05/05 17:03:42  scotte
+# Initial revision
+#
+# Revision 1.4  1998/05/05  09:49:19  mueller
+# comment corrections
+#
+# Revision 1.3  1998/05/05  08:46:27  mueller
+# comments added
+#
+# Revision 1.2  1998/05/04  17:49:56  mueller
+# miscellaneous cleanup
+#
+# Revision 1.1  1998/05/04  15:10:34  mueller
+# Initial revision
+#
+
+yn = [];
+while (length(yn) < 1)
+  yn = input(" * [s]iso, [m]imo, or [d]iscrete design? [no default]: ","S");
+endwhile
+if ((yn(1) == "s") | (yn(1) == 'S'))
+  sys_type = 1;
+elseif ((yn(1) == "m") | (yn(1) == 'M'))
+  sys_type = 2;
+elseif ((yn(1) == "d") | (yn(1) == 'D'))
+  sys_type = 3;
+else
+  disp(" *** no system type specified, hinfdemo terminated.");
+  return;
+endif
+
+echo off
+switch (sys_type)
+
+  case (1)
+    # siso
+    disp(" ");
+    disp("    ----------------------------------------------");
+    disp("    H_infinity optimal control for the SISO plant:");
+    disp(" ");
+    disp("		            s - 2");
+    disp("		G(s) = --------------");
+    disp("		       (s + 2)(s - 1)");
+    disp(" ");
+    disp("    ----------------------------------------------");
+    disp(" ");
+
+    # weighting on actuator u
+    W1 = wgt1o(0.05, 100.0, 425.0);
+    # weighting on controlled variable y
+    W2 = wgt1o(10.0, 0.05, 0.001);
+    # plant
+    G = tf2sys([1 -2],[1 1 -2]);
+
+    # need One as the pseudo transfer function One = 1
+    One = ugain(1);
+    disp(" o forming P...");
+    psys = buildssic([1 4;2 4;3 1],[3],[2 3 5],[3 4],G,W1,W2,One);
+    disp(" ");
+    disp(" o controller design...");
+    [K, gfin, GW]=hinfsyn(psys, 1, 1, 0.1, 10.0, 0.02);
+    disp(" ");
+    disp("-- OK ----------------------------------------------");
+
+    disp("  Closed loop poles:");
+    damp(GW);
+    # disp(" o Testing H_infinity norm: (hinfnorm does not work)");
+    # hinfnorm(GW);
+
+    disp(" ");
+    yn = input(" * Plot closed loop step response? [n]: ","S");
+    if (length(yn) >= 1)
+      if ((yn(1) == "y") || (yn(1) == 'Y'))
+      	disp(" o step responses of T and KS...");
+      	GW = buildssic([1 2; 2 1], [], [1 2], [-2], G, K);
+      	figure(1);
+      	step(GW, 1, 10);
+      endif
+    endif
+
+  case (2)
+    # mimo
+    disp(" ");
+    disp("    -----------------------------------------------");
+    disp("      H_inf optimal control for the jet707 plant");
+    disp("    -----------------------------------------------");
+    disp(" ");
+
+    # Weighting function on u (robustness weight)
+    ww1 = wgt1o(0.01,5,0.9);
+    ww2 = wgt1o(0.01,5,2.2);
+    W1 = buildssic([1 0;2 0],[],[1 2],[1 2],ww1,ww2);
+    # Weighting function on y (performance weight)
+    ww1 = wgt1o(250,0.1,0.0001);
+    ww2 = wgt1o(250,0.1,0.0002);
+    W2 = buildssic([1 0;2 0],[],[1 2],[1 2],ww1,ww2);
+    # plant (2 x 2 system)
+    G = jet707;
+
+    disp(" o forming P...");
+    One = ugain(2);
+    Clst = [1 7; 2 8; 3 7; 4 8; 5 1; 6 2];
+    P = buildssic(Clst,[5 6],[3:6 9 10],[1 2 5:8],G,W1,W2,One);
+
+    disp(" ");
+    disp(" o controller design...");
+    K = hinfsyn(P, 2, 2, 0.25, 10.0, 0.005);
+
+    disp(" ");
+    yn = input(" * Plot closed loop step responses? [n]: ","S");
+    if (length(yn) >= 1)
+      if ((yn(1) == "y") || (yn(1) == 'Y'))
+      	disp(" o step responses of T and KS...");
+      	GW = buildssic([1 3;2 4;3 1;4 2],[],[1 2 3 4],[-3 -4],G,K);
+
+      	disp(" ");
+      	disp("  FIGURE 1: speed refence => 1, pitch angle ref. => 0");
+      	disp("  ===================================================");
+      	disp("      y1:  speed                      (should be 1)");
+      	disp("      y2:  pitch            angle (should remain 0)");
+      	disp("      y3:  thrust      (should be a slow transient)");
+      	disp("      y6:  elevator  (should be a faster transient)");
+      	disp(" ");
+      	disp("  FIGURE 2: speed refence => 0, pitch angle ref. => 1");
+      	disp("  ===================================================");
+      	disp("      y1:  speed                  (should remain 0)");
+      	disp("      y2:  pitch                angle (should be 1)");
+      	disp("      y3:  thrust      (should be a slow transient)");
+      	disp("      y6:  elevator  (should be a faster transient)");
+      	disp(" ");
+      	figure(1)
+      	step(GW);
+      	figure(2)
+      	step(GW,2);
+      endif
+    endif
+
+  case (3)
+    # discrete
+    disp(" ");
+    disp("    --------------------------------------------------");
+    disp("    Discrete H_infinity optimal control for the plant:");
+    disp(" ");
+    disp("	                   0.199788z + 0.073498");
+    disp("	        G(s) = --------------------------");
+    disp("	               (z - 0.36788)(z - 0.13533)");
+    disp("    --------------------------------------------------");
+    disp(" ");
+
+    # sampling time
+    Ts = 1.0;
+    # weighting on actuator value u
+    W1 = wgt1o(0.1, 200.0, 50.0);
+    # weighting on controlled variable y
+    W2 = wgt1o(350.0, 0.05, 0.0002);
+    # omega axis
+    ww = logspace(-4.99, 3.99, 100);
+    if (columns(ww) > 1);  ww = ww';  endif
+
+    # continuous plant
+    G = tf2sys(2,[1 3 2]);
+    # discrete plant with zoh
+    Gd = c2d(G, Ts);
+    # w-plane (continuous representation of the sampled system)
+    Gw = d2c(Gd, "bi");
+
+    disp(" ");
+    disp(" o building P...");
+    # need One as the pseudo transfer function One = 1
+    One = ugain(1);
+    psys = buildssic([1 4;2 4;3 1],[3],[2 3 5],[3 4],Gw,W1,W2,One);
+    disp(" o controller design...");
+    [K, gfin, GWC] = hinfsyn(psys, 1, 1, 0.1, 10.0, 0.02);
+
+    disp(" ");
+    fig_n = 1;
+    yn = input(" * Plot magnitudes of W1KS and W2S? [n]: ","S");
+    if (length(yn) >= 1)
+      if ((yn(1) == "y") || (yn(1) == 'Y'))
+    	disp(" o magnitudes of W1KS and W2S...");
+    	gwx = sysprune(GWC, 1, 1);
+    	mag1 = bode(gwx, ww);
+    	if (columns(mag1) > 1);  mag1 = mag1';  endif
+    	gwx = sysprune(GWC, 2, 1);
+    	mag2 = bode(gwx, ww);
+    	if (columns(mag2) > 1);  mag2 = mag2';  endif
+    	figure(fig_n)
+    	fig_n = fig_n + 1;
+    	gset grid
+    	loglog(ww, [mag1 mag2]);
+      endif
+    endif
+
+    Kd = c2d(K, "bi", Ts);
+    GG = buildssic([1 2; 2 1], [], [1 2], [-2], Gd, Kd);
+    disp(" o closed loop poles...");
+    damp(GG);
+
+    disp(" ");
+    yn = input(" * Plot closed loop step responses? [n]: ","S");
+    if (length(yn) >= 1)
+      if ((yn(1) == "y") || (yn(1) == 'Y'))
+    	disp(" o step responses of T and KS...");
+    	figure(fig_n)
+    	step(GG, 1, 10);
+      endif
+    endif
+
+endswitch
+
+disp(" o hinfdemo terminated successfully.");
+
+# KPM-hinfdemo/End
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/hinfnorm.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,135 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [g gmin gmax] = hinfnorm(sys,tol,gmin,gmax,ptol)
+  # Usage: [g gmin gmax] = hinfnorm(sys[,tol,gmin,gmax,ptol])
+  #
+  # Computes the H infinity norm of a system data structure
+  # sys = system data structure
+  # tol = H infinity norm search tolerance (default: 0.001)
+  # gmin = minimum value for norm search (default: 1e-9)
+  # gmax = maximum value for norm search (default: 1e+9)
+  # ptol: pole tolerance:
+  #       if sys is continuous, poles with 
+  #         |real(pole)| < ptol*||H|| (H is appropriate Hamiltonian)
+  #         are considered to be on the imaginary axis.  
+  #       if sys is discrete, poles with
+  #         |abs(pole)-1| < ptol*||[s1,s2]|| (appropriate symplectic pencil)
+  #         are considered to be on the unit circle
+  #       Default: 1e-9
+  #
+  # References:
+  # Doyle, Glover, Khargonekar, Francis, "State space solutions to standard
+  #    H2 and Hinf control problems", IEEE TAC August 1989
+  # Iglesias and Glover, "State-Space approach to discrete-time Hinf control,"
+  #    Int. J. Control, vol 54, #5, 1991
+  # Zhou, Doyle, Glover, "Robust and Optimal Control," Prentice-Hall, 1996
+  # $Revision: 1.6 $
+
+  if((nargin == 0) || (nargin > 4))
+    usage("[g gmin gmax] = hinfnorm(sys[,tol,gmin,gmax,ptol])");
+  elseif(!is_struct(sys))
+    error("Sys must be a system data structure");
+  endif
+
+  # set defaults where applicable
+  if(nargin < 5)
+    ptol = 1e-9;	# pole tolerance
+  endif
+  if(nargin < 4)
+    gmax = 1e9;		# max gain value
+  endif
+
+  dflg = is_digital(sys);
+  sys = sysupdate(sys,"ss");
+  [A,B,C,D] = sys2ss(sys);
+  [n,nz,m,p] = sysdimensions(sys);
+
+  # eigenvalues of A must all be stable
+  if(!is_stable(sys))
+    warning(["hinfnorm: unstable system (is_stable, ptol=",num2str(ptol), ...
+      "), returning Inf"]);
+  endif
+
+  Dnrm = norm(D);
+  if(nargin < 3)
+    gmin = max(1e-9,Dnrm); 	# min gain value
+  elseif(gmin < Dnrm)
+    warning(["hinfnorm: setting Gmin=||D||=",num2str(Dnrm)]);
+  endif
+
+  if(nargin < 2)
+    tol = 0.001;	# convergence measure for gmin, gmax
+  endif
+
+  # check for scalar input arguments 2...5
+  if( ! (is_scalar(tol) && is_scalar(gmin) 
+	&& is_scalar(gmax) && is_scalar(ptol)) )
+    error("hinfnorm: tol, gmin, gmax, ptol must be scalars");
+  endif
+
+  In = eye(n+nz);
+  Im = eye(m);
+  Ip = eye(p);
+  # find the Hinf norm via binary search
+  while((gmax/gmin - 1) > tol)
+    g = (gmax+gmin)/2;
+
+    if(dflg)
+      # multiply g's through in formulas to avoid extreme magnitudes...
+      Rg = g^2*Im - D'*D;
+      Ak = A + (B/Rg)*D'*C;
+      Ck = g^2*C'*((g^2*Ip-D*D')\C);
+
+      # set up symplectic generalized eigenvalue problem per Iglesias & Glover
+      s1 = [Ak , zeros(nz) ; -Ck, In ];
+      s2 = [In, -(B/Rg)*B' ; zeros(nz) , Ak' ];
+
+      # guard against roundoff again: zero out extremely small values
+      # prior to balancing
+      s1 = s1 .* (abs(s1) > ptol*norm(s1,"inf"));
+      s2 = s2 .* (abs(s2) > ptol*norm(s2,"inf"));
+      [cc,dd,s1,s2] = balance(s1,s2);
+      [qza,qzb,zz,pls] = qz(s1,s2,"S");	# ordered qz decomposition
+      eigerr = abs(abs(pls)-1);
+      normH = norm([s1,s2]);
+      Hb = [s1 s2];
+
+      # check R - B' X B condition (Iglesias and Glover's paper)
+      X = zz((nz+1):(2*nz),1:nz)/zz(1:nz,1:nz);
+      dcondfailed = min(real( eig(Rg - B'*X*B)) < ptol);
+    else
+      Rinv = inv(g*g*Im - (D' * D));
+      H = [A + B*Rinv*D'*C,        B*Rinv*B'; ...
+           -C'*(Ip + D*Rinv*D')*C, -(A + B*Rinv*D'*C)'];
+      # guard against roundoff: zero out extremely small values prior 
+      # to balancing
+      H = H .* (abs(H) > ptol*norm(H,"inf"));
+      [DD,Hb] = balance(H);
+      pls = eig(Hb);
+      eigerr = abs(real(pls));
+      normH = norm(H);
+      dcondfailed = 0;		# digital condition; doesn't apply here
+    endif
+    if( (min(eigerr) <= ptol * normH) | dcondfailed)
+      gmin = g;
+    else
+      gmax = g;
+    endif
+  endwhile
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/hinfsyn.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,390 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [K,g,GW,Xinf,Yinf] = hinfsyn(Asys,nu,ny,gmin,gmax,gtol,ptol,tol)
+  # [K,g,GW,Xinf,Yinf] = hinfsyn(Asys,nu,ny,gmin,gmax,gtol[,ptol,tol])
+  #
+  # [1] Doyle, Glover, Khargonekar, Francis, "State Space Solutions
+  #     to Standard H2 and Hinf Control Problems," IEEE TAC August 1989
+  #
+  # [2] Maciejowksi, J.M.: "Multivariable feedback design,"
+  #     Addison-Wesley, 1989, ISBN 0-201-18243-2
+  #
+  # [3] Keith Glover and John C. Doyle: "State-space formulae for all
+  #     stabilizing controllers that satisfy and h-infinity-norm bound
+  #     and relations to risk sensitivity,"
+  #     Systems & Control Letters 11, Oct. 1988, pp 167-172.
+  #
+  # inputs: input system is passed as either
+  #        Asys: system data structure (see ss2sys, sys2ss)
+  #              - controller is implemented for continuous time systems 
+  #              - controller is NOT implemented for discrete time systems 
+  #        nu: number of controlled inputs
+  #        ny: number of measured outputs
+  #        gmin: initial lower bound on H-infinity optimal gain
+  #        gmax: initial upper bound on H-infinity optimal gain
+  #        gtol: gain threshhold.  Routine quits when gmax/gmin < 1+tol
+  #        ptol: poles with abs(real(pole)) < ptol*||H|| (H is appropriate
+  #              Hamiltonian) are considered to be on the imaginary axis.  
+  #              Default: 1e-9
+  #        tol: threshhold for 0.  Default: 200*eps
+  #
+  #        gmax, gmin, gtol, and tol must all be postive scalars.
+  # 
+  # outputs: 
+  #        K:   system controller
+  #        g:   designed gain value
+  #       GW:   closed loop system
+  #     Xinf:   ARE solution matrix for regulator subproblem
+  #     Yinf:   ARE solution matrix for filter subproblem
+
+
+  # A. S. Hodel August 1995
+  # Updated for Packed system structures December 1996 by John Ingram
+  # $Revision: 1.5 $
+  #
+  # Revised by Kai P Mueller April 1998 to solve the general H_infinity
+  # problem using unitary transformations Q (on w and z)
+  # and non-singular transformations R (on u and y).
+  # $Revision: 1.5 $
+  # $Log: hinfsyn.m,v $
+  # Revision 1.5  1998/08/24 15:50:10  hodelas
+  # updated documentation
+  #
+  # Revision 1.3  1998/07/01 16:23:37  hodelas
+  # Updated c2d, d2c to perform bilinear transforms.
+  # Updated several files per bug updates from users.
+  #
+  # Revision 1.2  1998/06/25 12:35:38  hodelas
+  # fixed controller input/output signal name code
+  #
+  # Revision 1.4  1998/06/25 12:40:35  hodel
+  # fixed error in input/output names in the controller
+  #
+  # Revision 1.3  1998/05/05 17:03:59  scotte
+  # update 5 May 1998 by Kai Mueller
+  #
+# Revision 1.2  1998/05/05  08:57:16  mueller
+# comments added
+#
+
+  old_page_val = page_screen_output;
+  page_screen_output = 0;
+
+  if( (nargin < 1) | (nargin > 8) )
+    usage("[K,g,GW,Xinf,Yinf] = hinfsyn(Asys,nu,ny,gmin,gmax,gtol,ptol,tol)");
+  endif
+  # set default arguments
+  if(nargin < 8)
+    tol = 200*eps;
+  elseif(!is_sample(tol))
+    error("tol must be a positive scalar.")
+  endif
+  if(nargin < 7)
+    ptol = 1e-9;
+  elseif(!is_sample(ptol))
+    error("hinfsyn: ptol must be a positive scalar");
+  endif
+    
+  if(!is_sample(gmax) | !is_sample(gmin) | !is_sample(gtol) )
+    error(["hinfsyn: gmax=",num2str(gmax),", gmin=",num2str(gmin), ...
+      "gtol=",num2str(gtol), " must be positive scalars."])
+  endif
+
+  [chkdgkf,dgs] = is_dgkf(Asys,nu,ny,tol);
+
+  if (! chkdgkf )
+    disp("hinfsyn: system does not meet required assumptions")
+    help is_dgkf
+    error("hinfsyn: exit");
+  endif
+
+  # extract dgs information
+  			nw = dgs.nw;	nu = dgs.nu;
+  A = dgs.A;		B1 = dgs.Bw;	B2 = dgs.Bu;
+  C1 = dgs.Cz;		D11 = dgs.Dzw;	D12 = dgs.Dzu;		nz = dgs.nz;
+  C2 = dgs.Cy;		D21 = dgs.Dyw;	D22 = dgs.Dyu;		ny = dgs.ny;
+  d22nz = dgs.Dyu_nz;
+  dflg = dgs.dflg;
+
+  # recover i/o transformations
+  R12 = dgs.Ru;		R21 = dgs.Ry;
+  [ncstates, ndstates, nin, nout] = sysdimensions(Asys);
+  Atsam = sysgettsam(Asys);
+  [Ast, Ain, Aout] = sysgetsignals(Asys);
+
+  BB = [B1 B2];
+  CC = [C1 ; C2];
+  DD = [D11 D12 ; D21  D22];
+
+  if (dflg == 0)
+    n = ncstates;
+    # perform binary search to find gamma min
+    ghi = gmax;
+    # derive a lower lower bound for gamma from D matrices
+    xx1 = norm((eye(nz) - (D12/(D12'*D12))*D12')*D11);
+    xx2 = norm(D11*(eye(nw)-(D21'/(D21*D21'))*D21));
+    glo = max(xx1, xx2);
+    if (glo > gmin)
+      disp(" *** D matrices indicate a greater value of gamma min.");
+      fprintf("     gamma min (%f) superseeded by %f.", gmin, glo);
+      glo = xx1;
+    else
+      glo = gmin;
+    endif
+    if (glo > ghi)
+      fprintf(" *** lower bound of gamma greater than upper bound(%f)", ...
+	      glo, ghi);
+      disp(" *** unable to continue, Goodbye.");
+      return;
+    endif
+
+    de = ghi - glo;
+    g = glo;
+    search_state = 0;
+    iteration_finished = 0;
+    disp(" o structural tests passed, start of iteration...");
+    disp("        o <-> test passed   # <-> test failed   - <-> cannot test");
+    printf("----------------------------------------");
+    printf("--------------------------------------\n");
+
+    # ------123456789012345678901234567890123456789012345678901234567890
+    printf("           .........X......... .........Y......... ");
+    printf(".Z. PASS REMARKS\n");
+    printf("        ga iax nev ene sym pos iax nev ene sym pos ");
+    printf("rho  y/n ======>\n");
+    printf("----------------------------------------");
+    printf("--------------------------------------\n");
+
+    # now do the search
+    while (!iteration_finished)
+      switch (search_state)
+        case (0)
+	  g = ghi;
+        case (1)
+	  g = glo;
+        case (2)
+	  g = 0.5 * (ghi + glo);
+        otherwise
+	  error(" *** This should never happen!");
+      endswitch
+      printf("%10.4f ", g);
+
+      # computing R and R~
+      d1dot = [D11 D12];
+      R = zeros(nin, nin);
+      R(1:nw,1:nw) = -g*g*eye(nw);
+      R = R + d1dot' * d1dot;
+      ddot1 = [D11; D21];
+      Rtilde = zeros(nout, nout);
+      Rtilde(1:nz,1:nz) = -g*g*eye(nz);
+      Rtilde = Rtilde + ddot1 * ddot1';
+
+      # build hamiltonian Ha for X_inf
+      xx = ([BB; -C1'*d1dot]/R) * [d1dot'*C1 BB'];
+      Ha = [A 0*A; -C1'*C1 -A'] - xx;
+      x_ha_err = 0;
+      # copied from from are(...)...
+      [d, Ha] = balance(Ha);
+      [u, s] = schur(Ha, "A");
+      rev = real(eig(s));
+      if (any(abs(rev) <= ptol))
+        # eigenvalues near the imaginary axis
+        x_ha_err = 1;
+      elseif (sum(rev > 0) != sum(rev < 0))
+        # unequal number of positive and negative eigenvalues
+	x_ha_err = 2;
+      else
+	# compute positive Riccati equation solution
+      	u = d * u;
+      	Xinf = u(n+1:2*n,1:n) / u(1:n,1:n);
+	if (!all(all(finite(Xinf))))
+	  x_ha_err = 3;
+	elseif (norm(Xinf-Xinf') >= 10*ptol)
+	  # solution not symmetric
+	  x_ha_err = 4;
+	else
+	  # positive semidefinite?
+	  rev = eig(Xinf);
+	  if (any(rev <= -ptol))
+	    x_ha_err = 5;
+	  endif
+	endif
+      endif
+      
+      # build hamiltonian Ha for Y_inf
+      xx = ([CC'; -B1*ddot1']/Rtilde) * [ddot1*B1' CC];
+      Ha = [A' 0*A; -B1*B1' -A] - xx;
+      y_ha_err = 0;
+      # copied from from are(...)...
+      [d, Ha] = balance(Ha);
+      [u, s] = schur(Ha, "A");
+      rev = real(eig(s));
+      if (any(abs(rev) <= ptol))
+        # eigenvalues near the imaginary axis
+        y_ha_err = 1;
+      elseif (sum(rev > 0) != sum(rev < 0))
+        # unequal number of positive and negative eigenvalues
+	y_ha_err = 2;
+      else
+	# compute positive Riccati equation solution
+      	u = d * u;
+      	Yinf = u(n+1:2*n,1:n) / u(1:n,1:n);
+	if (!all(all(finite(Yinf))))
+	  y_ha_err = 3;
+	elseif (norm(Yinf-Yinf') >= 10*ptol)
+	  # solution not symmetric
+	  x_ha_err = 4;
+     	else
+	  # positive semidefinite?
+	  rev = eig(Yinf);
+	  if (any(rev <= -ptol))
+	    y_ha_err = 5;
+	  endif
+	endif
+      endif
+
+      # assume failure for this gamma
+      passed = 0;
+      if (!x_ha_err && !y_ha_err)
+	# test spectral radius condition
+	rho = max(abs(eig(Xinf * Yinf)));
+	if (rho < g*g)
+	  # spectral radius condition passed
+	  passed = 1;
+	endif
+      endif
+
+      switch (x_ha_err)
+	case (0)
+	  #       iax nev ene sym pos
+	  printf(" o   o   o   o   o  ");
+          xerr = " ";
+	case (1)
+	  printf(" #   -   -   -   -  ");
+          xerr = "X im.eig.";
+	case (2)
+	  printf(" o   #   -   -   -  ");
+          xerr = "Hx not Ham.";
+	case (3)
+	  printf(" o   o   #   -   -  ");
+          xerr = "X inf.eig.";
+	case (4)
+	  printf(" o   o   o   #   -  ");
+          xerr = "X not symm.";
+	case (5)
+	  printf(" o   o   o   o   #  ");
+          xerr = "X not pos.";
+	otherwise
+	  error(" *** Xinf fail: this should never happen!");
+      endswitch
+      switch (y_ha_err)
+	case (0)
+	  #       iax nev ene sym pos rho
+	  if (passed)
+	    printf(" o   o   o   o   o   o    y  all tests passed.\n");
+	  elseif (x_ha_err)
+	    printf(" o   o   o   o   o   -    n  %s\n", xerr);
+	  else
+	    printf(" o   o   o   o   o   #    n  rho=%f.\n", rho);
+	  endif
+	case (1)
+	  printf(" #   -   -   -   -   -    n  %s/Y im. eig.", xerr);
+	case (2)
+	  printf(" o   #   -   -   -   -    n  %s/Hy not Ham.", xerr);
+	case (3)
+	  printf(" o   o   #   -   -   -    n  %s/Y inf.eig.", xerr);
+	case (4)
+	  printf(" o   o   o   #   -   -    n  %s/Y not symm.", xerr);
+	case (5)
+	  printf(" o   o   o   o   #   -    n  %s/Y not pos.", xerr);
+	otherwise
+	  error(" *** Yinf fail: this should never happen!");
+      endswitch
+
+
+      if (passed && (de/g < gtol))
+	search_state = 3;
+      endif
+
+      switch (search_state)
+        case (0)
+	  if (!passed)
+	    # upper bound must pass but did not
+	    fprintf(" *** the upper bound of gamma (%f) is too small.\n", g);
+	    iteration_finished = 2;
+	  else
+            search_state = 1;
+	  endif
+        case (1)
+	  if (!passed)
+            search_state = 2;
+	  else
+	    # lower bound must not pass but passed
+	    fprintf(" *** the lower bound of gamma (%f) passed.\n", g);
+	    iteration_finished = 3;
+	  endif
+        case (2)
+	  if (!passed)
+	    glo = g;
+	  else
+	    ghi = g;
+	  endif
+	    de = ghi - glo;
+        case (3)
+	  # done
+	  iteration_finished = 1;
+        otherwise
+	  error(" *** This should never happen!");
+      endswitch
+    endwhile
+
+    printf("----------------------------------------");
+    printf("--------------------------------------\n");
+    if (iteration_finished != 1)
+      K = [];
+    else
+      # success: compute controller
+      fprintf("   hinfsyn final: glo=%f ghi=%f, test gain g=%f\n", \
+              glo, ghi, g);
+      printf("----------------------------------------");
+      printf("--------------------------------------\n");
+      Z = inv(eye(ncstates) - Yinf*Xinf/g/g);
+      F = -R \ (d1dot'*C1 + BB'*Xinf);
+      H = -(B1*ddot1' + Yinf*CC') / Rtilde;
+      K = hinf_ctr(dgs,F,H,Z,g);
+
+      Kst = strappend(Ast,"_K");
+      Kin = strappend(Aout((nout-ny+1):(nout),:),"_K");
+      Kout = strappend(Ain((nin-nu+1):(nin),:),"_K");
+      [Ac, Bc, Cc, Dc] = sys2ss(K);
+      K = ss2sys(Ac,Bc,Cc,Dc,Atsam,ncstates,ndstates,Kst,Kin,Kout);
+      if (nargout >= 3)
+	GW = starp(Asys, K);
+      endif
+    endif
+    
+  elseif(ndstates)
+
+    # discrete time solution
+    error("hinfsyn: discrete-time case not yet implemented")
+
+  endif
+
+  page_screen_output = old_page_val;
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/hinfsyn_chk.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,88 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [retval,Pc,Pf] = hinfsyn_chk(A,B1,B2,C1,C2,D12,D21,g,ptol)
+  # [retval,Pc,Pf] = hinfsyn_chk(A,B1,B2,C1,C2,D12,D21,g,ptol)
+  #
+  # Called by hinfsyn to see if gain g satisfies conditions in Theorem 3 of
+  # Doyle, Glover, Khargonekar, Francis, "State Space Solutions to Standard
+  # H2 and Hinf Control Problems", IEEE TAC August 1989
+  # 
+  # inputs:
+  #   g = candidate gain level
+  #   ptol: as in hinfsyn
+  #   remaining parameters as returned by is_dgkf
+  # outputs: 
+  #   retval: = 1 if g exceeds optimal Hinf closed loop gain, else 0
+  #   Pc: solution of "regulator" H-inf ARE
+  #   Pf: solution of "filter" H-inf ARE
+  #
+  # Do not attempt to use this at home; no argument checking performed.
+
+  # A. S. Hodel August 1995
+  # $Revision: 1.1 $
+
+  Pc = Pf = [];
+
+  # Construct the two Hamiltonians
+  g2 = 1/(g*g);
+  Hc = [ A ,  g2*B1*B1' - B2*B2'; -C1'*C1 , -A'];
+  Hf = [ A' , g2*C1'*C1 - C2'*C2; -B1*B1' , -A];
+
+  # check if Hc, Hf are in dom(Ric)
+  Hcminval = min(abs(real(eig(Hc))));
+  Hfminval = min(abs(real(eig(Hf))));
+  if(Hcminval < ptol);
+    disp("hinfsyn_chk: Hc is not in dom(Ric)");
+    retval = 0;
+    return
+  endif
+  if(Hfminval < ptol)
+    disp("hinfsyn_chk: Hf is not in dom(Ric)");
+    retval = 0;
+    return
+  endif
+
+  #Solve ARE's
+  Pc = are(A, B2*B2'-g2*B1*B1',C1'*C1);
+  Pf = are(A',C2'*C2-g2*C1'*C1,B1*B1');
+
+  Pceig = eig(Pc);
+  Pfeig = eig(Pf);
+  Pcfeig = eig(Pc*Pf);
+
+  if(min(Pceig) < -ptol)
+    disp("hinfsyn_chk: Pc is not >= 0");
+    retval = 0;
+    return
+  endif
+  if(min(Pfeig) < -ptol)
+    disp("hinfsyn_chk: Pf is not >= 0");
+    retval = 0;
+    return
+  endif
+  if(max(abs(Pcfeig)) >= g*g)
+    disp("hinfsyn_chk: rho(Pf*Pc) is not < g^2");
+    retval = 0;
+    return
+  endif
+ 
+  # all conditions met.
+  retval = 1;
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/impulse.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,86 @@
+# Copyright (C) 1996 A. Scottedward Hodel
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [y, t] = impulse(sys, inp, tstop, n)
+# step: Impulse response for a linear system.
+#       The system can be discrete or multivariable (or both).
+#
+# [y, t] = impulse(sys[, inp, tstop, n])
+# Produces a plot or the step response data for system sys.
+#
+# The argument tstop (scalar value) denotes the time when the
+# simulation should end. The Parameter n is the number of data values.
+# Both parameters tstop and n can be ommitted and will be
+# computed from the eigenvalues of the A-Matrix.
+#
+# When the step function is invoked with the output parameter y
+# a plot is not displayed.
+#
+# See also: step, stepimp
+
+# Written by Kai P. Mueller October 2, 1997
+# based on lsim.m of Scottedward Hodel
+# modified by
+# $Revision: 1.1.1.1 $
+# $Log: impulse.m,v $
+# Revision 1.1.1.1  1998/05/19 20:24:07  jwe
+#
+# Revision 1.3  1997/12/01 16:51:50  scotte
+# updated by Mueller 27 Nov 97
+#
+# Revision 1.1  1997/11/11  17:33:06  mueller
+# Initial revision
+#
+
+  if((nargin < 1) || (nargin > 4))
+    usage("[y, u] = impulse(sys[, inp, tstop, n])");
+  endif
+
+  if(nargout > 2)
+    usage("[y, u] = impulse(sys[, inp, tstop, n])");
+  endif
+
+  if(!is_struct(sys))
+    error("impulse: sys must be a system data structure.");
+  endif
+
+  if (nargout == 0)
+    switch (nargin)
+      case (1)
+        stepimp(2, sys);
+      case (2)
+        stepimp(2, sys, inp);
+      case (3)
+        stepimp(2, sys, inp, tstop);
+      case (4)
+        stepimp(2, sys, inp, tstop, n);
+    endswitch
+  else
+    switch (nargin)
+      case (1)
+        [y, t] = stepimp(2, sys);
+      case (2)
+        [y, t] = stepimp(2, sys, inp);
+      case (3)
+        [y, t] = stepimp(2, sys, inp, tstop);
+      case (4)
+        [y, t] = stepimp(2, sys, inp, tstop, n);
+    endswitch
+  endif
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/is_abcd.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,106 @@
+# Copyright (C) 1997 Kai P. Mueller
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+
+function retval = is_abcd(a, b, c, d)
+  # ------------------------------------------------------
+  # retval = is_abcd(a [, b, c, d])
+  # Returns retval = 1 if the dimensions of a, b, c, d
+  # are compatible, otherwise retval = 0.
+  # The matrices b, c, or d may be omitted.
+  # ------------------------------------------------------
+  # 
+  # see also: abcddim
+
+  # Written by Kai P. Mueller November 4, 1997
+  # based on is_controllable.m of Scottedward Hodel
+  # modified by
+  # $Revision: 1.1.1.1 $
+  # $Log: is_abcd.m,v $
+  # Revision 1.1.1.1  1998/05/19 20:24:07  jwe
+  #
+  # Revision 1.1  1997/12/01 16:51:50  scotte
+  # Initial revision
+  #
+# Revision 1.1  1997/11/25  11:17:41  mueller
+# Initial revision
+#
+
+  retval = 0;
+  switch (nargin)
+    case (1)
+      # A only
+      [na, ma] = size(a);
+      if (na != ma)
+        disp("Matrix A ist not square.")
+      endif
+    case (2)
+      # A, B only
+      [na, ma] = size(a);  [nb, mb] = size(b);
+      if (na != ma)
+        disp("Matrix A ist not square.")
+	return;
+      endif
+      if (na != nb)
+        disp("A and B column dimension different.")
+        return;
+      endif
+    case (3)
+      # A, B, C only
+      [na, ma] = size(a);  [nb, mb] = size(b);  [nc, mc] = size(c);
+      if (na != ma)
+        disp("Matrix A ist not square.")
+	return;
+      endif
+      if (na != nb)
+        disp("A and B column dimensions not compatible.")
+	return;
+      endif
+      if (ma != mc)
+        disp("A and C row dimensions not compatible.")
+	return;
+      endif
+    case (4)
+      # all matrices A, B, C, D
+      [na, ma] = size(a);  [nb, mb] = size(b);
+      [nc, mc] = size(c);  [nd, md] = size(d);
+      if (na != ma)
+        disp("Matrix A ist not square.")
+	return;
+      endif
+      if (na != nb)
+        disp("A and B column dimensions not compatible.")
+	return;
+      endif
+      if (ma != mc)
+        disp("A and C row dimensions not compatible.")
+	return;
+      endif
+      if (mb != md)
+        disp("B and D row dimensions not compatible.")
+	return;
+      endif
+      if (nc != nd)
+        disp("C and D column dimensions not compatible.")
+	return;
+      endif
+    otherwise
+      usage("retval = is_abcd(a [, b, c, d])")
+  endswitch
+  # all tests passed, signal ok.
+  retval = 1;
+endfunction
--- a/scripts/control/is_controllable.m	Thu Nov 05 04:24:46 1998 +0000
+++ b/scripts/control/is_controllable.m	Fri Nov 06 16:16:31 1998 +0000
@@ -1,76 +1,96 @@
-## Copyright (C) 1996, 1997 John W. Eaton
-##
-## 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-1307, USA.
-
-## Usage: is_controllable (a, b {,tol})
-##
-## Returns 1 if the pair (a, b) is controllable, or 0 if not.
-##
-## See also: size, rows, columns, length, is_matrix, is_scalar, is_vector
-##
-## This should really use the method below, but I'm being lazy for now:
-##
-## Controllability is determined by applying Arnoldi iteration with
-## complete re-orthogonalization to obtain an orthogonal basis of the
-## Krylov subspace.
-##
-## (FIX ME... The Krylov subspace approach is not done yet!)
-##                      n-1
-##   span ([b,a*b,...,a^   b]).
-##
-## tol is a roundoff paramter, set to 2*eps if omitted.
+# Copyright (C) 1993, 1994, 1995 John W. Eaton
+# 
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA.
 
-## Author: A. S. Hodel <scotte@eng.auburn.edu>
-## Created: August 1993
-## Adapted-By: jwe
-
-function retval = is_controllable (a, b, tol)
-
-  if (nargin == 2 || nargin == 3)
-
-    n = is_square (a);
-    [nr, nc] = size (b);
-
-    if (n == 0 || n != nr || nc == 0)
-      retval = 0;
-    else
+function [retval,U] = is_controllable (a, b, tol)
+# [retval, U] = is_controllable (a, b {,tol})
+#             = is_controllable (sys{, tol})
+#      Returns retval=1 if the system sys or the pair (a, b) is controllable
+#                     0 if not.
+# U is an orthogonal basis of the controllable subspace. 
+#
+# Controllability is determined by applying Arnoldi iteration with
+# complete re-orthogonalization to obtain an orthogonal basis of the
+# Krylov subspace.
+#
+#   span ([b,a*b,...,a^   b]).
+#
+# tol is a roundoff paramter, set to 10*eps if omitted.
+#
+# See also: size, rows, columns, length, is_matrix, is_scalar, is_vector
+#     is_observable, is_stabilizable, is_detectable, krylov, krylovb
 
-      m = b;
-      tmp = b;
-      for ii = 1:(n-1)
-        tmp = a * tmp;
-        m = [m, tmp];
-      endfor
-
-      ## If n is of any significant size, m will be low rank, so be careful!
+# Written by A. S. Hodel (scotte@eng.auburn.edu) August, 1993.
+# Updated by A. S. Hodel (scotte@eng.auburn.edu) Aubust, 1995 to use krylovb 
+# Updated by John Ingram (ingraje@eng.auburn.edu) July, 1996 for packed systems
+# SYS_INTERNAL accesses members of packed system structure
+# $Revision: 1.14 $
 
-      if (nargin == 3)
-        if (is_scalar (tol))
-          retval = (rank (m, tol) == n);
-        else
-          error ("is_controllable: tol must be a scalar");
-        endif
-      else
-        retval = (rank (m) == n);
-      endif
+  deftol = 1;    # assume default tolerance
+  if(nargin < 1 | nargin > 3)
+    usage(sprintf("[retval,U] = %s\n\t%s", "is_controllable(a {, b ,tol})", ...
+	"is_controllable(sys{,tol})"));
+  elseif(is_struct(a))
+    # system structure passed.
+    sys = sysupdate(a,"ss");
+    [a,bs] = sys2ss(sys);
+    if(nargin > 2)
+      usage("[retval,U] = is_controllable(sys{,tol})");
+    elseif(nargin == 2)
+      tol = b;		% get tolerance
+      deftol = 0;
     endif
+    b = bs;
   else
-    usage ("is_controllable (a, b)");
+    # a,b arguments sent directly.
+    if(nargin < 2)
+      usage("[retval,U] = is_controllable(a {, b ,tol})");
+    else
+      deftol = 1;
+    endif
   endif
 
+  # check for default tolerance
+  if(deftol) tol = 1000*eps; endif
+
+  # check tol dimensions
+  if( !is_sample(tol) )
+    error("is_controllable: tol must be a positive scalar!");
+  endif
+
+  # check dimensions compatibility
+  n = is_square (a);
+  [nr, nc] = size (b);
+
+  if (n == 0 | n != nr | nc == 0)
+    warning(["is_controllable: a=(",num2str(rows(a)),"x", ...
+      num2str(columns(a)),"), b=(",num2str(nr),"x",num2str(nc),")"])
+    retval = 0;
+  else
+    # call block-krylov subspace routine to get an orthogonal basis
+    # of the controllable subspace.
+    if(nc == 1)
+      [U,H,Ucols] = krylov(a,b,n,tol);
+      U = U(:,1:Ucols);
+    else
+      [U,Ucols] = krylovb(a,b,n,tol);
+      U = U(:,1:Ucols);
+    endif
+
+    retval = (Ucols == n);
+  endif
 endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/is_detectable.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,60 @@
+# Copyright (C) 1993, 1994, 1995 John W. Eaton
+# 
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+function [retval,U] = is_detectable (a,c,tol)
+
+# [retval,U] = is_detectable (a,c,tol)
+# usage: is_detectable (a , c {,tol})
+#     or is_detectable (sys {,tol})
+#
+# Default: tol = 10*norm(a,'fro')*eps
+#
+# Returns 1 if the system, a, is detectable, 1 if the pair (a, c) is 
+# detectable, or 0 if not.
+#
+# See also: size, rows, columns, length, is_matrix, is_scalar, is_vector.
+
+# Written by A. S. Hodel (scotte@eng.auburn.edu) August 1993.
+# Updated by John Ingram (ingraje@eng.auburn.edu) July 1996.
+# SYS_INTERNAL accesses members of system structure
+# $Revision: 1.1.1.1 $ 
+
+  if( nargin < 1) 
+    usage("[retval,U] = is_detectable(a , c {, tol})");
+  elseif(is_struct(a))
+    # system form
+    if(nargin == 2)
+      tol = c;
+    elseif(nargin > 2)
+      usage("[retval,U] = is_detectable(sys {, tol})");
+    endif
+    a = sysupdate(a,"ss");
+    c = a.c;
+    a = a.a;
+  elseif(nargin > 3)
+    usage("[retval,U] = is_detectable(a , c {, tol})");
+  endif
+  if(exist("tol"))
+    [retval,U] = is_stabilizable (a', c', tol);
+  else
+    [retval,U] = is_stabilizable (a', c');
+  endif
+  
+
+endfunction
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/is_dgkf.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,240 @@
+# Copyright (C) 1996,1998 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [retval,dgkf_struct] = is_dgkf(Asys,nu,ny,tol)
+  # function [retval,dgkf_struct] = is_dgkf(Asys,nu,ny{,tol})
+  # Determine whether a continuous time state space system meets
+  # assumptions of DGKF algorithm.  
+  # Partitions system into: [z] = [A  | Bw  Bu  ][w]
+  #                         [y]   [Cz | Dzw Dzu ][u]
+  #                               [Cy | Dyw Dyu ]
+  #If necessary, orthogonal transformations Qw, Qz and nonsingular
+  # transformations Ru, Ry are applied to respective vectors w, z, u, y 
+  # in order to satisfy DGKF assumptions.  Loop shifting is used if Dyu block
+  # is nonzero.
+  #
+  # inputs: 
+  #        Asys: structured system
+  #	   nu: number of controlled inputs
+  #        ny: number of measured outputs
+  #        tol: threshhold for 0.  Default: 200*eps
+  # outputs: 
+  #    retval: true(1) if system passes check, false(0) otherwise
+  #    dgkf_struct: data structure of is_dgkf results.  Entries:
+  #      nw, nz: dimensions of w, z
+  #      A: system A matrix
+  #      Bw: (n x nw) Qw-transformed disturbance input matrix
+  #      Bu: (n x nu) Ru-transformed controlled input matrix;
+  #          Note: B = [Bw Bu] 
+  #      Cz: (nz x n) Qz-transformed error output matrix
+  #      Cy: (ny x n) Ry-transformed measured output matrix 
+  #          Note: C = [Cz; Cy] 
+  #      Dzu, Dyw: off-diagonal blocks of transformed D matrix that enter 
+  #          z, y from u, w respectively
+  #      Ru: controlled input transformation matrix 
+  #      Ry: observed output transformation matrix
+  #      Dyu_nz: nonzero if the Dyu block is nonzero.
+  #      Dyu: untransformed Dyu block
+  #      dflg: nonzero if the system is discrete-time
+  #   
+  #    is_dgkf exits with an error if the system is mixed discrete/continuous
+  #
+  # [1] Doyle, Glover, Khargonekar, Francis, "State Space Solutions
+  #     to Standard H2 and Hinf Control Problems," IEEE TAC August 1989
+  #
+  # [2] Maciejowksi, J.M.: "Multivariable feedback design,"
+  #     Addison-Wesley, 1989, ISBN 0-201-18243-2
+  #
+  # [3] Keith Glover and John C. Doyle: "State-space formulae for all
+  #     stabilizing controllers that satisfy and h-infinity-norm bound
+  #     and relations to risk sensitivity,"
+  #     Systems & Control Letters 11, Oct. 1988, pp 167-172.
+  # [4] P. A. Iglesias and K. Glover, "State-space approach to discrete-time
+  #     H-infinity control."  Int. J. Control, 1991, V. 54, #5, 1031-1073.
+  #
+  
+  #  Written by A. S. Hodel
+  #  Updated by John Ingram July 1996 to accept structured systems
+  #  $Revision: 1.7 $
+  #
+  # Revised by Kai P Mueller April 1998 to solve the general H_infinity
+  # problem using unitary transformations Q (on w and z)
+  # and non-singular transformations R (on u and y) such
+  # that the Dzu and Dyw matrices of the transformed plant
+  #
+  #    ~
+  #    P  (the variable Asys here)
+  #
+  # become
+  #
+  #    ~            -1         T
+  #    D  = Q   D   R   = [ 0 I ]  or [ I ],
+  #     12   12  12  12
+  #
+  #    ~            T
+  #    D  = R   D   Q   = [ 0 I ] or [ I ].
+  #     21   21  21  21
+  #
+  # This transformation together with the algorithm in [1] solves
+  # the general problem (see [2] for example). 
+  # $Revision: 1.7 $
+  # $Log: is_dgkf.m,v $
+  # Revision 1.7  1998/08/19 19:11:18  hodelas
+  # uniform interface for is_dgkf among h2syn, hinfsyn
+  #
+  # Revision 1.6  1998/07/13 21:05:03  hodelas
+  # Updated for discrete time systems
+  #
+  # fixed typo in error messages; use system functions instead of
+  #   direct access to system structure
+  #
+
+  if (nargin < 3) | (nargin > 4)
+    usage("[retval,dgkf_struct] = is_dgkf(Asys,nu,ny{,tol})");
+  elseif (! is_scalar(nu) | ! is_scalar(ny) )
+    error("is_dgkf: arguments 2 and 3 must be scalars")
+  elseif (! is_struct(Asys) )
+    error("Argument 1 must be a system data structure");
+  endif
+  if(nargin < 4)
+    tol = 200*eps;
+  elseif( !is_sample(tol) )
+    error("is_dgkf: tol must be a positive scalar")
+  endif
+
+  retval = 1;		# assume passes test
+
+  dflg = is_digital(Asys);
+  [Anc, Anz, nin, nout ] = sysdimensions(Asys);
+
+  if( Anz == 0 & Anc == 0 )
+    error("is_dgkf: no system states");
+  elseif( nu >= nin )
+    error("is_dgkf: insufficient number of disturbance inputs");
+  elseif( ny >= nout )
+    error("is_dgkf: insufficient number of regulated outputs");
+  endif
+
+  nw = nin - nu;           nw1 = nw + 1;
+  nz = nout - ny;          nz1 = nz + 1;
+
+  [A,B,C,D] = sys2ss(Asys);
+  # scale input/output for numerical reasons
+  if(norm(C,'fro')*norm(B,'fro') == 0)
+    error("||C||*||B|| = 0; no dynamic connnection from inputs to outputs");
+  endif
+  xx = sqrt(norm(B, Inf) / norm(C, Inf));
+  B = B / xx;  C = C * xx;
+
+  # partition matrices
+  			Bw = B(:,1:nw);		Bu = B(:,nw1:nin);
+  Cz = C(1:nz,:);	Dzw = D(1:nz,1:nw);	Dzu = D(1:nz,nw1:nin);
+  Cy = C(nz1:nout,:);	Dyw = D(nz1:nout,1:nw);	Dyu = D(nz1:nout,nw1:nin);
+
+  # Check for loopo shifting
+  Dyu_nz = (norm(Dyu,Inf) != 0);
+  if (Dyu_nz)
+    warning("is_dgkf: D22 nonzero; performing loop shifting");
+  endif
+
+  # 12 - rank condition at w = 0
+  xx =[A Bu; Cz Dzu];
+  [nr, nc] = size(xx);
+  irank = rank(xx);
+  if (irank != nc)
+    retval = 0;
+    warning(sprintf("rank([A Bu; Cz Dzu]) = %d, need %d; n=%d, nz=%d, nu=%d", ...
+	irank,nc,(Anc+Anz),nz,nu));
+    warning(" *** 12-rank condition violated at w = 0.");
+  endif
+
+  # 21 - rank condition at w = 0
+  xx =[A Bw; Cy Dyw];
+  [nr, nc] = size(xx);
+  irank = rank(xx);
+  if (irank != nr)
+    retval = 0;
+    warning(sprintf("rank([A Bw; Cy Dyw]) = %d, need %d; n=%d, ny=%d, nw=%d", ...
+	irank,nr,(Anc+Anz),ny,nw));
+    warning(" *** 21-rank condition violated at w = 0.");
+  endif
+
+  # can Dzu be transformed to become [0 I]' or [I]?
+  # This ensures a normalized weight
+  [Qz, Ru] = qr(Dzu);
+  irank = rank(Ru);
+  if (irank != nu)
+    retval = 0;
+    warning(sprintf("*** rank(Dzu(%d x %d) = %d", nz, nu, irank));
+    warning(" *** Dzu does not have full column rank.");
+  endif
+  if (nu >= nz)
+    Qz = Qz(:,1:nu)';
+  else
+    Qz = [Qz(:,(nu+1):nz) Qz(:,1:nu)]';
+  endif
+  Ru = Ru(1:nu,:);
+
+  # can Dyw be transformed to become [0 I] or [I]?
+  # This ensures a normalized weight
+  [Qw, Ry] = qr(Dyw');
+  irank = rank(Ry);
+  if (irank != ny)
+    retval = 0;
+    warning(sprintf("*** rank(Dyw(%d x %d) = %d", ny, nw, irank));
+    warning(" *** Dyw does not have full row rank.");
+  endif
+
+  if (ny >= nw)
+    Qw = Qw(:,1:ny);
+  else
+    Qw = [Qw(:,(ny+1):nw) Qw(:,1:ny)];
+  endif
+  Ry = Ry(1:ny,:)';
+
+  # transform P by Qz/Ru and Qw/Ry
+  Bw  = Bw*Qw;
+  Bu  = Bu/Ru;
+  B   = [Bw Bu];
+  Cz  = Qz*Cz;
+  Cy  = Ry\Cy;
+  C   = [Cz; Cy];
+  Dzw = Qz*Dzw*Qw;
+  Dzu = Qz*Dzu/Ru;
+  Dyw = Ry\Dyw*Qw;
+
+  # pack the return structure
+  dgkf_struct.nw	= nw;
+  dgkf_struct.nu	= nu;
+  dgkf_struct.nz	= nz;
+  dgkf_struct.ny	= ny;
+  dgkf_struct.A		= A;
+  dgkf_struct.Bw	= Bw;
+  dgkf_struct.Bu	= Bu;
+  dgkf_struct.Cz	= Cz;
+  dgkf_struct.Cy	= Cy;
+  dgkf_struct.Dzw	= Dzw;
+  dgkf_struct.Dzu	= Dzu;
+  dgkf_struct.Dyw	= Dyw;
+  dgkf_struct.Dyu	= Dyu;
+  dgkf_struct.Ru	= Ru;
+  dgkf_struct.Ry	= Ry;
+  dgkf_struct.Dyu_nz	= Dyu_nz;
+  dgkf_struct.dflg	= dflg;
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/is_digital.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,39 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function DIGITAL = is_digital(sys)
+# function DIGITAL = is_digital(sys)
+# retrurn nonzero if system is digital
+# exits with an error of sys is a mixed (continuous and discrete) system
+
+# a s hodel July 1996
+# $Revision: 1.1.1.1 $
+# SYS_INTERNAL accesses members of system structure
+
+  # checked for sampled data system (mixed)
+  # discrete system
+  cont = sum(sys.yd == 0) + sys.n;
+  dig = sum(sys.yd != 0) + sys.nz + sys.tsam;
+  if( cont*dig != 0)
+   sysout(sys);
+   error("continuous/discrete system; use syscont, sysdisc, or c2d first");
+  else
+    DIGITAL = (sys.tsam > 0);
+  endif
+ 
+endfunction
--- a/scripts/control/is_observable.m	Thu Nov 05 04:24:46 1998 +0000
+++ b/scripts/control/is_observable.m	Fri Nov 06 16:16:31 1998 +0000
@@ -1,40 +1,59 @@
-## Copyright (C) 1996, 1997 John W. Eaton
-##
-## 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-1307, USA.
+# Copyright (C) 1993, 1994, 1995 John W. Eaton
+# 
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+function [retval,U] = is_observable (a,c,tol)
 
-## usage: is_observable (a, c {,tol})
-##
-## Returns 1 if the pair (a, c) is observable, or 0 if not.
-##
-## See also: size, rows, columns, length, is_matrix, is_scalar, is_vector.
+# [retval,U] = is_observable (a,c,tol)
+# usage: is_observable (a , c {,tol})
+#     or is_observable (sys {,tol})
+#
+# Default: tol = 10*norm(a,'fro')*eps
+#
+# Returns 1 if the system, a, is observable, 1 if the pair (a, c) is 
+# observable, or 0 if not.
+#
+# See also: size, rows, columns, length, is_matrix, is_scalar, is_vector.
+
+# Written by A. S. Hodel (scotte@eng.auburn.edu) August 1993.
+# Updated by John Ingram (ingraje@eng.auburn.edu) July 1996.
+# SYS_INTERNAL accesses members of system structure
+# $Revision: 1.14 $ 
 
-## Author: A. S. Hodel <scotte@eng.auburn.edu>
-## Created: August 1993
-## Adapted-By: jwe
-
-function retval = is_observable (a,c,tol)
-
-  if (nargin == 2)
-    retval = is_controllable (a', c');
-  elseif (nargin == 3)
-    retval = is_controllable (a', c', tol);
+  if( nargin < 1) 
+    usage("[retval,U] = is_observable(a , c {, tol})");
+  elseif(is_struct(a))
+    # system form
+    if(nargin == 2)
+      tol = c;
+    elseif(nargin > 2)
+      usage("[retval,U] = is_observable(sys {, tol})");
+    endif
+    a = sysupdate(a,"ss");
+    c = a.c;
+    a = a.a;
+  elseif(nargin > 3)
+    usage("[retval,U] = is_observable(a , c {, tol})");
+  endif
+  if(exist("tol"))
+    [retval,U] = is_controllable (a', c', tol);
   else
-    usage ("is_observable (a, c {,tol})");
+    [retval,U] = is_controllable (a', c');
   endif
 
 endfunction
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/is_sample.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,29 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function out = is_sample(Ts)
+#
+# out = is_sample(Ts): return true if Ts is a legal sampling time
+# (real,scalar, > 0)
+
+# A. S. Hodel July 1995
+# $Revision: 1.1 $
+
+out = (is_scalar(Ts) && (Ts == abs(Ts)) && (Ts != 0) );
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/is_siso.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,37 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function  SISO = is_siso(sys)
+# function SISO = is_siso(sys)
+# return nonzero if the system sys is single-input, single-output.
+
+# a s hodel July 1996, 1998
+# $Revision: 1.2 $
+# SYS_INTERNAL accesses members of system structure
+
+  if(nargin != 1)
+    usage("SISO = is_siso(sys)");
+  elseif( !is_struct(sys))
+    error("input must be a system structure (see ss2sys, tf2sys, zp2sys)");
+  endif
+
+  [n,nz,m,p] = sysdimensions(sys);
+
+  SISO = (m == 1 & p == 1);
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/is_stabilizable.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,96 @@
+# Copyright (C) 1993, 1994, 1995 John W. Eaton
+# 
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+function [retval,U] = is_stabilizable (a, b, tol)
+
+# Usage: [retval,U] = is_stabilizable (a {, b, tol})
+#
+# Returns retval = 1 if the system, a, is stabilizable, if the pair (a, b) is 
+# stabilizable, or 0 if not.
+#         U = orthogonal basis of controllable subspace.
+#
+# Controllable subspace is determined by applying Arnoldi iteration with
+# complete re-orthogonalization to obtain an orthogonal basis of the
+# Krylov subspace.
+#
+#   span ([b,a*b,...,a^   b]).
+#
+# tol is a roundoff paramter, set to 200*eps if omitted.
+#
+# See also: size, rows, columns, length, is_matrix, is_scalar, is_vector
+#     is_observable, is_stabilizable, is_detectable, krylov, krylovb
+
+# Written by A. S. Hodel (scotte@eng.auburn.edu) August, 1993.
+# Updated by A. S. Hodel (scotte@eng.auburn.edu) Aubust, 1995 to use krylovb 
+# Updated by John Ingram (ingraje@eng.auburn.edu) July, 1996 to accept systems
+# SYS_INTERNAL accesses members of system structure
+# $Revision: 1.1.1.1 $
+
+  if(nargin < 1)
+    usage("[retval,U] = is_stabilizable(a {, b ,tol})");
+  elseif(is_struct(a))
+    # sustem passed.
+    if(nargin == 2)
+      tol = b;          % get tolerance
+    elseif(nargin > 2)
+      usage("[retval,U] = is_stabilizable(sys{,tol})");
+    endif
+    sys = sysupdate(a,"ss");
+    a = sys.a;
+    b = sys.b;
+  else
+    # a,b arguments sent directly.
+    if(nargin > 3)
+      usage("[retval,U] = is_stabilizable(a {, b ,tol})");
+    endif
+  endif
+
+  if(exist("tol"))
+    [retval,U] = is_controllable(a,b,tol);
+  else
+    [retval,U] = is_controllable(a,b);
+    tol = 1e2*rows(b)*eps;
+  endif
+  
+  #disp("is_stabilzable: is_controllable returns")
+  #retval
+  #U
+  #disp("/is_stabilzable: is_controllable returns")
+
+  if( !retval & columns(U) > 0)
+    # now use an ordered Schur decomposition to get an orthogonal
+    # basis of the unstable subspace...
+    n = rows(a);
+    [ua,s] = schur(-(a+eye(n)*tol),'A');
+    k = sum( real(eig(a)) >= 0 );	# count unstable poles 
+
+    #disp("is_stabilizable: unstable poles found:")
+    #k
+    #s
+    #disp("/is_stabilizable: unstable poles found:")
+    
+    if( k > 0 )
+      ua = ua(:,1:k);
+      # now see if span(ua) is contained in span(U)
+      retval = (norm(ua - U*U'*ua) < tol);
+    else
+      retval = 1;			# all poles stable
+    endif
+  endif
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/is_stable.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,73 @@
+# Copyright (C) 1993, 1994, 1995 John W. Eaton
+# 
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+function retval = is_stable (a, tol, disc)
+
+# Usage: retval = is_stable (a {,tol,disc})
+# or     retval = is_stable (sys{,tol})
+#
+# Returns retval = 1 if the matrix a or the system a is stable, or 0 if not.
+#
+# tol is a roundoff paramter, set to 200*eps if omitted.
+# disc != 0: stable if eig(a) in unit circle
+#         0: stable if eig(a) in open LHP (default)
+#
+# See also: size, rows, columns, length, is_matrix, is_scalar, is_vector
+#     is_observable, is_stabilizable, is_detectable, krylov, krylovb
+
+# Written by A. S. Hodel (scotte@eng.auburn.edu) August, 1993.
+# Updated by A. S. Hodel (scotte@eng.auburn.edu) Aubust, 1995 to use krylovb 
+# Updated by John Ingram (ingraje@eng.auburn.edu) July, 1996 for systems
+# SYS_INTERNAL accesses members of system structure
+# $Revision: 1.1.1.1 $
+
+  if( (nargin < 1) | (nargin > 3) )
+    usage("is_stable(a {,tol,disc})");
+  elseif(is_struct(a))
+    # system was passed
+    if(nargin < 3)
+      disc = is_digital(a);
+    elseif(disc != is_digital(a))
+      warning(["is_stable: disc =",num2str(disc),", does not match system"])
+    endif
+    sys = sysupdate(a,"ss");
+    a = sys.a;
+  else
+    if(nargin < 3)
+      disc = 0;
+    endif
+    if(is_square(a) == 0)
+      error("non-square a matrix passed.")
+    endif
+  endif
+
+  if( nargin < 2)
+    tol = 200*eps;
+  elseif( !is_scalar(tol) )
+    error("is_stable: tol must be a scalar!");
+  endif
+ 
+  l = eig(a);
+  if(disc)
+    nbad = sum(abs(l)*(1+tol) > 1);
+  else
+    nbad = sum(real(l)+tol > 0);
+  endif
+  retval = (nbad == 0);   
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/jet707.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,64 @@
+# Copyright (C) 1997 Kai P. Mueller
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function outsys = jet707()
+  # function outsys = jet707()
+  # Creates linearized state space model of a Boeing 707-321 aircraft
+  # at v=80m/s. (M = 0.26, Ga0 = -3 deg, alpha0 = 4 deg, kappa = 50 deg)
+  # System inputs:   (1) thrust   and (2) elevator angle
+  # System outputs:  (1) airspeed and (2) pitch angle
+  # Ref: R. Brockhaus: Flugregelung (Flight Control), Springer, 1994
+  #
+  # see also: ord2
+
+  # Written by Kai P. Mueller September 28, 1997
+  # Updates
+  # $Revision: 1.1.1.1 $
+  # $Log: jet707.m,v $
+  # Revision 1.1.1.1  1998/05/19 20:24:07  jwe
+  #
+  # Revision 1.3  1997/12/01 16:51:50  scotte
+  # updated by Mueller 27 Nov 97
+  #
+# Revision 1.1  1997/11/11  17:33:24  mueller
+# Initial revision
+#
+
+  if (nargin != 0)
+    usage("outsys = jet707()")
+  endif
+  if (nargin > 1)
+    usage("outsys = jet707()")
+  endif
+
+  a = [ -0.46E-01,            0.10681415316, 0.0,   -0.17121680433;
+        -0.1675901504661613, -0.515,         1.0,    0.6420630320636088E-02;
+         0.1543104215347786, -0.547945,     -0.906, -0.1521689385990753E-02;
+         0.0,                 0.0,           1.0,    0.0 ];
+  b = [ 0.1602300107479095,      0.2111848453E-02;
+        0.8196877780963616E-02, -0.3025E-01;
+        0.9173594317692437E-01, -0.75283075;
+        0.0,                     0.0 ];
+  c = [ 1.0,  0.0,  0.0,  0.0;
+        0.0,  0.0,  0.0,  1.0 ];
+  d=zeros(2,2);
+  inam = ["thrust"; "rudder"];
+  onam = ["speed"; "pitch"];
+  snam = ["x1"; "x2"; "x3"; "x4"];
+  outsys = ss2sys(a, b, c, d, 0.0, 4, 0, snam, inam, onam);
+endfunction
--- a/scripts/control/lqe.m	Thu Nov 05 04:24:46 1998 +0000
+++ b/scripts/control/lqe.m	Fri Nov 06 16:16:31 1998 +0000
@@ -1,55 +1,66 @@
-## Copyright (C) 1996, 1997 John W. Eaton
-##
-## 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-1307, USA.
-
-## Usage: [k, p, e] = lqe (A, G, C, SigW, SigV {,Z})
-##
-## Linear quadratic estimator (Kalman filter) design for the
-## continuous time system
-##
-##   dx/dt = A x + B u + G w
-##       y = C x + D u + v
-##
-## where w, v are zero-mean gaussian noise processes with respective
-## intensities SigW = cov (w, w) and SigV = cov (v, v).
-##
-## Z (if specified) is cov(w,v); otherwise cov(w,v) = 0.
-##
-## Observer structure is dz/dt = A z + B u + k( y - C z - D u).
-##
-## Returns:
-##
-##   k = observer gain, (A - K C) is stable
-##   p = solution of algebraic Riccati equation
-##   e = closed loop poles of (A - K C)
-
-## Author: A. S. Hodel <scotte@eng.auburn.edu>
-## Created: August 1993
-## Adapted-By: jwe
+# Copyright (C) 1993, 1994, 1995 John W. Eaton
+# 
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA.
 
 function [k, p, e] = lqe (a, g, c, sigw, sigv, zz)
 
-  if (nargin != 5 && nargin != 6)
+# Usage: [k, p, e] = lqe (A, G, C, SigW, SigV {,Z})
+#
+# Linear quadratic estimator (Kalman filter) design for the 
+# continuous time system
+#
+#   dx/dt = A x + B u + G w
+#       y = C x + D u + v
+#
+# where w, v are zero-mean gaussian noise processes with respective
+# intensities SigW = cov (w, w) and SigV = cov (v, v).
+#
+# Z (if specified) is cov(w,v); otherwise cov(w,v) = 0.
+#
+# Observer structure is dz/dt = A z + B u + k( y - C z - D u).
+#
+# Returns:
+#
+#   k = observer gain, (A - K C) is stable
+#   p = solution of algebraic Riccati equation
+#   e = closed loop poles of (A - K C)
+
+# Written by A. S. Hodel (scotte@eng.auburn.edu) August, 1993.
+# $Revision: 1.14 $
+# $Log: lqe.m,v $
+# Revision 1.14  1998-11-06 16:15:36  jwe
+# *** empty log message ***
+#
+# Revision 1.1.1.1  1998/05/19 20:24:07  jwe
+#
+# Revision 1.3  1997/09/19 21:36:54  scotte
+# *** empty log message ***
+#
+# Revision 1.2  1997/02/28 23:03:45  hodel
+# added parenthesis in if command (just in case)
+# a.s.hodel@eng.auburn.edu
+#
+
+  if ( (nargin != 5) && (nargin != 6))
     error ("lqe: invalid number of arguments");
   endif
 
-  ## The problem is dual to the regulator design, so transform to lqr
-  ## call.
+# The problem is dual to the regulator design, so transform to lqr
+# call.
 
   if (nargin == 5)
     [k, p, e] = lqr (a', c', g*sigw*g', sigv);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/lqg.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,156 @@
+# Copyright (C) 1996, 1997 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [K,Q1,P1,Ee,Er] = lqg(sys,Sigw,Sigv,Q,R,input_list)
+#
+# function [K,Q,P,Ee,Er] = lqg(sys,Sigw,Sigv,Q,R,input_list)
+# design a linear-quadratic-gaussian optimal controller for the system
+#
+#  dx/dt = A x + B u + G w       [w]=N(0,[Sigw 0    ])
+#      y = C x + v               [v]  (    0   Sigv ])
+#
+# or
+# 
+#  x(k+1) = A x(k) + B u(k) + G w(k)       [w]=N(0,[Sigw 0    ])
+#    y(k) = C x(k) + v(k)                  [v]  (    0   Sigv ])
+#
+# inputs:
+#  sys: system data structure
+#  Sigw, Sigv: intensities of independent Gaussian noise processes (as above)
+#  Q, R: state, control weighting respectively.  Control ARE is
+#  input_list: indices of controlled inputs
+#     default: last dim(R) inputs are assumed to be controlled inputs, all
+#              others are assumed to be noise inputs.
+# Outputs:
+#    K: system data structure LQG optimal controller
+#       (Obtain A,B,C matrices with sys2ss, sys2tf, or sys2zp as appropriate)
+#    P: Solution of control (state feedback) algebraic Riccati equation
+#    Q: Solution of estimation algebraic Riccati equation
+#    Ee: estimator poles
+#    Es: controller poles
+#
+# See also: h2syn, lqe, lqr
+
+# Written by A. S. Hodel August 1995; revised for new system format
+# August 1996
+# $Revision: 1.1.1.1 $
+# $Log: lqg.m,v $
+# Revision 1.1.1.1  1998/05/19 20:24:07  jwe
+#
+# Revision 1.2  1997/03/01 00:21:33  hodel
+# fixed some string manipulation problems.
+#
+
+sav_val = implicit_str_to_num_ok;
+implicit_str_to_num_ok = 1;
+
+if ( (nargin < 5) | (nargin > 6))
+  usage("[K,Q1,P1,Ee,Er] = lqg(sys,Sigw, Sigv,Q,R{,input_list})");
+
+elseif(!is_struct(sys) )
+  error("sys must be in system data structure");
+endif
+
+DIG = is_digital(sys);
+[A,B,C,D,tsam,n,nz,stname,inname,outname] = sys2ss(sys);
+nout = rows(outname);
+nin = rows(inname);
+if(nargin == 5)
+  #construct default input_list
+  input_list = (columns(Sigw)+1):nin;
+endif
+
+if( !(n+nz) )
+    error(["lqg: 0 states in system"]);
+
+elseif(nin != columns(Sigw)+ columns(R))
+  error(["lqg: sys has ",num2str(nin)," inputs, dim(Sigw)=", ...
+	num2str(columns(Sigw)),", dim(u)=",num2str(columns(R))])
+
+elseif(nout != columns(Sigv))
+  error(["lqg: sys has ",num2str(nout)," outputs, dim(Sigv)=", ...
+	num2str(columns(Sigv)),")"])
+elseif(length(input_list) != columns(R))
+  error(["lqg: length(input_list)=",num2str(length(input_list)), ...
+	", columns(R)=", num2str(columns(R))]);
+endif
+
+varname = ["Sigw";"Sigv";"Q   ";"R   "];
+for kk=1:rows(varname);
+  stval = dezero(varname(kk,:));
+  cmd = ["chk = is_square(",stval,");"];
+  eval(cmd);
+  if(! chk )
+    error(["lqg: ",stval," is not square"]);
+  endif
+endfor
+
+# permute (if need be)
+if(nargin == 6)
+  all_inputs = sysreorder(nin,input_list);
+  B = B(:,all_inputs);
+  inname = inname(all_inputs,:);
+endif
+
+# put parameters into correct variables
+m1 = columns(Sigw);
+m2 = m1+1;
+G = B(:,1:m1);
+B = B(:,m2:nin);
+
+# now we can just do the design; call dlqr and dlqe, since all matrices
+# are not given in Cholesky factor form (as in h2syn case)
+if(DIG)
+  [Ks P1 Er] = dlqr(A,B,Q,R);
+  [Ke Q1 jnk Ee] = dlqe(A,G,C,Sigw,Sigv);
+else
+  [Ks P1 Er] = lqr(A,B,Q,R);
+  [Ke Q1 Ee] = lqe(A,G,C,Sigw,Sigv);
+endif
+Ac = A - Ke*C - B*Ks;
+Bc = Ke;
+Cc = -Ks;
+Dc = zeros(rows(Cc),columns(Bc));
+
+# fix state names
+for ii=1:rows(stname)
+  newst = [dezero(stname(ii,:)),"\\e"];
+  stname1(ii,1:length(newst)) = newst;
+endfor
+
+# fix controller output names
+inname = inname(m2:nin,:);
+for ii=1:rows(inname)
+  newst = [dezero(inname(ii,:)),"\\K"];
+  outname1(ii,1:length(newst)) = newst;
+endfor
+
+# fix controller input names
+for ii=1:rows(outname)
+  newst = [dezero(outname(ii,:)),"\\K"];
+  inname1(ii,1:length(newst)) = newst;
+endfor
+
+if(DIG)
+  K = ss2sys(Ac,Bc,Cc,Dc,tsam,n,nz,stname1,inname1,outname1,1:rows(Cc));
+else
+  K = ss2sys(Ac,Bc,Cc,Dc,tsam,n,nz,stname,inname1,outname1);
+endif
+
+implicit_str_to_num_ok = sav_val;
+endfunction
--- a/scripts/control/lqr.m	Thu Nov 05 04:24:46 1998 +0000
+++ b/scripts/control/lqr.m	Fri Nov 06 16:16:31 1998 +0000
@@ -1,100 +1,124 @@
-## Copyright (C) 1996, 1997 John W. Eaton
-##
-## 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-1307, USA.
+# Copyright (C) 1993, 1994, 1995 John W. Eaton
+# 
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+function [k, p, e] = lqr (a, b, q, r, s)
 
-## Usage: [k, p, e] = lqr (A, B, Q, R {,Z})
-##
-## Linear quadratic regulator design for the continuous time system
-##
-##   dx/dt = A x + B u
-##
-## to minimize the cost functional
-##
-##  J = int_0^\infty{ x' Q x + u' R u } 			Z omitted
-##
-## or
-##
-##  J = int_0^\infty{ x' Q x + u' R u +2 x' Z u}		Z included
-##
-## Returns:
-##
-##   k = state feedback gain, (A - B K) is stable
-##   p = solution of algebraic Riccati equation
-##   e = closed loop poles of (A - B K)
+# Usage: [k, p, e] = lqr (A, B, Q, R {,S})
+#
+# Linear quadratic regulator design for the continuous time system
+#   dx/dt = A x + B u
+# to minimize the cost functional
+#
+#  J = int_0^\infty{ [x' u'] [Q  S'; S R] [x ; u] dt}
+#
+# inputs:
+#   A, B: coefficient matrices for continuous time system
+#   Q, R, S: cost functional coefficient matrices.
+#      Q: must be nonnegative definite.
+#      R: must be positive definite
+#      S: defaults to 0
+# 
+# if S is omitted, the optimization simplifies to the usual
+#
+#  J = int_0^\infty{ x' Q x + u' R u }
+#
+# Returns:
+#
+#   k = state feedback gain, (A - B K) is stable and minimizes the
+#       cost functional
+#   p = solution of algebraic Riccati equation
+#   e = closed loop poles of (A - B K)
+#
+# reference: Anderson and Moore, OPTIMAL CONTROL: LINEAR QUADRATIC METHODS,
+# Prentice-Hall, 1990, pp. 56-58
 
-## Author: A. S. Hodel <scotte@eng.auburn.edu>
-## Created: August 1993
-## Adapted-By: jwe
+# $Revision: 1.13 $
 
-function [k, p, e] = lqr (a, b, q, r, zz)
+# Written by A. S. Hodel (scotte@eng.auburn.edu) August 1993.
+# $Log: lqr.m,v $
+# Revision 1.13  1998-11-06 16:15:36  jwe
+# *** empty log message ***
+#
+# Revision 1.1.1.1  1998/05/19 20:24:07  jwe
+#
+# Revision 1.4  1997/09/19 21:37:24  scotte
+# added references for feedback matrices
+# ,
+#
+#
+# Revision 1.2  1997/02/28 23:02:14  hodel
+# added parenthesis around if commands (just to be sure)
+# a.s.hodel@eng.auburn.edu
 
-  if (nargin != 4 && nargin != 5)
+  # disp("lqr: entry");
+
+  if ((nargin != 4) && (nargin != 5))
     error ("lqr: invalid number of arguments");
   endif
 
-  ## Check a.
+# Check a.
   if ((n = is_square (a)) == 0)
     error ("lqr: requires 1st parameter(a) to be square");
   endif
 
-  ## Check b.
+# Check b.
   [n1, m] = size (b);
   if (n1 != n)
     error ("lqr: a,b not conformal");
   endif
 
-  ## Check q.
-
-  if ((n1 = is_square (q)) == 0 || n1 != n)
+# Check q.
+  
+  if ( ((n1 = is_square (q)) == 0) || (n1 != n))
     error ("lqr: q must be square and conformal with a");
   endif
 
-  ## Check r.
-  if((m1 = is_square(r)) == 0 || m1 != m)
+# Check r.
+  if ( ((m1 = is_square(r)) == 0) || (m1 != m))
     error ("lqr: r must be square and conformal with column dimension of b");
   endif
 
-  ## Check if n is there.
+# Check if n is there.
   if (nargin == 5)
-    [n1, m1] = size (zz);
-    if (n1 != n || m1 != m)
+    [n1, m1] = size (s);
+    if ( (n1 != n) || (m1 != m))
       error ("lqr: z must be identically dimensioned with b");
     endif
 
-    ## Incorporate cross term into a and q.
-
-    ao = a - (b/r)*zz';
-    qo = q - (zz/r)*zz';
+# Incorporate cross term into a and q.
+    ao = a - (b/r)*s';
+    qo = q - (s/r)*s';
   else
-    zz = zeros (n, m);
+    s = zeros (n, m);
     ao = a;
     qo = q;
   endif
 
-  ## Check that q, (r) are symmetric, positive (semi)definite
+# Check that q, (r) are symmetric, positive (semi)definite
 
   if (is_symmetric (q) && is_symmetric (r) ...
       && all (eig (q) >= 0) && all (eig (r) > 0))
     p = are (ao, (b/r)*b', qo);
-    k = r\(b'*p + zz');
+    k = r\(b'*p + s');
     e = eig (a - b*k);
   else
     error ("lqr: q (r) must be symmetric positive (semi) definite");
   endif
 
+  # disp("lqr: exit");
 endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/lsim.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,114 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [y,x] = lsim(sys,u,t,x0)
+# lsim: Produce output for a linear simulation of a system
+#
+# lsim(sys,u,t,[x0])
+# Produces a plot for the output of the system, sys.
+#
+# U is an array that contains the system's inputs.  Each column in u 
+# corresponds to a different time step.  Each row in u corresponds to a 
+# different input.  T is an array that contains the time index of the 
+# system.  T should be regularly spaced.  If initial conditions are required
+# on the system, the x0 vector should be added to the argument list.
+#
+# When the lsim function is invoked with output parameters:
+# [y,x] = lsim(sys,u,t,[x0])
+# a plot is not displayed, however, the data is returned in y = system output
+# and x = system states.
+
+# Written by David Clem, A. S. Hodel July 1995
+# modified by John Ingram for system format August 1996
+# $Revision: 1.1.1.1 $
+# $Log: lsim.m,v $
+# Revision 1.1.1.1  1998/05/19 20:24:07  jwe
+#
+# Revision 1.3  1997/12/01 16:51:50  scotte
+# updated by Mueller 27 Nov 97
+#
+# Revision 1.2  1997/11/24  16:13:39  mueller
+# old style c2d call fixed
+#
+
+  if((nargin < 3)||(nargin > 4))
+    usage("[y,x] = lsim(sys,u,t[,x0])");
+  endif
+
+  if(!is_struct(sys))
+    error("sys must be in system data structure");
+  endif
+
+  sys = sysupdate(sys,"ss");
+
+  nout = rows(sys.c);
+  nin = columns(sys.b);
+  ncstates = sys.n;
+  ndstates = sys.nz;
+  
+  a = sys.a;
+  b = sys.b;
+  c = sys.c;
+  d = sys.d;
+  
+  if (nargin == 3)
+    x0 = zeros(columns(a),1);
+  endif
+
+  if(rows(u) ~= length(t))
+    error("lsim: There should be an input value (row) for each time instant");
+  endif
+  if(columns(u) ~= columns(d))
+    error("lsim: U and d should have the same number of inputs");
+  endif
+  if(columns(x0) > 1)
+    error("lsim: Initial condition vector should have only one column");
+  endif
+  if(rows(x0) > rows(a))
+    error("lsim: Initial condition vector is too large");
+  endif
+
+  Ts = 0;
+  t(2)-t(1);
+  u=u';
+  n = max(size(t));
+  for ii = 1:(n-1)
+
+    # check if step size changed
+    if (t(ii+1) - t(ii) != Ts)
+      Ts = t(ii+1) - t(ii);
+      # [F,G] = c2d(a,b,Ts);
+      dsys = c2d(sys, Ts);
+      F = dsys.a;
+      G = dsys.b;
+    endif
+
+    x(:,ii) = x0;
+    x0 = F*x0 + G*u(:,ii);
+  endfor
+
+  # pick up last point
+  x(:,n) = x0;
+
+  y = c*x + d*u;
+  if(nargout == 0)
+   plot(t,y);
+   y=[];
+   x=[];
+  endif
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/ltifr.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,85 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function out = ltifr(a,b,w)
+  #ltifr:  Linear time invarient frequency response of SISO systems
+  # out = ltifr(A,B,w)
+  # user enters the A and B matrices
+  #
+  # out = ltifr(sys,w)
+  # user enters the system, SYS
+  #
+  # this function takes the system matrices, A and B and
+  # returns:               -1
+  #          G(s) = (jw I-A) B
+  #
+  # for complex frequencies s = jw. 
+
+  # R. B. Tenison, D. Clem, A. S. Hodel, July 1995
+  # updated by John Ingram August 1996 for system format
+  # $Revision: 1.1.1.1 $
+  
+  if ((nargin < 2) || (nargin > 3))
+    error("incorrect number of input arguments");
+  endif
+
+  if (nargin == 2)
+    sys = a;
+    w = b;
+
+    if (!is_vector(w))
+      error("w must be a vector");
+    endif
+    
+    sys = sysupdate(sys,"ss");
+
+    if(columns(sys.b) != 1)
+      error("sys is not an SISO system");
+    endif
+
+    a = sys.a;
+    b = sys.b;        
+
+  else  
+
+    if (columns(a) != rows(b)),
+      error("ltifr:  A, B not compatibly dimensioned");
+    endif
+
+    if(columns(b) != 1)
+      error("ltifr: 2nd argument must be a single column vector");
+    endif
+  
+    if (!is_square(a))
+      error("ltifr:  A must be square.")
+    endif
+
+  endif
+
+  if (!is_vector(w))
+    error("w must be a vector");
+  endif
+
+  ey = eye(size(a));
+  lw = length(w);
+  out = ones(columns(a),lw);
+
+  for ii=1:lw,
+    out(:,ii) = (w(ii)*ey-a)\b;
+  endfor
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/mb.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,40 @@
+# $Revision: 1.1 $
+
+Ap = [0 1;1960 0];
+Bp = [0;-6261];
+Cp = [1 0];
+Dp = 0;
+
+Gp = ss2sys(Ap,Bp,Cp,Dp,0,2,0,[],"delta_i","delta_y");
+Gp = syschnames(Gp,"st",1,"delta_x1");
+Gp = syschnames(Gp,"st",2,"delta_x2");
+
+Ak = [-20 1;-22160 -200];
+Bk = [-20;-2160];
+Ck = [-3.5074 -0.0319];
+Dk = 0;
+
+Gk = ss2sys(Ak,Bk,Ck,Dk,0,2,0,[],"y","i");
+Gk = syschnames(Gk,"st",1,"x1");
+Gk = syschnames(Gk,"st",2,"x2");
+
+Gc = sysgroup(Gp,Gk);
+
+Gc = sysdup(Gc,[],[1 2]);
+# Gc = sysscale(Gc,[],diag([1,1,1,1]));
+
+Gc = sysconnect(Gc,[1 2],[4 3]);
+Gc = sysprune(Gc,1,[1 2]);
+
+disp("after pruning, closed loop system is")
+sysout(Gc)
+
+# Gc = sysdup(Gc,[],2);
+# Gc = sysconnect(Gc,1,3);
+# Gc = sysprune(Gc,1,1);
+
+is_stable(Gc)
+eig(Gc.a)
+
+Acl = [Gp.a, -Gp.b*Gk.c; Gk.b*Gp.c, Gk.a]
+eig(Acl)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/minfo.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,85 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [systype, nout, nin, ncstates, ndstates] = minfo(inmat)
+  #  function [systype, nout, nin, ncstates, ndstates] = minfo(inmat)
+  #
+  # MINFO:  Determines the type of system matrix.  INMAT can be
+  #         a varying(*), system, constant, and empty matrix.
+  #
+  #    Returns:
+  #      systype can be one of:
+  #            varying, system, constant, and empty
+  #      nout is the number of outputs of the system
+  #      nin is the number of inputs of the system
+  #      ncstates is the number of continuous states of the system
+  #	 ndstates is the number of discrete states of the system
+
+  # Written by R. Bruce Tenison July 29, 1994
+  # Modified by David Clem November 13, 1994
+  # Modified by A. S. Hodel July 1995
+  # $Revision: 1.1.1.1 $
+
+  warning("minfo: obsolete.  Use sys2ss, sys2tf, or sys2zp.");
+    
+  if (nargin ~= 1 )
+    disp('MINFO: Wrong number of arguments')
+    systype = nout = nin = ncstates = ndstates = [];
+  endif
+  
+  [rr,cc] = size(inmat);
+  
+  # Check for empty matrix first!
+  if (isempty(inmat))
+    systype = "empty";
+    nout = nin = ncstates = ndstates = 0;
+    return
+  
+  # Check for Constant matrix
+
+  elseif (rr == 1 || cc == 1)
+    systype = "constant";
+    nout = nin = ncstates = ndstates = 1;
+    return
+  
+  # Check for system type matrix
+  elseif (inmat(rr,cc) == -Inf)
+    systype = "system";
+    ncstates = inmat(1,cc);
+    ndstates = inmat(rr,1);
+    nstates = ncstates + ndstates;
+    nout = rr - nstates - 1;
+    nin = cc - nstates - 1;
+  
+  # Check for Varying type matrix
+  elseif (inmat(rr,cc) == Inf)
+    systype = "varying";
+    npoints = inmat(rr,cc-1);
+    nin = cc - 1;
+    nout = rr / npoints;
+    nstates = 0;
+
+    # Must be a standard matrix
+  else
+    systype = "constant";
+    nin = cc;
+    nout = rr;
+    ncstates = 0;
+    ndstates = 0;
+  endif
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/moddemo.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,201 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function moddemo()
+# Octave Controls toolbox demo: Model Manipulations demo
+# Written by David Clem August 15, 1994
+
+# $Revision: 1.1 $
+# a s hodel: updated to reflect updated output order in ss2zp
+
+  while (1)
+    clc
+    disp('Octave Model Manipulations Demo')
+    disp('=======================================')
+    disp('  1)  Perform continuous to discrete time conversion (c2d)')
+    disp('  2)  Convert from state space to zero / pole form (ss2zp)')
+    disp('      Convert from zero / pole to state space form (zp2ss)')
+    disp('  3)  Convert from state space to transfer function form (ss2tf)')
+    disp('      Convert from transfer function to state space form (tf2ss)')
+    disp('  4)  Convert from transfer function to zero / pole form (tf2zp)')
+    disp('      Convert from zero / pole to transfer function form (zp2tf)')
+    disp('  5)  Return to main demo menu')
+    disp(' ')
+    k=6;
+    while(k > 5 || k < 1)
+      k = input('Please enter a number:');
+    endwhile
+    if (k == 1)
+      clc
+      disp('Perform continuous to discrete time conversion (c2d)\n')
+      disp('Example #1, Consider the following continuous time state space system:\n')
+      a=[0 1;-25 -4]
+      b=[0;1]
+      c=[1 1]
+      d=1
+      prompt
+      disp('\nTo convert this to a discrete time system (using a zero order hold),')
+      disp('use the following commands:\n')
+      cmd="sys=ss2sys(a,b,c,d);";
+      run_cmd
+      cmd="dsys = c2d(sys,0.2);";
+      run_cmd
+      cmd="sysout(dsys);";
+      run_cmd
+      disp('Function check\n')
+      disp('Check the poles of sys vs dsys:\n')
+      cmd="[da,db]=sys2ss(dsys);";
+      run_cmd
+      cmd="lam = eig(a);";
+      run_cmd
+      disp('Discretize the continuous time eigenvalues using the matrix exponential:\n')
+      disp('lambc = exp(lam*0.2)\n')
+      lambc = exp(lam*0.2)
+      disp('Check the eigenvalues of da\n')
+      lambd = eig(da)
+      disp('Calculate the difference between lambd and lambc:\n')
+      cmd = 'error = sort(lambd)-sort(lambc)\n';
+      run_cmd
+      disp("The error is on the order of roundoff noise, so we're o.k.")
+      prompt
+      clc
+    elseif (k == 2)
+      clc
+      disp('Convert from state space to zero / pole form (ss2zp)\n')
+      disp('Example #1, Consider the following state space system:\n')
+      a=[0 3 1;-2 -4 5;5 8 2]
+      b=[0;5;2.5]
+      c=[6 -1.9 2]
+      d=[-20]
+      prompt
+      disp(' ')
+      disp('\nTo find the poles and zeros of this sytstem, use the following command:\n')
+      disp('\n[zer, pol] = ss2zp(a, b, c, d)\n')
+      prompt
+      disp('Results:\n')
+      [zer, pol] = ss2zp(a, b, c, d)
+      disp('Variable Description:\n')
+      disp('zer, pol => zeros and poles of the state space system')
+      disp('a, b, c, d => state space system\n')
+      prompt
+      clc
+      disp('Convert from zero / pole to state space form (zp2ss)\n')
+      disp('Example #1, Consider the following set of zeros and poles:\n')
+      zer
+      pol
+      prompt
+      disp('\nTo find an equivalent state space representation for this set of poles')
+      disp('and zeros, use the following commands:\n')
+      k=1
+      disp('\n[na, nb, nc, nd] = zp2ss(zer, pol, k)\n')
+      prompt
+      disp('Results:\n')
+      [na, nb, nc, nd] = zp2ss(zer, pol, k)
+      disp('Variable Description:\n')
+      disp('na, nb, nc, nd => state space system equivalent to zero / pole input')
+      disp('zer, pol => zeros and poles of desired state space system')
+      disp('k => gain associated with the zeros\n')
+      prompt
+      disp('Function check\n')
+      disp('Are the eigenvalues of the origonal state space system the same as the')
+      disp('eigenvalues of the newly constructed state space system ?\n')
+      disp('Find the difference between the two sets of eigenvalues')
+      disp('error = sort(eig(a)) - sort(eig(na))\n')
+      error = sort(eig(a)) - sort(eig(na))
+      prompt
+      clc
+    elseif (k == 3)
+      clc
+      disp('Convert from state space to transfer function (ss2tf)\n')
+      disp('Example #1, Consider the following state space system:\n')
+      a=[0 1;-2 -3]
+      b=[1;1]
+      c=[1 9]
+      d=[1]
+      prompt
+      disp('\nTo find an equivalent transfer function for this system, use')
+      disp('the following command:\n')
+      disp('[num, den] = ss2tf(a, b, c, d)\n')
+      prompt
+      disp('Results:\n')
+      [num,den] = ss2tf(a, b, c, d)
+      disp('Variable Description:\n')
+      disp('num, den => numerator and denominator of transfer function that is')
+      disp('            equivalent to the state space system')
+      disp('a, b, c, d => state space system\n')
+      prompt
+      clc
+      disp('Convert from transfer function to state space form (tf2ss)\n')
+      disp('Example #1, Consider the following transfer function:\n')
+      num
+      den
+      prompt
+      disp('\nTo find an equivalent state space representation for this system, use')
+      disp('the following command:\n')
+      disp('[a, b, c, d] = tf2ss(num, den)\n')
+      prompt
+      disp('Results:\n')
+      [a, b, c, d] = tf2ss(num, den)
+      disp('Variable Description:\n')
+      disp('a, b, c, d => state space system equivalent to transfer function input')
+      disp('num, den => numerator and denominator of transfer function that is equivalent')
+      disp('            to the state space system\n')
+      prompt
+      clc
+    elseif (k == 4)
+      clc
+      disp('Convert from transfer function to zero / pole form (tf2zp)\n')
+      disp('Example #1, Consider the following transfer function:\n')
+      num=[1 2 3 4 5 ]
+      den=[1 2 3 4 5 6 7]
+      prompt
+      disp('\nTo find the zeros and poles of this system, use the following command:\n')
+      disp('[zer,pol] = tf2zp(num,den)\n')
+      prompt
+      disp('Results:\n')
+      [zer,pol] = tf2zp(num,den)
+      disp('Variable Description:\n')
+      disp('zer,pol => zeros and poles of the transfer function')
+      disp('num, den => numerator and denominator of transfer function\n')
+      prompt
+      clc
+      disp('Convert from zero / pole to transfer function (zp2tf)\n')
+      disp('Example #1, Consider the following set of zeros and poles:\n')
+      zer
+      pol 
+      prompt
+      disp('\nTo find an equivalent transfer function representation for this set')
+      disp('of poles and zeros, use the following commands:\n')
+      k=1
+      disp('\n[num, den] = zp2tf(zer, pol, k)\n')
+      prompt
+      disp('Results:\n')
+      [num, den] = zp2tf(zer, pol, k)
+      disp('Variable Description:\n')
+      disp('[num, den] => transfer function representation of desired set of zeros')
+      disp('              and poles') 
+      disp('a, b, c, d => state space system')
+      disp('zer, pol => zeros and poles of desired state space system')
+      disp('k => gain associated with the zeros\n')
+      prompt
+      clc
+    elseif (k == 5)
+      return
+    endif
+  endwhile  
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/nichols.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,114 @@
+# Copyright (C) 1998 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [mag,phase,w] = nichols(sys,w,outputs,inputs)
+# [mag,phase,w] = nichols(sys[,w,outputs,inputs])
+# Produce Nichols plot of a system
+#
+# Compute the frequency response of a system.
+# inputs:
+#   sys: system data structure (must be either purely continuous or discrete;
+#	 see is_digital)
+#   w: frequency values for evaluation.
+#      if sys is continuous, then nichols evaluates G(jw)
+#      if sys is discrete, then nichols evaluates G(exp(jwT)), where T=sys.tsam
+#         (the system sampling time)
+#      default: the default frequency range is selected as follows: (These
+#        steps are NOT performed if w is specified)
+#          (1) via routine bodquist, isolate all poles and zeros away from
+#              w=0 (jw=0 or exp(jwT)=1) and select the frequency
+#             range based on the breakpoint locations of the frequencies.
+#          (2) if sys is discrete time, the frequency range is limited
+#              to jwT in [0,2p*pi]
+#          (3) A "smoothing" routine is used to ensure that the plot phase does
+#              not change excessively from point to point and that singular
+#              points (e.g., crossovers from +/- 180) are accurately shown.
+#   outputs, inputs: the indices of the output(s) and input(s) to be used in
+#     the frequency response; see sysprune.
+# outputs:
+#    mag, phase: the magnitude and phase of the frequency response
+#       G(jw) or G(exp(jwT)) at the selected frequency values.
+#    w: the vector of frequency values used
+# If no output arguments are given, nichols plots the results to the screen.
+# Descriptive labels are automatically placed.  See xlabel, ylable, title,
+# and replot.
+#
+# Note: if the requested plot is for an MIMO system, mag is set to
+# ||G(jw)|| or ||G(exp(jwT))|| and phase information is not computed.
+
+# $Log$
+
+  # check number of input arguments given
+  if (nargin < 1 | nargin > 4)
+    usage("[mag,phase,w] = nichols(sys[,w,outputs,inputs])");
+  endif
+  if(nargin < 2)
+    w = [];
+  endif
+  if(nargin < 3)
+    outputs = [];
+  endif
+  if(nargin < 4)
+    inputs = [];
+  endif
+
+  [f, w] = bodquist(sys,w,outputs,inputs,"nichols");
+
+  [stname,inname,outname] = sysgetsignals(sys);
+  systsam = sysgettsam(sys);
+
+  # Get the magnitude and phase of f.
+  mag = abs(f);
+  phase = arg(f)*180.0/pi;
+
+  if (nargout < 1),
+    # Plot the information
+    if(gnuplot_has_multiplot)
+      oneplot();
+    endif
+    gset autoscale;
+    if(gnuplot_has_multiplot)
+      gset nokey;
+    endif
+    clearplot();
+    grid("on");
+    gset data style lines;
+    if(is_digital(sys))
+      tistr = "(exp(jwT)) ";
+    else
+      tistr = "(jw)";
+    endif
+    xlabel("Phase (deg)");
+    ylabel("Gain in dB");
+    if(is_siso(sys))
+      title(["Nichols plot of |[Y/U]",tistr,"|, u=", inname, ...
+	", y=",outname]);
+    else
+      title([ "||Y(", tistr, ")/U(", tistr, ")||"]);
+      disp("MIMO plot from")
+      outlist(inname,"	");
+      disp("to")
+      outlist(outname,"	");
+    endif
+    md = 20*log10(mag);
+    axvec = axis2dlim([vec(phase),vec(md)]);
+    axis(axvec);
+    plot(phase,md);
+    mag = phase = w = [];
+  endif
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/nyquist.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,195 @@
+# Copyright (C) 1996,1998 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [realp,imagp,w] = nyquist(sys,w,outputs,inputs,atol)
+# [realp,imagp,w] = nyquist(sys[,w,outputs,inputs,atol])
+# Produce Nyquist plots of a system
+#
+# Compute the frequency response of a system.
+# inputs: (pass as empty to get default values
+#   sys: system data structure (must be either purely continuous or discrete;
+#        see is_digital)
+#   w: frequency values for evaluation.
+#      if sys is continuous, then bode evaluates G(jw)
+#      if sys is discrete, then bode evaluates G(exp(jwT)), where 
+#         T=sysgettsam(sys) (the system sampling time)
+#      default: the default frequency range is selected as follows: (These
+#        steps are NOT performed if w is specified)
+#          (1) via routine bodquist, isolate all poles and zeros away from 
+#              w=0 (jw=0 or exp(jwT)=1) and select the frequency
+#             range based on the breakpoint locations of the frequencies.
+#          (2) if sys is discrete time, the frequency range is limited
+#              to jwT in [0,2p*pi]
+#          (3) A "smoothing" routine is used to ensure that the plot phase does
+#              not change excessively from point to point and that singular
+#              points (e.g., crossovers from +/- 180) are accurately shown.
+#   outputs, inputs: the indices of the output(s) and input(s) to be used in
+#     the frequency response; see sysprune.
+#   atol: for interactive nyquist plots: atol is a change-in-angle tolerance 
+#     (in degrees) for the of asymptotes (default = 0; 1e-2 is a good choice).
+#     Consecutive points along the asymptotes whose angle is within atol of
+#     the angle between the largest two points are omitted for "zooming in"
+#
+# outputs:
+#    realp, imagp: the real and imaginary parts of the frequency response
+#       G(jw) or G(exp(jwT)) at the selected frequency values.
+#    w: the vector of frequency values used
+#
+# If no output arguments are given, nyquist plots the results to the screen.
+# If atol != 0 and asymptotes are detected then the user is asked 
+#    interactively if they wish to zoom in (remove asymptotes)
+# Descriptive labels are automatically placed.  See xlabel, ylable, title,
+# and replot.
+#
+# Note: if the requested plot is for an MIMO system, a warning message is
+# presented; the returned information is of the magnitude 
+# ||G(jw)|| or ||G(exp(jwT))|| only; phase information is not computed.
+   
+  # By R. Bruce Tenison, July 13, 1994
+  # A. S. Hodel July 1995 (adaptive frequency spacing, 
+  #     remove acura parameter, etc.)
+  # Revised by John Ingram July 1996 for system format
+  #
+  # Revision 1.6  1998/02/09 13:03:37  scotte
+  # fixed oneplot/gset nokey to function only if gnuplot_has_multiplot
+  #
+# Revision 1.2  1997/11/24  17:27:58  mueller
+# call to oneplot() and gset nokey added
+#
+# Revision 1.1  1997/11/11  17:33:41  mueller
+# Initial revision
+#
+
+  # Both bode and nyquist share the same introduction, so the common parts are 
+  # in a file called bodquist.m.  It contains the part that finds the 
+  # number of arguments, determines whether or not the system is SISO, and 
+  # computes the frequency response.  Only the way the response is plotted is
+  # different between the two functions.
+
+  save_val = implicit_str_to_num_ok;	# save for later
+  implicit_str_to_num_ok = 1;
+
+  # check number of input arguments given
+  if (nargin < 1 | nargin > 5)
+    usage("[realp,imagp,w] = nyquist(sys[,w,outputs,inputs,atol])");
+  endif
+  if(nargin < 2)
+    w = [];
+  endif
+  if(nargin < 3)
+    outputs = [];
+  endif
+  if(nargin < 4)
+    inputs = [];
+  endif
+  if(nargin < 5)
+    atol = 0;
+  elseif(!(is_sample(atol) | atol == 0))
+    error("atol must be a nonnegative scalar.")
+  endif
+
+  # signal to bodquist who's calling
+   
+  [f,w] = bodquist(sys,w,outputs,inputs,"nyquist");
+
+  # Get the real and imaginary part of f.
+  realp = real(f);
+  imagp = imag(f);
+
+  # No output arguments, then display plot, otherwise return data.
+  if (nargout == 0)
+    dnplot = 0;
+    while(!dnplot)
+      if(gnuplot_has_multiplot)
+        oneplot();
+        gset key;
+      endif
+      clearplot();
+      grid ("on");
+      gset data style lines;
+  
+      if(is_digital(sys))
+        tstr = " G(e^{jw}) ";
+      else
+        tstr = " G(jw) ";
+      endif
+      xlabel(["Re(",tstr,")"]);
+      ylabel(["Im(",tstr,")"]);
+  
+      [stn, inn, outn] = sysgetsignals(sys);
+      if(is_siso(sys))
+        title(sprintf("Nyquist plot from %s to %s, w (rad/s) in [%e, %e]", ...
+	  inn, outn, w(1), w(length(w))) )
+      endif
+  
+      gset nologscale xy;
+
+      axis(axis2dlim([[vec(realp),vec(imagp)];[vec(realp),-vec(imagp)]]));
+      plot(realp,imagp,"- ;+w;",realp,-imagp,"-@ ;-w;");
+
+      # check for interactive plots
+      dnplot = 1; # assume done; will change later if atol is satisfied
+      if(atol > 0 & length(f) > 2)
+
+        # check for asymptotes
+        fmax = max(abs(f));
+        fi = max(find(abs(f) == fmax));
+        
+        # compute angles from point to point
+        df = diff(f);
+        th = atan2(real(df),imag(df))*180/pi;
+
+        # get angle at fmax
+        if(fi == length(f)) fi = fi-1; endif
+        thm = th(fi);
+    
+        # now locate consecutive angles within atol of thm
+        ith_same = find(abs(th - thm) < atol);
+        ichk = union(fi,find(diff(ith_same) == 1));
+
+        #locate max, min consecutive indices in ichk
+        loval = max(complement(ichk,1:fi));
+        if(isempty(loval)) loval = fi;
+        else               loval = loval + 1;   endif
+
+        hival = min(complement(ichk,fi:length(th)));
+        if(isempty(hival))  hival = fi+1;      endif
+
+        keep_idx = complement(loval:hival,1:length(w));
+
+        if(length(keep_idx))
+          resp = input("Remove asymptotes and zoom in (y or n): ",1);
+          if(resp(1) == "y")
+            dnplot = 0;                 # plot again
+            w = w(keep_idx);
+            f = f(keep_idx);
+            realp = real(f);
+            imagp = imag(f);
+          endif
+        endif
+
+     endif
+    endwhile
+    w = [];
+    realp=[];
+    imagp=[];
+  endif
+
+  implicit_str_to_num_ok = save_val;	# restore value
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/obsv.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,75 @@
+# Copyright (C) 1997 Kai P. Mueller
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+
+function Qb = obsv(sys, c)
+  # ------------------------------------------------------
+  # Qb = obsv(sys [, c])
+  # Build observability matrix
+  #
+  #          +          +
+  #          | C        |
+  #          | CA       |
+  #     Qb = | CA^2     |
+  #          | ...      |
+  #          | CA^(n-1) |
+  #          +          +
+  #
+  # of a system data structure or the pair (A, C).
+  #
+  # Note: obsv() forms the observability matrix.
+  #       The numerical properties of is_observable()
+  #       are much better for observability tests.
+  # See also:  ctrb, is_observable, is_controllable
+  # ------------------------------------------------------
+
+  # Written by Kai P. Mueller November 4, 1997
+  # modified by
+  # $Revision: 1.1.1.1 $
+  # $Log: obsv.m,v $
+  # Revision 1.1.1.1  1998/05/19 20:24:07  jwe
+  #
+  # Revision 1.2  1997/12/01 16:51:50  scotte
+  # updated by Mueller 27 Nov 97
+  #
+# Revision 1.1  1997/11/25  11:17:05  mueller
+# Initial revision
+#
+
+  if (nargin == 2)
+    a = sys;
+  elseif (nargin == 1 && is_struct(sys))
+    sysupdate(sys,"ss");
+    a = sys.a;
+    c = sys.c;
+  else
+    usage("obsv(sys [, c])")
+  endif
+
+  if (!is_abcd(a,c'))
+    Qb = [];
+  else
+    # no need to check dimensions, we trust is_abcd().
+    [na, ma] = size(a);
+    [nc, mc] = size(c);
+    Qb = zeros(na*nc, ma);
+    for i = 1:na
+      Qb((i-1)*nc+1:i*nc, :) = c;
+      c = c * a;
+    endfor
+  endif
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/ord2.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,64 @@
+# Copyright (C) 1997 Kai P. Mueller
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function outsys = ord2(nfreq, damp, gain)
+  # function outsys = ord2(nfreq, damp[, gain])
+  # Creates a continuous 2nd order system with parameters:
+  #
+  #      nfreq:   natural frequency [Hz]. (not in rad/s)
+  #      damp:    damping coefficient
+  #      gain:    dc-gain
+  #               This is steady state value only for damp > 0.
+  #               gain is assumed to be 1.0 if ommitted.
+  #
+  #      The system has representation with w = 2 * pi * nfreq:
+  #
+  #          /                                        \
+  #          | / -2w*damp -w \  / w \                 |
+  #      G = | |             |, |   |, [ 0  gain ], 0 |
+  #          | \   w       0 /  \ 0 /                 |
+  #          \                                        /
+  #
+  # See also: jet707 (MIMO example, Boeing 707-321 aircraft model)
+
+  # Written by Kai P. Mueller September 28, 1997
+  # Updates
+  # $Revision: 1.1.1.1 $
+  # $Log: ord2.m,v $
+  # Revision 1.1.1.1  1998/05/19 20:24:07  jwe
+  #
+  # Revision 1.3  1997/12/01 16:51:50  scotte
+  # updated by Mueller 27 Nov 97
+  #
+# Revision 1.1  1997/11/11  17:34:06  mueller
+# Initial revision
+#
+
+  if(nargin != 2 & nargin != 3)
+    usage("outsys = ord2(nfreq, damp[, gain])")
+  endif
+  if (nargout > 1)
+    usage("outsys = ord2(nfreq, damp[, gain])")
+  endif
+  if (nargin == 2)
+    gain = 1.0;
+  endif
+
+  w = 2.0 * pi * nfreq;
+  outsys = ss2sys([-2.0*w*damp, -w; w, 0], [w; 0], [0, gain]);
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/outlist.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,77 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function outlist(lmat,tabchar,yd,ilist)
+# function outlist(lmat[,tabchar,yd,ilist])
+#
+# internal use only; minimal argument checking performed
+#
+# print an enumerated list of strings
+# inputs:
+#	lmat: matrix of strings (one per row)
+#	tabchar: tab character (default: none)
+#       yd: indices of strings to append with the string "(discrete)"
+#           (used by sysout; minimal checking of this argument)
+#	   yd = [] => all continuous
+#       ilist: index numbers to print with names
+#	  default: 1:rows(lmat)
+# outputs:
+#   prints the list to the screen, numbering each string in order.
+
+# A. S. Hodel Dec. 1995
+# $Revision: 1.1.1.1 $
+
+save_val = implicit_str_to_num_ok;	# save for later
+implicit_str_to_num_ok = 1;
+
+#save for restore later
+save_empty = empty_list_elements_ok;
+empty_list_elements_ok = 1;
+
+if( (nargin < 1) || (nargin > 4) )
+  usage("outlist(x[,tabchar,yd,ilist])");
+endif
+
+[m,n] = size(lmat);
+if(nargin < 4)
+  ilist = 1:m;
+endif
+if(nargin ==1)
+  empty_list_elements_ok = 1;
+  tabchar = "";
+endif
+
+if(nargin < 3)
+  yd = zeros(1,m);
+elseif(isempty(yd))
+  yd = zeros(1,m);
+endif
+
+if((m >= 1) && (isstr(lmat)))
+  for ii=1:m
+    str = dezero([lmat(ii,:),setstr((yd(ii)*" (discrete)"))]);
+    #disp(["length(str)=",num2str(length(str))])
+    disp([tabchar,num2str(ilist(ii)),": ",str])
+  endfor
+else
+  disp([tabchar,"None"])
+endif
+
+empty_list_elements_ok = save_empty;
+implicit_str_to_num_ok = save_val;	# restore value
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/packedform.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,98 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+# $Revision#
+save_var = page_screen_output;
+page_screen_output = 1;
+disp("Description of system data structure:")
+disp("A linear system is stored in a structure, and may be represented in")
+disp("ss (state space), tf (transfer function),  and/or zp (zero-pole-gain)")
+disp("form.")
+disp(" ")
+disp("variables in all representations:")
+disp("inname: string or a matrix of strings containing name(s) of system ")
+disp("        inputs");
+disp("n: number of continuous states")
+disp("nz: number of discrete states")
+disp("outname: string or a matrix of strings containing name(s) of system ")
+disp("        outputs");
+disp(" ")
+disp("variables in all representations:(cont'd)")
+disp("sys: system status vector.  This vector indicates both what")
+disp("     representation was used to initialize the system data structure")
+disp("     (called the primary system type) and which other representations")
+disp("     are currently up-to-date with the primary system type.")
+disp("     sys(0): primary system type")
+disp("           =0 for tf form")
+disp("           =1 for zp form")
+disp("           =2 for ss form")
+disp("     sys(1:3): indicate whether tf, zp, or ss, respectively, are")
+disp("          \"up to date\" (whether it is safe to use the variables")
+disp("          associated with these representations)")
+disp("     sys(1): = 1 if tf variables are up to date")
+disp("             = 0 else");
+disp("     sys(2): = 1 if zp variables are up to date")
+disp("             = 0 else");
+disp("     sys(3): = 1 if ss variables are up to date")
+disp("             = 0 else");
+disp("You can update alternative representations internally with the")
+disp("sysupdate command:")
+disp(" ")
+help sysupdate
+disp("===============================")
+disp("More variables common to all representations in system data structures:");
+disp("tsam: discrete time sampling interval ")
+disp("      =0 if system is purely continuous");
+disp("      >0 if system has discrete-time states or outputs");
+disp("yd: vector indicating which outputs are discrete time (i.e.,")
+disp("    produced by D/A converters) and which are continuous time.")
+disp("    yd(ii) = 0 if output ii is continuous, = 1 if discrete.")
+disp(" ")
+disp("===============================")
+disp("variables in tf representations (SISO only):")
+disp("num: vector of numerator coefficients")
+disp("den: vector of denominator coefficients")
+disp(" ")
+disp("===============================")
+disp("variables in zp representations (SISO only):")
+disp("zer: vector of system zeros")
+disp("pol: vector of system poles")
+disp("k: system leading coefficient")
+disp(" ")
+disp("===============================")
+disp("variables in ss representations:")
+disp("a,b,c,d: usual state-space matrices.  If a system has both")
+disp("        continuous and discrete states, they are sorted so that")
+disp("        continuous states come first, then discrete states")
+disp(" ")
+disp("WARNING: some functions (e.g., bode) will not accept systems")
+disp("with both discrete and continuous states/outputs")
+disp("stname: string or matrix of strings containing name(s) of system")
+disp("        states");
+disp("===============================")
+disp("Object oriented programming:")
+disp("It is recommended that users do not directly access the internal")
+disp("variables themselves, but use the interface functions")
+disp("        ss2sys        sys2ss      syschnames")
+disp("        tf2sys        sys2tf")
+disp("        zp2sys        sys2zp")
+disp("to create/access internal variables.  For developmental purposes,")
+disp("routines that directly access the internal structure of a system data")
+disp("structure either have the string \"sys\" in their name or else")
+disp("have the word SYS_INTERNAL in their revision comment block");
+page_screen_output = save_var;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/packsys.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,71 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function Asys = packsys(a,b,c,d,dflg)
+  # O B S O L E T E: use ss2sys instead.
+  # function Asys = packsys(a,b,c[,d,dflg])
+  #
+  # dflg: 0 for continuous time system, 1 for discrete-time system.
+  # 
+  # defaults:
+  #   D: 0 matrix of appropriate dimension.
+  #   dflg: 0 (continuous time)
+  #
+  # Note: discrete-state sampling time is not included!
+  #
+  
+  # Written by R. Bruce Tenison  July 29, 1994
+  # Modified by David Clem November 13, 1994
+  # Modified by A. S. Hodel April 1995
+  # $Revision: 1.2 $
+
+  warning("packsys is obsolete!  Use ss2sys instead.");
+  
+  if (nargin < 3 || nargin > 5)
+    disp("packsys: Invalid number of arguments")
+  endif
+
+  # check dflg
+  if(nargin == 5)
+    if( !is_scalar(dflg))
+      [m,n] = size(dflg);
+      error(["packsys: dflg (",num2str(m),",",num2str(n), ...
+	") must be a scalar."]);
+    elseif( (dflg != 0) && (dflg != 1))
+      error(["packsys: dflg=",num2str(dflg),"must be 0 or 1"]);
+    endif
+  else
+    #default condition
+    dflg = 0;
+  endif
+
+  if (nargin == 3)
+    # No D matrix.  Form a zero one!
+    [brows,bcols] = size(b);
+    [crows,ccols] = size(c);
+    d = zeros(crows,bcols);
+  endif
+
+  [n,m,p] = abcddim(a,b,c,d);
+  if (n == -1 || m == -1 || p == -1)
+    error("packsys: incompatible dimensions")
+  endif
+  
+  Asys = ss2sys(a,b,c,d,dflg);
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/parallel.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,62 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function sysp = parallel(Asys,Bsys)
+# function sysp = parallel(Asys,Bsys)
+# Forms the parallel connection of two systems.
+#
+#              ____________________
+#              |      ________    |
+#     u  ----->|----> | Asys |--->|----> y1
+#         |    |      --------    |
+#         |    |      ________    |
+#         |--->|----> | Bsys |--->|----> y2
+#              |      --------    |
+#              --------------------
+#                   Ksys
+
+# Written by David Clem August 15, 1994
+# completely rewritten Oct 1996 a s hodel
+# SYS_INTERNAL accesses members of system structure
+# $Revision: 1.1.1.1 $
+
+  if(nargin != 2)
+    usage("sysp = parallel(Asys,Bsys)");
+  endif
+  if(! is_struct(Asys) )
+    error("1st input argument is not a system data structure")
+  elseif (! is_struct(Bsys) )
+    error("2nd input argument is not a system data structure")
+  endif
+  mA = rows(Asys.inname);
+  mB = rows(Bsys.inname);
+  if(mA != mB)
+    error(["Asys has ",num2str(mA)," inputs, Bsys has ",num2str(mB)," inputs"]);
+  endif
+  sysp = sysgroup(Asys,Bsys);
+  sysD = ss2sys([],[],[],[eye(mA);eye(mA)]);
+  
+  #disp("sysp=")
+  #sysout(sysp)
+  #disp("sysD")
+  #sysout(sysD)
+
+  sysp = sysmult(sysp,sysD);
+  sysp = syschnames(sysp,"in",1:mA,Asys.inname);
+  
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/pinv.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,55 @@
+# Copyright (C) 1994 John W. Eaton
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+function retval = pinv (X, tol)
+
+# usage: pinv (X, tol)
+#
+# Returns the pseudoinverse of X; singular values less than tol are
+# ignored.
+#
+# If the second argument is omitted, it is assumed that
+#
+#   tol = max (size (X)) * sigma_max (X) * eps,
+#
+# where sigma_max(X) is the maximal singular value of X.
+
+# Written by Kurt Hornik (hornik@neuro.tuwien.ac.at) March 1993.
+# Dept of Probability Theory and Statistics TU Wien, Austria.
+# $Revision: 1.1 $
+
+  if (nargin < 1 || nargin > 2)
+    error ("usage: pinv (X [, tol])");
+  endif
+
+  [U, S, V] = svd(X);
+  s = diag(S);
+
+  if (nargin == 1)
+    tol = max (size (X)) * s (1) * eps;
+  endif
+
+  r = sum (s > tol);
+  if (r == 0)
+    retval = zeros (X');
+  else
+    D = diag (ones (r, 1) ./ s (1:r));
+    retval = V (:, 1:r) * D * U (:, 1:r)';
+  endif
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/place.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,133 @@
+# Copyright (C) 1997 Jose Daniel Munoz Frias
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function K = place(sys, P) 
+
+%PLACE K =  place(sys,P) Computes the matrix  K such that if the state
+%is feedback with gain K, then the eigenvalues  of the closed loop
+%system (i.e. A-BK) are those specified in the vector P.
+%
+% Version: Beta (May-1997): If you have any comments, please let me know.
+%			    (see the file place.m for my address)
+%
+% Written by: Jose Daniel Munoz Frias.
+
+%	      Universidad Pontificia Comillas
+%	      ICAIdea
+%	      Alberto Aguilera, 23
+%	      28015 Madrid, Spain
+%
+%	      E-Mail: daniel@dea.icai.upco.es
+%
+%	      Phone: 34-1-5422800   Fax: 34-1-5596569
+%
+% Algorithm taken from "The Control Handbook", IEEE press pp. 209-212
+#
+# code adaped by A.S.Hodel (a.s.hodel@eng.auburn.edu) for use in controls
+# toolbox
+# $Revision: 1.1.1.1 $
+# $Log: place.m,v $
+# Revision 1.1.1.1  1998/05/19 20:24:08  jwe
+#
+# Revision 1.2  1997/03/10 21:41:10  scotte
+# *** empty log message ***
+#
+# Revision 1.1  1997/03/10 20:38:53  scotte
+# Initial revision
+#
+
+  sav_val = empty_list_elements_ok;
+  empty_list_elements_ok = 1;
+  #
+  # check arguments
+  #
+  if(!is_struct(sys))
+    error("sys must be in system data structure format (see ss2sys)");
+  endif
+  sys = sysupdate(sys,"ss");	# make sure it has state space form up to date
+  if(!is_controllable(sys))
+    error("sys is not controllable.");
+  elseif( min(size(P)) != 1)
+    error("P must be a vector")
+  else
+    P = reshape(P,length(P),1);	# make P a column vector
+  endif
+  # system must be purely continuous or discrete
+  is_digital(sys);
+  [n,nz,m,p] = sysdimensions(sys);
+  nx = n+nz;	# already checked that it's not a mixed system.
+  if(m != 1)
+    error(["sys has ", num2str(m)," inputs; need only 1"]);
+  endif
+
+  # takes the A and B matrix from the system representation
+  [A,B]=sys2ss(sys);
+  sp = length(P);
+  if(nx == 0)
+    error("place: A matrix is empty (0x0)");
+  elseif(nx != length(P))
+    error(["A=(",num2str(nx),"x",num2str(nx),", P has ", num2str(length(P)), ...
+	"entries."])
+  endif
+
+  # arguments appear to be compatible; let's give it a try!
+  %The second step is the calculation of the characteristic polynomial ofA
+  PC=poly(A);
+
+  %Third step: Calculate the transformation matrix T that transforms the state
+  %equation in the controllable canonical form.
+
+  %first we must calculate the controllability matrix M:
+  M=B;
+  AA=A;
+  for n = 2:nx
+    M(:,n)=AA*B;
+    AA=AA*A;
+  endfor
+
+  %second, construct the matrix W
+  PCO=PC(nx:-1:1);
+  PC1=PCO; 	%Matrix to shift and create W row by row
+
+  for n = 1:nx
+    W(n,:) = PC1;
+    PC1=[PCO(n+1:nx),zeros(1,n)];
+  endfor
+
+  T=M*W;
+
+  %finaly the matrix K is calculated 
+  PD = poly(P); %The desired characteristic polynomial
+  PD = PD(nx+1:-1:2);
+  PC = PC(nx+1:-1:2);
+  
+  K = (PD-PC)/T;
+
+  %Check if the eigenvalues of (A-BK) are the same specified in P
+  Pcalc = eig(A-B*K);
+
+  Pcalc = sortcom(Pcalc);
+  P = sortcom(P);
+
+  if(max( (abs(Pcalc)-abs(P))./abs(P) ) > 0.1)
+    disp("Place: Pole placed at more than 10% relative error from specified");
+  endif
+
+  empty_list_elements_ok = sav_val;
+endfunction
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/polyout.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,76 @@
+# Copyright (C) 1995,1998 A. Scottedward Hodel
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+function y = polyout(c,x)
+#
+# usage: [y=] polyout(c[,x])
+#
+# print formatted polynomial 
+#   c(x) = c(1) * x^n + ... + c(n) x + c(n+1)
+# in a string or to the screen (if y is omitted)
+# x defaults to the string "s"
+#
+#  SEE ALSO: polyval, polyvalm, poly, roots, conv, deconv, residue, 
+#	filter, polyderiv, polyinteg
+
+# Written by A. Scottedward Hodel (scotte@eng.auburn.edu) May 1995)
+# Nov 1998: Correctly handles complex coefficients
+# $Revision$ 
+  
+  if (nargin < 1 ) || (nargin > 2) || (nargout < 0 ) || (nargout > 1)
+    usage("[y = ] polyout(c,[x])");
+  endif
+
+  if (!is_vector(c))
+    error("polyout: first argument must be a vector");
+  endif
+  
+  if (nargin == 1)
+    x = 's';
+  elseif( ! isstr(x) )
+    error("polyout: second argument must be a string");
+  endif
+
+  n = length(c);
+  if(n > 0)
+    n1 = n+1;
+
+    if( imag(c(1)) )     tmp = com2str(c(1))
+    else                 tmp = num2str(c(1));       endif
+
+    for ii=2:n
+      if(real(c(ii)) < 0)     ns = ' - ';    c(ii) = -c(ii);
+      else                    ns = ' + ';                      endif
+
+      if( imag(c(ii)) )       nstr = sprintf("(%s)",com2str(c(ii)) );
+      else                    nstr = num2str(c(ii));           endif
+
+      tmp = sprintf("%s*%s^%d%s%s",tmp,x,n1-ii,ns,nstr);
+      
+    endfor
+  else
+    tmp = " ";
+  endif
+
+  if(nargout == 0)
+    disp(tmp)
+  else
+    y = tmp;
+  endif
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/prompt.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,40 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function prompt(str)
+# function prompt([str])
+# Prompt user to continue
+# str: input string. Default value: "\n ---- Press a key to continue ---"
+# Written by David Clem August 15, 1994
+# Modified A. S. Hodel June 1995
+
+# $Revision: 1.2 $
+
+if(nargin > 1)
+  usage("prompt([str])");
+elseif(nargin == 0)
+  str = "\n ---- Press a key to continue ---";
+elseif ( !isstr(str) )
+  error("prompt: input must be a string");
+endif
+
+disp(str);
+fflush(stdout);
+kbhit;
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/pzmap.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,89 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [zer,pol]=pzmap(sys)
+# function [zer,pol]=pzmap(sys)
+# Plots the zeros and poles of a system in the complex plane.
+#
+# inputs: sys: system data structure
+# outputs: if omitted, the poles and zeros are plotted on the screen.
+#          otherwise, pol, zer are returned as the system poles and zeros.
+#          (see sys2zp for a preferable function call)
+
+# $Log: pzmap.m,v $
+# Revision 1.2  1998/07/14 22:01:28  hodelas
+# Changed to use axis2dlim (new function) to getplot limits;
+# Changed gnuplot plotting commands
+#
+
+  save_val = implicit_str_to_num_ok;	# save for later
+  save_emp = empty_list_elements_ok;
+
+  implicit_str_to_num_ok = 1;
+  empty_list_elements_ok = 1;
+
+  if(nargin != 1)
+    usage("pzmap(sys) or [zer,pol] = pzmap(sys)"); 
+  elseif (!is_struct(sys));
+    error("sys must be in system format");
+  endif
+
+  [zer,pol] = sys2zp(sys);
+
+  # force to column vectors, split into real, imaginary parts
+  zerdata = poldata = [];
+  if(length(zer))
+    zer = reshape(zer,length(zer),1);
+    zerdata = [real(zer(:,1)) imag(zer(:,1))];
+  endif
+  if(length(pol))
+    pol = reshape(pol,length(pol),1);
+    poldata = [real(pol(:,1)) imag(pol(:,1))];
+  endif
+
+  # determine continuous or discrete plane
+  vars = "sz";
+  varstr = vars(is_digital(sys) + 1);
+
+  # Plot the data
+  gset nologscale xy;
+  if(is_siso(sys))
+    title(["Pole-zero map from ",sys.inname," to ", sys.outname]);
+  endif
+  xlabel(["Re(",varstr,")"]);
+  ylabel(["Im(",varstr,")"]);
+  grid;
+
+  # compute axis limits
+  axis(axis2dlim([zerdata;poldata]));
+  grid
+  # finally, plot the data
+  if(length(zer) == 0)
+    plot(poldata(:,1), poldata(:,2),"@12 ;poles (no zeros);");
+  elseif(length(pol) == 0)
+    plot(zerdata(:,1), zerdata(:,2),"@31 ;zeros (no poles);");
+  else
+    plot(zerdata(:,1), zerdata(:,2),"@31 ;zeros;", ...
+      poldata(:,1), poldata(:,2),"@12 ;poles;");
+  endif
+  replot
+
+  implicit_str_to_num_ok = save_val;	# restore value
+  empty_list_elements_ok = save_emp;
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/qzval.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,33 @@
+# Copyright (C) 1998 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function lam = qzval(A,B)
+# X = qzval (A, B)
+# 
+# compute generalized eigenvalues of the matrix pencil (A - lambda B).
+# A and B must be real matrices.
+# 
+# This function is superseded by qz.  You should use qz instead.
+#
+
+# A. S. Hodel July 1998
+
+  warning("qzval is obsolete; calling qz instead")
+  lam = qz(A,B);
+endfunction
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/rldemo.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,297 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function rldemo()
+# Octave Controls toolbox demo: Root Locus demo
+# Written by David Clem August 15, 1994
+# Updated by John Ingram December 1996
+# $Revision: 1.2 $
+
+  while (1)
+    clc
+    k = menu("Octave Root Locus Demo", ...
+    	"Display continuous system's open loop poles and zeros (pzmap)", ...
+    	"Display discrete system's open loop poles and zeros (pzmap)", ...
+    	"Display root locus diagram of SISO continuous system (rlocus)", ...
+    	"Display root locus diagram of SISO discrete system (rlocus)", ...	
+    	"Return to main demo menu");
+    gset autoscale
+    if (k == 1)
+      clc
+      help pzmap
+      prompt
+
+      clc
+      disp("Display continuous system's open loop poles and zeros (pzmap)\n");
+      disp("Example #1, Consider the following continuous transfer function:");
+      cmd = "sys1 = tf2sys([1.5 18.5 6],[1 4 155 302 5050]);";
+      disp(cmd);
+      eval(cmd);
+      cmd ="sysout(sys1);";
+      disp(cmd);
+      eval(cmd);
+      disp("\nPole-zero form can be obtained as follows:");
+      cmd = "sysout(sys1,""zp"");";
+      disp(cmd);
+      eval(cmd);     
+      disp("View the system's open loop poles and zeros with the command:")
+      cmd = "pzmap(sys1);";
+      run_cmd
+      prompt     
+
+      clc
+      disp("Example #2, Consider the following set of poles and zeros:");
+      cmd = "sys2 = zp2sys([-1 5 -23],[-1 -10 -7+5i -7-5i],5);";
+      disp(cmd);
+      eval(cmd);
+      cmd = "sysout(sys2);";
+      disp(cmd);
+      eval(cmd);
+      disp("\nThe pzmap command for the zp form is the same as the tf form:")
+      cmd = "pzmap(sys2);";
+      run_cmd;
+      disp("\nThe internal representation of the system is not important;");
+      disp("pzmap automatically sorts it out internally.");
+      prompt;
+
+      clc
+      disp("Example #3, Consider the following state space system:\n");
+      cmd = "sys3=ss2sys([0 1; -10 -11], [0;1], [0 -2], 1);";
+      disp(cmd); 
+      eval(cmd);
+      cmd = "sysout(sys3);";
+      disp(cmd); 
+      eval(cmd);
+      disp("\nPole-zero form can be obtained as follows:");
+      cmd = "sysout(sys3,""zp"");";
+      disp(cmd);
+      eval(cmd); 
+      disp("\nOnce again, the pzmap command is the same:");
+      cmd = "pzmap(sys3);";
+      run_cmd;
+      prompt;
+
+      closeplot
+      clc
+    
+    elseif (k == 2)
+      clc
+      help pzmap
+      prompt
+
+      clc
+      disp("\nDisplay discrete system's open loop poles and zeros (pzmap)\n");
+      disp("First we must define a sampling time, as follows:\n");
+      cmd = "Tsam = 1;";
+      run_cmd;
+      disp("Example #1, Consider the following discrete transfer function:");
+      cmd = "sys1 = tf2sys([1.05 -0.09048],[1 -2 1],Tsam);";
+      disp(cmd);
+      eval(cmd);
+      cmd ="sysout(sys1);";
+      disp(cmd);
+      eval(cmd);
+      disp("\nPole-zero form can be obtained as follows:");
+      cmd = "sysout(sys1,""zp"");";
+      disp(cmd);
+      eval(cmd);     
+      disp("View the system's open loop poles and zeros with the command:")
+      cmd = "pzmap(sys1);";
+      run_cmd
+      prompt     
+
+      clc
+      disp("Example #2, Consider the following set of discrete poles and zeros:");
+      cmd = "sys2 = zp2sys([-0.717],[1 -0.368],3.68,Tsam);";
+      disp(cmd);
+      eval(cmd);
+      cmd = "sysout(sys2);";
+      disp(cmd);
+      eval(cmd);
+      disp("\nThe pzmap command for the zp form is the same as the tf form:")
+      cmd = "pzmap(sys2);";
+      run_cmd;
+      disp("\nThe internal representation of the system is not important;");
+      disp("pzmap automatically sorts it out internally.");
+      prompt;
+
+      clc
+      disp("Example #3, Consider the following discrete state space system:\n");
+      cmd = "sys3=ss2sys([1 0.0952;0 0.905], [0.00484; 0.0952], [1 0], 0, Tsam);";
+      disp(cmd); 
+      eval(cmd);
+      cmd = "sysout(sys3);";
+      disp(cmd); 
+      eval(cmd);
+      disp("\nPole-zero form can be obtained as follows:");
+      cmd = "sysout(sys3,""zp"");";
+      disp(cmd);
+      eval(cmd); 
+      disp("\nOnce again, the pzmap command is the same:");
+      cmd = "pzmap(sys3);";
+      run_cmd;
+      prompt;
+
+      closeplot
+      clc
+
+    elseif (k == 3)
+      clc
+      help rlocus
+      prompt;
+
+      clc
+      disp("Display root locus of a continuous SISO system (rlocus)\n")
+      disp("Example #1, Consider the following continuous transfer function:");
+      cmd = "sys1 = tf2sys([1.5 18.5 6],[1 4 155 302 5050]);";
+      disp(cmd);
+      eval(cmd);
+      cmd ="sysout(sys1);";
+      disp(cmd);
+      eval(cmd);
+      disp("\nPole-zero form can be obtained as follows:");
+      cmd = "sysout(sys1,""zp"");";
+      disp(cmd);
+      eval(cmd); 
+      disp("\nWhen using rlocus, inital system poles are displayed as X's.")
+      disp("Moving poles are displayed as diamonds.  Zeros are displayed as")
+      disp("boxes.  The simplest form of the rlocus command is as follows:")
+      cmd = "rlocus(sys1);";
+      run_cmd
+      disp("\nrlocus automatically selects the minimum and maximum gains based")
+      disp("on the real-axis locus breakpoints.  The plot limits are chosen")
+      disp("to be no more than 10 times the maximum magnitude of the open")
+      disp("loop poles/zeros.");
+      prompt
+
+      clc
+      disp("Example #2, Consider the following set of poles and zeros:");
+      cmd = "sys2 = zp2sys([],[0 -20 -2 -0.1],5);";
+      disp(cmd);
+      eval(cmd);
+      cmd = "sysout(sys2);";
+      disp(cmd);
+      eval(cmd);
+      disp("\nThe rlocus command for the zp form is the same as the tf form:")
+      cmd = "rlocus(sys2);";
+      run_cmd;
+      disp("\nThe internal representation of the system is not important;");
+      disp("rlocus automatically sorts it out internally.");
+      prompt;
+
+      clc
+      disp("Example #3, Consider the following state space system:\n");
+      cmd = "sys3=ss2sys([0 1; -10 -11], [0;1], [0 -2], 0);";
+      disp(cmd); 
+      eval(cmd);
+      cmd = "sysout(sys3);";
+      disp(cmd); 
+      eval(cmd);
+      disp("\nPole-zero form can be obtained as follows:");
+      cmd = "sysout(sys3,""zp"");";
+      disp(cmd);
+      eval(cmd); 
+      disp("\nOnce again, the rlocus command is the same:");
+      cmd = "rlocus(sys3);";
+      run_cmd;
+
+      disp("\nNo matter what form the system is in, the rlocus command works the");
+      disp("the same.");
+      prompt;
+
+      closeplot
+      clc
+
+    elseif (k == 4)
+      clc
+      help rlocus
+      prompt
+
+      clc
+      disp("Display root locus of a discrete SISO system (rlocus)\n")
+      disp("First we must define a sampling time, as follows:\n");
+      cmd = "Tsam = 1;";
+      run_cmd;
+      disp("Example #1, Consider the following discrete transfer function:");
+      cmd = "sys1 = tf2sys([1.05 -0.09048],[1 -2 1],Tsam);";
+      disp(cmd);
+      eval(cmd);
+      cmd ="sysout(sys1);";
+      disp(cmd);
+      eval(cmd);
+      disp("\nPole-zero form can be obtained as follows:");
+      cmd = "sysout(sys1,""zp"");";
+      disp(cmd);
+      eval(cmd);     
+      disp("\nWhen using rlocus, inital system poles are displayed as X's.")
+      disp("Moving poles are displayed as diamonds.  Zeros are displayed as")
+      disp("boxes.  The simplest form of the rlocus command is as follows:")
+      cmd = "rlocus(sys1);";
+      run_cmd
+      disp("\nrlocus automatically selects the minimum and maximum gains based")
+      disp("on the real-axis locus breakpoints.  The plot limits are chosen")
+      disp("to be no more than 10 times the maximum magnitude of the open")
+      disp("loop poles/zeros.");
+      prompt
+
+      clc
+      disp("Example #2, Consider the following set of discrete poles and zeros:");
+      cmd = "sys2 = zp2sys([-0.717],[1 -0.368],3.68,Tsam);";
+      disp(cmd);
+      eval(cmd);
+      cmd = "sysout(sys2);";
+      disp(cmd);
+      eval(cmd);
+      disp("\nThe rlocus command for the zp form is the same as the tf form:")
+      cmd = "rlocus(sys2);";
+      run_cmd;
+      disp("\nThe internal representation of the system is not important;");
+      disp("rlocus automatically sorts it out internally.  Also, it does not");
+      disp("matter if the system is continuous or discrete.  rlocus also sorts");
+      disp("this out automatically");
+      prompt;
+
+      clc
+      disp("Example #3, Consider the following discrete state space system:\n");
+      cmd = "sys3=ss2sys([1 0.0952;0 0.905], [0.00484; 0.0952], [1 0], 0, Tsam);";
+      disp(cmd); 
+      eval(cmd);
+      cmd = "sysout(sys3);";
+      disp(cmd); 
+      eval(cmd);
+      disp("\nPole-zero form can be obtained as follows:");
+      cmd = "sysout(sys3,""zp"");";
+      disp(cmd);
+      eval(cmd); 
+      disp("\nOnce again, the rlocus command is the same:");
+      cmd = "rlocus(sys3);";
+      run_cmd;
+
+      disp("\nNo matter what form the system is in, the rlocus command works the");
+      disp("the same.");
+
+      prompt;
+
+      closeplot
+      clc
+ 
+    elseif (k == 5)
+      return
+    endif
+  endwhile  
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/rlocus.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,199 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [rldata,k_break,rlpol,gvec,real_ax_pts] = rlocus(sys,increment,min_k,max_k)
+  # [rldata,k_break,rlpol,gvec,real_ax_pts] = rlocus(sys,increment,min_k,max_k)
+  # Displays root locus plot of the specified SISO system.
+  # 
+  #       -----   ---     -------- 
+  #   --->| + |---|k|---->| SISO |----------->
+  #       -----   ---     --------        | 
+  #       - ^                             | 
+  #         |_____________________________|  
+  #
+  #inputs: sys = system data structure
+  #        min_k, max_k,increment: minimum, maximum values of k and
+  #               the increment used in computing gain values
+  # outputs: plots the root locus to the screen.  
+  #   rldata: Data points plotted column 1: real values, column 2: imaginary
+  #           values)
+  #   k_break: gains for real axis break points.
+  #   rlpol: complex vector: column ii of pol is the set of poles
+  #        corresponding to to gain gvec(ii)
+  #   gvec: gains used to compute root locus
+  #   real_ax_pts: breakpoints of the real axis locus.
+  
+  # Convert the input to a transfer function if necessary
+  # Written by Clem and Tenison
+  # Updated by Kristi McGowan July 1996 for intelligent gain selection
+  # Updated by John Ingram July 1996 for systems
+  # $Revision: 1.7 $
+  
+  if (nargin < 1) | (nargin > 4)
+    usage("rlocus(sys[,inc,mink,maxk])");
+  endif
+  
+  [num,den] = sys2tf(sys);		# extract numerator/denom polyomials
+  lnum = length(num);      lden = length(den);
+  if(lden < 2)
+    error(sprintf("length of derivative=%d, doesn't make sense",lden));
+  elseif(lnum == 1)
+    num = [0 num];     # so that derivative is shortened by one
+  endif
+
+  # root locus plot axis limits
+  
+  # compute real axis locus breakpoints
+  # compute the derivative of the numerator and the denominator 
+  dern=polyderiv(num);        derd=polyderiv(den);
+  
+  # compute real axis breakpoints
+  real_ax_pol = conv(den,dern) - conv(num,derd);
+  real_ax_pts = roots(real_ax_pol);
+  if(isempty(real_ax_pts))
+    k_break = [];
+    maxk = 0;
+  else
+    # compute gains that achieve the breakpoints
+    c1 = polyval(num,real_ax_pts);
+    c2 = polyval(den,real_ax_pts);
+    k_break = -real(c2 ./ c1);
+    maxk = max(max(k_break,0));
+  endif
+
+  # compute gain ranges based on computed K values
+  if(maxk == 0)     maxk = 1; 
+  else              maxk = 1.1*maxk;        endif
+  mink = 0;
+  ngain = 20;
+
+  # check for input arguments:
+  if (nargin > 2)       mink = min_k;          endif
+  if (nargin > 3)       maxk = max_k;          endif
+  if (nargin > 1)
+    if(increment <= 0)  error("increment must be positive");
+    else
+      ngain = (maxk-mink)/increment;
+    endif
+  endif
+
+  # vector of gains
+  ngain = max(3,ngain);
+  gvec = linspace(mink,maxk,ngain);
+  
+  # Find the open loop zeros and the initial poles
+  rlzer = roots(num);
+
+  # update num to be the same length as den
+  lnum = length(num);  if(lnum < lden) num = [zeros(1,lden - lnum),num];  endif
+
+  # compute preliminary pole sets
+  nroots = lden-1;
+  for ii=1:ngain
+   gain = gvec(ii);
+   rlpol(1:nroots,ii)  = vec(sortcom(roots(den + gain*num)));
+  endfor
+
+  # compute axis limits (isolate asymptotes)
+  olpol = roots(den);
+  real_axdat = union(real(rlzer), real(union(olpol,real_ax_pts)) );
+  rmin = min(real_axdat);      rmax = max(real_axdat);
+
+  rlpolv = [vec(rlpol); vec(real_axdat)];
+  idx = find(real(rlpolv) >= rmin & real(rlpolv) <= rmax);
+  axlim = axis2dlim([real(rlpolv(idx)),imag(rlpolv(idx))]);
+  xmin = axlim(1);
+  xmax = axlim(2);
+  
+  # set smoothing tolerance per axis limits
+  smtol = 0.01*max(abs(axlim));
+  
+  # smooth poles if necessary, up to maximum of 1000 gain points
+  # only smooth points within the axis limit window
+  # smoothing done if max_k not specified as a command argument
+  done=(nargin == 4);    # perform a smoothness check
+  while((!done) & ngain < 1000)
+    done = 1 ;      # assume done
+    dp = abs(diff(rlpol'))';
+    maxd = max(dp);
+    # search for poles in the real axis limits whose neighbors are distant
+    idx = find(maxd > smtol);
+    for ii=1:length(idx)
+      i1 = idx(ii);      g1 = gvec(i1);       p1 = rlpol(:,i1);
+      i2 = idx(ii)+1;    g2 = gvec(i2);       p2 = rlpol(:,i2);
+    
+      # isolate poles in p1, p2 that are inside the real axis limits
+      bidx = find( (real(p1) >= xmin & real(p1) <= xmax)  ...
+          | (real(p2) >= xmin & real(p2) <= xmax) );
+      if(!isempty(bidx))
+        p1 = p1(bidx);
+        p2 = p2(bidx);
+        if( max(abs(p2-p1)) > smtol) 
+          newg = linspace(g1,g2,5);
+          newg = newg(2:4);
+          if(isempty(newg))
+            printf("rlocus: empty newg")
+            g1
+            g2
+            i1
+            i2
+            idx_i1 = idx(ii)
+            gvec_i1 = gvec(i1:i2)
+            delta_vec_i1 = diff(gvec(i1:i2))
+            prompt
+          endif
+          gvec =  [gvec,newg];
+          done = 0;             # need to process new gains
+        endif
+      endif
+    endfor
+    
+    # process new gain values
+    ngain1 = length(gvec);
+    for ii=(ngain+1):ngain1
+      gain = gvec(ii);
+      rlpol(1:nroots,ii)  = vec(sortcom(roots(den + gain*num)));
+    endfor
+
+    [gvec,idx] = sort(gvec);
+    rlpol = rlpol(:,idx);
+    ngain = length(gvec);
+  endwhile
+   
+  # Plot the data
+  if(nargout  == 0)
+    rlpolv = vec(rlpol);
+    idx = find(real(rlpolv) >= xmin & real(rlpolv) <= xmax);
+    axdata = [real(rlpolv(idx)),imag(rlpolv(idx))];
+    axlim = axis2dlim(axdata);
+    axlim(1:2) = [xmin xmax];
+    gset nologscale xy;
+    grid("on");
+    rldata = [real(rlpolv), imag(rlpolv) ];
+    axis(axlim);
+    [stn,inname,outname] = sysgetsignals(sys);
+    xlabel(sprintf("Root locus from %s to %s, gain=[%f,%f]: Real axis", ...
+	dezero(inname),dezero(outname),gvec(1),gvec(ngain)));
+    ylabel("Imag. axis");
+	
+    plot(real(rlpolv),imag(rlpolv),".1;locus points;", ...
+	real(olpol),imag(olpol),"x2;open loop poles;", ...
+	real(rlzer),imag(rlzer),"o3;zeros;");
+    rldata = [];
+  endif
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/rotg.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,28 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [c,s] = rotg(a,b)
+  #function [c,s] = rotg(a,b)
+  # givens rotation calculation
+  #
+  # NOTE: Use [c,s] = givens(a,b) instead.
+
+  # $Revision: 1.1 $
+
+  [c,s] = givens(a,b);
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/run_cmd.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,32 @@
+# run_cmd: short script used in demos
+# prints string cmd to the screen, then executes after a pause
+
+# $Revision: 1.1.1.1 $
+# $Log: run_cmd.m,v $
+# Revision 1.1.1.1  1998/05/19 20:24:05  jwe
+#
+# Revision 1.4  1997/02/20 16:07:26  hodel
+# added "fflush" after disp("executing")
+#
+# Revision 1.3  1997/02/12 15:38:14  hodel
+# added separator after command execution
+#
+# added blank line after eval(cmd)
+#
+# Revision 1.1  1997/02/12 11:35:08  hodel
+# Initial revision
+#
+# Revision 1.3  1997/02/07 15:44:13  scotte
+# Added "executing" string so that users would know that the command was
+# being processed
+#
+
+disp(["Command: ",cmd])
+puts("Press a key to execute command");
+fflush(stdout);
+kbhit();
+disp("  executing");
+fflush(stdout);
+eval(cmd);
+disp("---")
+disp(" ")
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/series.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,97 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [a,b,c,d] = series(a1,b1,c1,d1,a2,b2,c2,d2)
+# Forms the series connection of two systems.
+#
+# Superseded by sysmult.  Do not use this routine!
+# used internally in zp2ss
+#
+# Type of input: Transfer functions
+# Command:       [num,den]=series(num1,den1,num2,den2)
+# Forms the series representation of the two transfer functions.
+#
+# Type of input: State space systems
+# Command:       [a,b,c,d]=series(a1,b1,c1,d1,a2,b2,c2,d2)
+# Forms the series representation of the two state space system arguments.
+# The series connected system will have the inputs of system 1 and the 
+# outputs of system 2.
+#
+# Type of input: system data structure
+# Command:       syst=series(syst1,syst2)
+# Forms the series representation of the two mu system arguments.
+# Written by David Clem August 15, 1994
+
+# If two arguments input, take care of mu system case
+# $Revision: 1.1.1.1 $
+
+  warning("series is superseded by sysmult; use sysmult instead.")
+
+  muflag = 0;
+  if(nargin == 2)
+    temp=b1;
+    [a1,b1,c1,d1]=sys2ss(a1);
+    [a2,b2,c2,d2]=sys2ss(temp);
+    muflag = 1;
+  endif
+
+# If four arguments input, put two transfer functions in series
+
+  if(nargin == 4)
+    a = conv(a1,c1);	% was conv1
+    b = conv(b1,d1);	% was conv1
+    c = 0;
+    d = 0;
+
+# Find series combination of 2 state space systems
+
+  elseif((nargin == 8)||(muflag == 1))
+
+# check matrix dimensions
+  
+    [n1,m1,p1] = abcddim(a1,b1,c1,d1);
+    [n2,m2,p2] = abcddim(a2,b2,c2,d2);
+
+    if((n1 == -1) || (n2 == -1))
+      error("Incorrect matrix dimensions");
+    endif
+
+# check to make sure the number of outputs of system1 equals the number
+# of inputs of system2
+
+   if(p1 ~= m2)
+     error("System 1 output / System 2 input connection sizes do not match");
+   endif
+
+# put the two state space systems in series
+
+    a = [a1 zeros(rows(a1),columns(a2));b2*c1 a2];
+    b = [b1;b2*d1];
+    c = [d2*c1 c2];
+    d = [d2*d1];
+
+# take care of mu output
+
+    if(muflag == 1)
+      a=ss2sys(a,b,c,d);
+      b=c=d=0;
+    endif 
+  endif
+
+endfunction
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/sortcom.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,79 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [yy,idx] = sortcom(xx,opt)
+# [yy,idx] = sortcom(xx[,opt]): sort a complex vector
+# xx: complex vector
+# opt: sorting option:
+#	"re": real part (default)
+#	"mag": by magnitude
+#	"im": by imaginary part
+#
+#  if opt != "im" then values with common real part/magnitude are
+#     sorted by imaginary part, i.e. a - jb followed by a + jb. 
+#     [Complex conjugate pairs may not be grouped consecutively if more than 2
+#     numbers share a common real part/magnitude]
+# yy: sorted values
+# idx: permutation vector: yy = xx(idx)
+
+# Written by A. S. Hodel June 1995
+# $Revision: 1.4 $
+
+  if( nargin < 1 | nargin > 2 )
+     usage("yy = sortcom(xx[,opt]");
+  elseif( !(is_vector(xx) | isempty(xx) ))
+    error("sortcom: first argument must be a vector");
+  endif
+
+  if(nargin == 1)         opt = "re";
+  else
+    if (!isstr(opt))
+      error("sortcom: second argument must be a string");
+    endif
+  endif
+
+  if(strcmp(opt,"re"))        datavec = real(xx);
+  elseif(strcmp(opt,"im"))    datavec = imag(xx);
+  elseif(strcmp(opt,"mag"))   datavec = abs(xx);
+  else
+    error(["sortcom: illegal option = ", opt])
+  endif
+
+  [datavec,idx] = sort(datavec);
+  yy= xx(idx);
+  
+  if(strcmp(opt,"re") | strcmp(opt,"mag"))
+    # sort so that complex conjugate pairs appear together
+    
+    ddiff = diff(datavec);
+    zidx = find(ddiff == 0);
+
+    # sort common datavec values
+    if(!isempty(zidx))
+      for iv=create_set(datavec(zidx))
+        vidx = find(datavec == iv);
+        [vals,imidx] = sort(imag(yy(vidx)));
+        yy(vidx)  = yy(vidx(imidx));
+        idx(vidx) = idx(vidx(imidx));
+      endfor
+    endif
+
+  endif
+
+endfunction
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/ss2sys.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,219 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function  outsys = ss2sys  (a,b,c,d,tsam,n,nz,stname,inname,outname,outlist)
+  # outsys = ss2sys  (a,b,c{,d,tsam,n,nz,stname,inname,outname,outlist})
+  # Create system structure from state-space data.   May be continous,
+  # discrete, or mixed (sampeld-data)
+  # inputs:
+  #   a, b, c, d: usual state space matrices.
+  #               default: d = zero matrix
+  #   tsam: sampling rate.  Default: tsam = 0 (continuous system)
+  #   n, nz: number of continuous, discrete states in the system
+  #        default: tsam = 0: n = rows(a), nz = 0
+  #                 tsam > 0: n = 0,       nz = rows(a), n 
+  #        see below for system partitioning
+  #   stname: string matrix of state signal names
+  #           default (stname=[] on input): x_n for continuous states,
+  #                    xd_n for discrete states
+  #   inname: string matrix of input signal names
+  #           default (inname = [] on input): u_n
+  #   outname: string matrix of input signal names
+  #           default (outname = [] on input): y_n
+  #   outlist: list of indices of outputs y that are sampled
+  #           default: (tsam = 0)  outlist = []
+  #                    (tsam > 0)  outlist = 1:rows(c)
+  #           Unlike states, discrete/continous outputs may appear
+  #           in any order.
+  #           Note: sys2ss returns a vector yd where
+  #                 yd(outlist) = 1; all other entries of yd are 0.
+  #
+  #  System partitioning: Suppose for simplicity that outlist specified
+  #  that the first several outputs were continuous and the remaining outputs
+  #  were discrete.  Then the system is partitioned as
+  #   x = [ xc ]  (n x 1)
+  #       [ xd ]  (nz x 1 discrete states)
+  #   a = [ acc acd ]    b = [ bc ]
+  #       [ adc add ]        [ bd ]
+  #   c = [ ccc  ccd  ]    d = [ dc ]
+  #       [ cdc  cdd  ]    d = [ dd ]  (cdc = c(outlist,1:n), etc.)
+  # 
+  # with dynamic equations:
+  #   
+  #  d/dt xc(t)     = acc*xc(t)      + acd*xd(k*tsam) + bc*u(t)
+  #  xd((k+1)*tsam) = adc*xc(k*tsam) + add*xd(k*tsam) + bd*u(k*tsam)
+  #  yc(t)      = ccc*xc(t)      + ccd*xd(k*tsam) + dc*u(t)
+  #  yd(k*tsam) = cdc*xc(k*tsam) + cdd*xd(k*tsam) + dd*u(k*tsam)
+  #  
+  #  signal partitions: 
+  #            | continuous      | discrete               |
+  #  ------------------------------------------------------
+  #  states    | stname(1:n,:)   | stname((n+1):(n+nz),:) |
+  #  ------------------------------------------------------
+  #  outputs   | outname(cout,:) | outname(outlist,:)     |
+  #  ------------------------------------------------------
+  #
+  #  where cout = list if indices in 1:rows(p) not contained in outlist.
+  #
+
+  #  Written by John Ingram (ingraje@eng.auburn.edu)  July 20, 1996
+  # $Revision: 1.3 $
+  # $Log: ss2sys.m,v $
+  # Revision 1.3  1998/07/01 20:55:08  hodelas
+  # Updated sysgroup, sys2ss, ss2sys to use system structure interface
+  #
+  # Revision 1.4  1997/03/11 15:19:27  scotte
+  # fixed warning message about inname dimensions a.s.hodel@eng.auburn.edu
+  #
+
+  save_val = implicit_str_to_num_ok;	# save for later
+  implicit_str_to_num_ok = 1;
+
+  #  Test for correct number of inputs
+  if ((nargin < 3) | (nargin > 11))
+    error("Incorrect number of arguments");
+  endif
+
+  # verify A, B, C, D arguments
+  #  If D is not specified, set it to a zero matrix of appriate dimension.
+  if (nargin == 3) 
+    d = zeros(rows(c) , columns(b));
+  elseif (isempty(d))
+    d = zeros(rows(c) , columns(b));
+  endif
+
+  #  Check the dimensions
+  [na,m,p] = abcddim(a,b,c,d);
+
+  #  If dimensions are wrong, exit function
+  if (m == -1)
+    error("a,b,c,d matrix dimensions are not compatible");
+  endif
+
+  # check for tsam input
+  if(nargin < 5)
+    tsam = 0;
+  elseif( !( is_sample(tsam) | (tsam == 0) ) )
+    error("tsam must be a nonnegative real scalar");
+  endif
+
+  # check for continuous states
+  if( (nargin < 6) & (tsam == 0) )
+    n = na;
+  elseif(nargin < 6)
+    n = 0;
+  elseif( (!is_scalar(n)) | (n < 0 ) | (n != round(n)) )
+    if(is_scalar(n))
+      error(["illegal value of n=",num2str(n)]);
+    else
+      error(["illegal value of n=(",num2str(rows(n)),"x", ...
+	num2str(columns(n)),")"]);
+    endif
+  endif
+
+  # check for num discrete states
+  if( (nargin < 7) & (tsam == 0))
+    nz = 0;
+  elseif(nargin < 7)
+    nz = na - n;
+  elseif( (!is_scalar(nz)) | (nz < 0 ) | (nz != round(nz)) )
+    if(is_scalar(nz))
+      error(["illegal value of nz=",num2str(nz)]);
+    else
+      error(["illegal value of nz=(",num2str(rows(nz)),"x", ...
+	num2str(columns(nz)),")"]);
+    endif
+  endif
+
+  #check for total number of states
+  if( (n + nz) != na )
+    error(["Illegal: a is ",num2str(na),"x",num2str(na),", n=", ...
+	num2str(n),", nz=",num2str(nz)]);
+  endif
+
+  # check for state names
+  if(nargin < 8)
+    stname = sysdefstname(n,nz);
+  else
+    nr = rows(stname);
+    if(na != nr)
+      error(["ss2sys: ",num2str(na),"system states,", ...
+	num2str(nr)," state names provided"]);
+    endif
+  endif
+
+  #check for input names
+  if(nargin < 9)
+    inname = sysdefioname(m,"u");
+  elseif( !isstr(inname) )
+    warning("ss2sys: inname=")
+    disp(inname);
+    error("inname must be a string or string matrix.");
+  elseif(rows(inname) != m )
+    warning("ss2sys: inname=")
+    disp(inname);
+    error(["inname has ",num2str(rows(inname))," rows, sys has ", ...
+      num2str(m)," inputs."]);
+  endif
+
+  #check for output names
+  if(nargin < 10)
+    outname = sysdefioname(p,"y");
+  elseif( !isstr(outname) )
+    warning("ss2sys: outname=")
+    disp(outname);
+    error("outname must be a string or string matrix.");
+  elseif(rows(outname) != p )
+    warning("ss2sys: outname=")
+    disp(outname);
+    error(["outname has ",num2str(rows(outname))," rows, sys has ", ...
+      num2str(p)," outputs."]);
+  endif
+
+  # set up yd
+  if(nargin < 11)
+    yd = ones(1,p)*(tsam > 0);
+  else
+    yd = zeros(1,p);
+    yd(outlist) = ones(1,length(outlist));
+    if(max(outlist) > p)
+      error(["max outlist index=",num2str(max(outlist)), ...
+	" exceeds number of outputs=",num2str(p)]);
+    endif
+  endif
+
+  # Construct the state space system
+  outsys.a = a; 
+  outsys.b = b; 
+  outsys.c = c; 
+  outsys.d = d;
+
+  outsys.n = n;
+  outsys.nz = nz;
+  outsys.tsam = tsam;
+  outsys.yd = yd;
+
+  outsys.stname = stname;
+  outsys.inname = inname;
+  outsys.outname = outname;
+
+  #  Set the system vector:  active = 2(ss), updated = [0 0 1];
+  outsys.sys = [2 0 0 1]; 
+
+  implicit_str_to_num_ok = save_val;	# restore value
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/ss2tf.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,74 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [num,den] = ss2tf(a,b,c,d)
+# [num,den] = ss2tf(a,b,c,d)
+# Conversion from tranfer function to state-space.
+# The state space system
+#      . 
+#      x = Ax + Bu
+#      y = Cx + Du
+#
+# is converted to a transfer function
+#
+#                num(s)
+#          G(s)=-------
+#                den(s)
+#
+# used internally in system data structure manipulations
+
+# Written by R. Bruce Tenison (June 24, 1994) btenison@eng.auburn.edu
+# a s hodel: modified to allow for pure gain blocks Aug 1996
+# $Revision: 1.1.1.1 $
+
+# Check args
+  [n,m,p] = abcddim(a,b,c,d);
+  if (n == -1)
+    num = [];
+    den = [];
+    error("ss2tf: Non compatible matrix arguments");
+  elseif ( (m != 1) | (p != 1))
+    num = [];
+    den = [];
+    error(["ss2tf: not SISO system: m=",num2str(m)," p=",num2str(p)]);
+  endif
+  
+  if(n == 0)
+    # gain block only
+    num = d;
+    den = 1;
+  else
+    # First, get the denominator coefficients
+    den = poly(a);
+  
+    # Get the zeros of the system
+    [zz,g] = tzero(a,b,c,d);
+
+    # Form the Numerator (and include the gain)
+    if (!isempty(zz))
+      num = g * poly(zz);
+    else
+      num = g;
+    endif
+  
+    # the coefficients must be real
+    den = real(den);
+    num = real(num);
+  endif
+endfunction
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/ss2zp.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,53 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [zer,pol,k] = ss2zp(a,b,c,d)
+# Converts a state space representation to a set of poles and zeros.
+#
+# [pol,zer,k] = ss2zp(a,b,c,d) returns the poles and zeros of the state space 
+# system (a,b,c,d).  K is a gain associated with the zeros.
+#
+# used internally in system data structure manipulations
+
+# Written by David Clem August 15, 1994
+# Hodel: changed order of output arguments to zer, pol, k. July 1996
+# a s hodel: added argument checking, allow for pure gain blocks aug 1996
+# $Revision: 1.1.1.1 $
+
+  if(nargin != 4)
+    usage("[zer,pol,k] = ss2zp(a,b,c,d)");
+  endif
+
+  [n,m,p] = abcddim(a,b,c,d);
+  if (n == -1)
+    error("ss2tf: Non compatible matrix arguments");
+  elseif ( (m != 1) | (p != 1))
+    error(["ss2tf: not SISO system: m=",num2str(m)," p=",num2str(p)]);
+  endif
+ 
+  if(n == 0)
+    # gain block only
+    k = d;
+    zer = pol = [];
+  else
+    # First, get the denominator coefficients
+    [zer,k] = tzero(a,b,c,d);
+    pol = eig(a);
+  endif
+endfunction
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/starp.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,129 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [sys] = starp(P, K, ny, nu);
+#
+# [sys] = starp(P, K, ny, nu)
+#
+# Redheffer star product or upper/lower LFT, respectively.
+#
+#
+#               +-------+
+#     --------->|       |---------> 
+#               |   P   |
+#          +--->|       |---+  ny
+#          |    +-------+   |
+#          +-------------------+
+#                           |  |
+#          +----------------+  |
+#          |                   |
+#          |    +-------+      |
+#          +--->|       |------+ nu 
+#               |   K   |
+#     --------->|       |--------->
+#               +-------+
+#
+# If ny and nu "consume" all inputs and outputs of K then the result
+# is a lower fractional transformation. If ny and nu "consume" all
+# inputs and outputs of P then the result is an upper fractional
+# transformation.
+#
+# ny and/or nu may be negative (= negative feedback)
+
+# Written by Kai Mueller May 1998
+# $Revision: 1.1.1.1 $
+# $Log: starp.m,v $
+# Revision 1.1.1.1  1998/05/19 20:24:08  jwe
+#
+# Revision 1.1  1998/05/05 17:04:20  scotte
+# Initial revision
+#
+# Revision 1.1  1998/05/04  15:12:14  mueller
+# Initial revision
+#
+
+  if((nargin != 2) && (nargin != 4))
+    usage("[sys] = starp(P, K, ny, nu)");
+  endif
+  if (!is_struct(P))
+    error("---> P must be in system data structure");
+  endif
+  if (!is_struct(K))
+    error("---> K must be in system data structure");
+  endif
+
+  P = sysupdate(P, "ss");
+  [n, nz, mp, pp] = sysdimensions(P);
+  np = n + nz;
+  K = sysupdate(K, "ss");
+  [n, nz, mk, pk] = sysdimensions(K);
+  nk = n + nz;
+  ny_sign = 1;
+  nu_sign = 1;
+  if (nargin == 2)
+    # perform a LFT of P and K (upper or lower)
+    ny = min([pp mk]);
+    nu = min([pk mp]);
+  else
+    if (ny < 0)
+      ny = -ny;
+      ny_sign = -1;
+    endif
+    if (nu < 0)
+      nu = -nu;
+      nu_sign = -1;
+    endif
+  endif
+  if (ny > pp)
+    error("---> P has not enough outputs.");
+  endif
+  if (nu > mp)
+    error("---> P has not enough inputs.");
+  endif
+  if (ny > mk)
+    error("---> K has not enough inputs.");
+  endif
+  if (nu > pk)
+    error("---> K has not enough outputs.");
+  endif
+  nwp  = mp - nu;
+  nzp  = pp - ny;
+  nwk  = mk - ny;
+  nzk  = pk - nu;
+  if ((nwp + nwk) < 1)
+    error("---> no inputs left for star product.");
+  endif
+  if ((nzp + nzk) < 1)
+    error("---> no outputs left for star product.");
+  endif
+
+  # checks done, form sys
+  if (nzp)  Olst = [1:nzp];  endif
+  if (nzk)  Olst = [Olst pp+nu+1:pp+pk];  endif
+  if (nwp)  Ilst = [1:nwp];  endif
+  if (nwk)  Ilst = [Ilst mp+ny+1:mp+mk];  endif
+  Clst = zeros(ny+nu,2);
+  for ii = 1:nu
+    Clst(ii,:) = [nwp+ii nu_sign*(pp+ii)];
+  endfor
+  for ii = 1:ny
+    Clst(nu+ii,:) = [mp+ii ny_sign*(nzp+ii)];
+  endfor
+  sys = buildssic(Clst,[],Olst,Ilst,P,K);
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/step.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,86 @@
+# Copyright (C) 1996 A. Scottedward Hodel
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [y, t] = step(sys, inp, tstop, n)
+# step: Step response for a linear system.
+#       The system can be discrete or multivariable (or both).
+#
+# [y, t] = step(sys[, inp, tstop, n])
+# Produces a plot or the step response data for system sys.
+#
+# The argument tstop (scalar value) denotes the time when the
+# simulation should end. The Parameter n is the number of data values.
+# Both parameters tstop and n can be ommitted and will be
+# computed from the eigenvalues of the A-Matrix.
+#
+# When the step function is invoked with the output parameter y
+# a plot is not displayed.
+#
+# See also: impulse, stepimp
+
+# Written by Kai P. Mueller September 30, 1997
+# based on lsim.m of Scottedward Hodel
+# modified by
+# $Revision: 1.1.1.1 $
+# $Log: step.m,v $
+# Revision 1.1.1.1  1998/05/19 20:24:08  jwe
+#
+# Revision 1.3  1997/12/01 16:51:50  scotte
+# updated by Mueller 27 Nov 97
+#
+# Revision 1.1  1997/11/11  17:34:34  mueller
+# Initial revision
+#
+
+  if((nargin < 1) || (nargin > 4))
+    usage("[y, u] = step(sys[, inp, tstop, n])");
+  endif
+
+  if(nargout > 2)
+    usage("[y, u] = step(sys[, inp, tstop, n])");
+  endif
+
+  if(!is_struct(sys))
+    error("step: sys must be a system data structure.");
+  endif
+
+  if (nargout == 0)
+    switch (nargin)
+      case (1)
+        stepimp(1, sys);
+      case (2)
+        stepimp(1, sys, inp);
+      case (3)
+        stepimp(1, sys, inp, tstop);
+      case (4)
+        stepimp(1, sys, inp, tstop, n);
+    endswitch
+  else
+    switch (nargin)
+      case (1)
+        [y, t] = stepimp(1, sys);
+      case (2)
+        [y, t] = stepimp(1, sys, inp);
+      case (3)
+        [y, t] = stepimp(1, sys, inp, tstop);
+      case (4)
+        [y, t] = stepimp(1, sys, inp, tstop, n);
+    endswitch
+  endif
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/stepimp.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,302 @@
+# Copyright (C) 1996 A. Scottedward Hodel
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [y, t] = stepimp(sitype, sys, inp, tstop, n)
+# step: Impulse or step response for a linear system.
+#       The system can be discrete or multivariable (or both).
+#       This m-file contains the "common code" of step and impulse.
+#
+# [y, t] = stepimp(sitype, sys[, inp, tstop, n])
+# Produces a plot or the response data for system sys.
+#
+# Limited argument checking; "do not attempt to do this at home".
+# Use step or impulse instead.
+#
+# See also:  step, impulse
+
+# Written by Kai P. Mueller October 2, 1997
+# based on lsim.m of Scottedward Hodel
+# $Revision: 1.1.1.1 $
+# $Log: stepimp.m,v $
+# Revision 1.1.1.1  1998/05/19 20:24:08  jwe
+#
+# Revision 1.4  1998/05/05 17:04:35  scotte
+# minor corrections by Kai Mueller 5 May 1998
+#
+# Revision 1.1  1998/05/04  15:12:42  mueller
+# Initial revision
+#
+# Revision 1.3  1997/12/01 16:51:50  scotte
+# updated by Mueller 27 Nov 97
+#
+# Revision 1.4  1997/11/26  17:41:18  mueller
+# impulse gives now expected results for continuous and discrete systems
+#
+# Revision 1.3  1997/11/24  18:57:57  mueller
+# gset autoscale for proper scaling
+#
+# Revision 1.2  1997/11/24  17:23:38  mueller
+# call to oneplot() and gset nokey added
+#
+# Revision 1.1  1997/11/11  17:34:50  mueller
+# Initial revision
+#
+
+  if (sitype == 1)
+    IMPULSE = 0;
+  elseif (sitype == 2)
+    IMPULSE = 1;
+  else
+    error("stepimp: illegal sitype argument.")
+  endif
+  sys = sysupdate(sys,"ss");
+
+  USE_DEF = 0;   # default tstop and n if we have to give up
+  N_MIN = 50;    # minimum number of points
+  N_MAX = 2000;  # maximum number of points
+  T_DEF = 10.0;  # default simulation time
+  # collect useful information about the system
+  NOUT = rows(sys.c);
+  NIN = columns(sys.b);
+  if (nargin < 3)
+    inp = 1;
+  elseif ((inp < 1) || (inp > NIN))
+    error("Argument inp out of range")
+  endif
+  DIGITAL = is_digital(sys);
+  if (DIGITAL)
+    NSTATES = sys.nz;
+    TSAMPLE = sys.tsam;
+    if (TSAMPLE < eps)
+      error("stepimp: sampling time of discrete system too small.")
+    endif
+  else
+    NSTATES = sys.n;
+  endif
+  if (NSTATES < 1)
+    error("step: n < 1, step response is trivial")
+  endif
+  if (nargin < 5)
+    # we have to compute the time when the system reaches steady state
+    # and the step size
+    ev = eig(sys.a);
+    if (DIGITAL)
+      # perform bilinear transformation on poles in z
+      for i = 1:NSTATES
+        pole = ev(i);
+	if (abs(pole + 1) < 1.0e-10)
+	  ev(i) = 0;
+	else
+	  ev(i) = 2 / TSAMPLE * (pole - 1) / (pole + 1);
+	endif
+      endfor
+    endif
+    # remove poles near zero from eigenvalue array ev
+    nk = NSTATES;
+    for i = 1:NSTATES
+      if (abs(ev(i)) < 1.0e-10)
+        ev(i) = 0;
+        nk = nk - 1;
+      endif
+    endfor
+    if (nk == 0)
+      USE_DEF = 1;
+      #printf("##STEPIMP-DEBUG: using defaults.\n");
+    else
+      ev = ev(find(ev));
+      x = max(abs(ev));
+      t_step = 0.2 * pi / x;
+      x = min(abs(real(ev)));
+      t_sim = 5.0 / x;
+      # round up
+      yy = 10^(ceil(log10(t_sim)) - 1);
+      t_sim = yy * ceil(t_sim / yy);
+      #printf("##STEPIMP-DEBUG: nk=%d   t_step=%f  t_sim=%f\n",
+      #       nk, t_step, t_sim);  
+    endif
+  endif
+
+  if (DIGITAL)
+    # ---- sampled system
+    if (nargin == 5)
+      n = round(n);
+      if (n < 2)
+        error("stepimp: n must not be less than 2.")
+      endif
+    else
+      if (nargin == 4)
+        # n is unknown
+      elseif (nargin >= 1)
+        # tstop and n are unknown
+        if (USE_DEF)
+          tstop = (N_MIN - 1) * TSAMPLE;
+        else
+          tstop = t_sim;
+        endif
+      endif
+      n = floor(tstop / TSAMPLE) + 1;
+      if (n < 2)  n = 2;  endif
+      if (n > N_MAX)
+	n = N_MAX;
+	printf("Hint: number of samples limited to %d by default.\n", \
+	       N_MAX);
+	printf("  ==> increase \"n\" parameter for longer simulations.\n");
+      endif
+    endif
+    tstop = (n - 1) * TSAMPLE;
+    t_step = TSAMPLE;
+  else
+    # ---- continuous system
+    if (nargin == 5)
+      n = round(n);
+      if (n < 2)
+        error("step: n must not be less than 2.")
+      endif
+      t_step = tstop / (n - 1);
+    else
+      if (nargin == 4)
+        # only n in unknown
+        if (USE_DEF)
+          n = N_MIN;
+	  t_step = tstop / (n - 1);
+        else
+          n = floor(tstop / t_step) + 1;
+        endif
+      else
+        # tstop and n are unknown
+        if (USE_DEF)
+          tstop = T_DEF;
+	  n = N_MIN;
+	  t_step = tstop / (n - 1);
+        else
+          tstop = t_sim;
+          n = floor(tstop / t_step) + 1;
+        endif
+      endif
+      if (n < N_MIN)
+	n = N_MIN;
+        t_step = tstop / (n - 1);
+      endif
+      if (n > N_MAX)
+    	tstop = (n - 1) * t_step;
+	t_step = tstop / (N_MAX - 1);
+	n = N_MAX;
+      endif
+    endif
+    tstop = (n - 1) * t_step;
+    B = sys.b(:,inp);
+    sys = c2d(sys, t_step);
+  endif
+  #printf("##STEPIMP-DEBUG: t_step=%f n=%d  tstop=%f\n", t_step, n, tstop);
+
+  F = sys.a;
+  G = sys.b(:,inp);
+  C = sys.c;
+  D = sys.d(:,inp);
+  y = zeros(NOUT, n);
+  t = linspace(0, tstop, n);
+
+  if (IMPULSE)
+    if (!DIGITAL && (D'*D > 0))
+      error("impulse: D matrix is nonzero, impulse response infinite.")
+    endif
+    if (DIGITAL)
+      y(:,1) = D;
+      x = G / t_step;
+    else
+      x = B;
+      y(:,1) = C * x;
+      x = F * x;
+    endif
+    for i = 2:n
+      y(:,i) = C * x;
+      x = F * x;
+    endfor
+  else
+    x = zeros(NSTATES, 1);
+    for i = 1:n
+      y(:,i) = C * x + D;
+      x = F * x + G;
+    endfor
+  endif
+
+  if(nargout == 0)
+    # Plot the information
+    oneplot();
+    gset nogrid
+    gset nologscale
+    gset autoscale
+    gset nokey
+    clearplot();
+    if (gnuplot_has_multiplot)
+      if (IMPULSE)
+        gm = zeros(NOUT, 1);
+	tt = "impulse";
+      else
+        ssys = ss2sys(F, G, C, D, t_step);
+        gm = dcgain(ssys);
+	tt = "step";
+      endif
+      ncols = floor(sqrt(NOUT));
+      nrows = ceil(NOUT / ncols);
+      for i = 1:NOUT
+        subplot(nrows, ncols, i);
+	title([tt, ": | ", sys.inname(inp,:), " -> ", sys.outname(i,:)]);
+	if (DIGITAL)
+	  [ts, ys] = stairs(t, y(i,:));
+	  ts = ts(1:2*n-2)';  ys = ys(1:2*n-2)';
+	  if (length(gm) > 0)
+	    yy = [ys; gm(i)*ones(size(ts))];
+	  else
+	    yy = ys;
+	  endif
+	  grid("on");
+	  xlabel("time [s]");
+	  ylabel("y(t)");
+          plot(ts, yy);
+	else
+	  if (length(gm) > 0)
+	    yy = [y(i,:); gm(i)*ones(size(t))];
+	  else
+	    yy = y(i,:);
+	  endif
+	  grid("on");
+	  xlabel("time [s]");
+	  ylabel("y(t)");
+	  plot(t, yy);
+	endif
+      endfor
+      # leave gnuplot in multiplot mode is bad style
+      oneplot();
+    else
+      # plot everything in one diagram
+      title([tt, " response | ", sys.inname(inp,:), " -> all outputs"]);
+      if (DIGITAL)
+        stairs(t, y(i,:));
+      else
+	grid("on");
+	xlabel("time [s]");
+	ylabel("y(t)");
+	plot(t, y(i,:));
+      endif
+    endif
+    y=[];
+    t=[];
+  endif
+  #printf("##STEPIMP-DEBUG: gratulations, successfull completion.\n");
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/strappend.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,34 @@
+# Copyright (C) 1998 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function retval = strappend(str,suffix);
+  # retval = strappend(str,suffix);
+  # append string suffix to each string in the string matrix str
+  
+  if(nargin != 2 | nargout > 1)
+    usage(" retval = strappend(str,suffix)");
+  elseif(!isstr(str) | !isstr(suffix))
+    error("Both arguments must be strings")
+  endif
+
+  for ii=1:rows(str)
+    newst = [dezero(str(ii,:)),suffix];
+    retval(ii,1:length(newst)) = (newst);
+  endfor
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/susball.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,94 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+    cmd = "ballsys = margetsys(""disc"")";
+    eval(cmd);
+    
+    disp("Design LQG controller");
+    cmd = "sysout(ballsys)";
+    run_cmd
+    disp("add noise inputs to system...")
+ 
+    disp("discrete system:")
+    cmd = "ballsys = sysappend(ballsys,eye(ballsys.nz));";
+    run_cmd 
+
+    cmd = "sysout(ballsys)";
+    run_cmd
+
+    disp("Notice the two additional inputs, u_2, and u_3.  These are the ");
+    disp("""entry points"" for the gaussian noise disturbance.");
+    disp(" ");
+    disp("We'll design the controller to use only position feedback:")
+
+    cmd = "ballsys=sysprune(ballsys,1,[]);";
+    run_cmd
+    cmd = "sysout(ballsys)";
+    run_cmd
+
+    disp("Now design an LQG controller: Sigw: input noise")
+    Sigw = eye(2)
+    disp("Now design an LQG controller: Sigv: measurement noise")
+    Sigv = eye(rows(ballsys.c))
+
+    disp("State and input penalties:")
+    Q = eye(2)
+    R = 1
+    disp("Controlled input is input 1");
+
+    cmd="Ksys = lqg(ballsys,Sigw,Sigv,Q,R,1);";
+    run_cmd
+
+    disp("sysout(Ksys);");
+    sysout(Ksys);
+
+    disp("\nGet rid of the disturbance inputs");
+    cmd = "ballsys = sysprune(ballsys,1,1);"
+    run_cmd;
+    sysout(ballsys);
+    sysout(ballsys,"zp");
+
+    disp("\nGrouping the plant and the controller");
+    cmd = "closed_loop = sysgroup(ballsys,Ksys);"
+    run_cmd;
+    sysout(closed_loop);
+
+    disp("\nduplicating the plant input");
+    cmd = "closed_loop = sysdup(closed_loop,[],1);"
+    run_cmd;
+    sysout(closed_loop);
+
+#    disp("\nscaling the duplicated input by -1");
+#    cmd = "closed_loop = sysscale(closed_loop,[],diag([1,1,1]));"
+#    run_cmd;
+#    sysout(closed_loop);
+
+    disp("\nconnecting plant output to controller input and controller output");
+    disp("to the duplicated plant input");
+    cmd = "closed_loop = sysconnect(closed_loop,[1 2],[2 3]);"
+    run_cmd;
+    sysout(closed_loop);
+
+    disp("\nkeeping only the original plant input and plant output");
+    cmd = "closed_loop = sysprune(closed_loop,1,1);"
+    run_cmd;
+    sysout(closed_loop);
+
+    sysout(closed_loop,"zp");
+
+ 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/swap.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,30 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [a1,b1] = swap(a,b)
+  # [a1,b1] = swap(a,b)
+  # interchange a and b
+
+  # A. S. Hodel July 24 1992
+  # Conversion to Octave R. Bruce Tenison July 4, 1994
+  # $Revision: 1.1 $
+
+  a1 = b;
+  b1 = a;
+endfunction
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/swapcols.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,31 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function B = swapcols(A)
+  # function B = swapcols(A)
+  # permute columns of A into reverse order
+  
+  # A. S. Hodel July 23, 1992
+  # Conversion to Octave R. Bruce Tenison July 4, 1994
+  # $Revision: 1.1 $
+
+  m = length(A(1,:));
+  idx = m:-1:1;
+  B = A(:,idx);
+endfunction
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/swaprows.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,31 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function B = swaprows(A)
+  # function B = swaprows(A)
+  # permute rows of A into reverse order
+
+  # A. S. Hodel July 23, 1992
+  # Conversion to Octave R. Bruce Tenison July 4, 1994
+  # $Revision: 1.1.1.1 $
+  
+  m = rows(A);
+  idx = m:-1:1;
+  B = A(idx,:);
+endfunction
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/sys2fir.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,46 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [c,tsam,input,output] = sys2fir(sys)
+# function [c,tsam,input,output] = sys2fir(sys)
+# extract fir system from system data structure
+
+# $Revision: 1.1.1.1 $
+# a s hodel July 1996
+
+  sys=sysupdate(sys,"tf");		# make sure it's SISO
+  alph = sys.den(1);			# scale to get monic denominator
+  sys.den = sys.den/alph;
+  sys.num = sys.num/alph;
+  l = length(sys.den);
+  m = length(sys.num);
+  if( norm(sys.den(2:l)) )
+    sysout(sys,"tf");
+    error("denominator has poles away from origin");
+  elseif( !is_digital(sys) )
+    error("system must be discrete-time to be FIR");
+  elseif(m != l)
+    warning(["sys2fir: deg(num) - deg(den) = ",num2str(m-l), ...
+	"; coefficients must be shifted"]);
+  endif
+  c = sys.num;
+  tsam = sys.tsam;
+  input = sys.inname;
+  output = sys.outname;
+endfunction
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/sys2ss.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,76 @@
+# Copyright (C) 1996, 1998 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [a,b,c,d,tsam,n,nz,stname,inname,outname,yd] = sys2ss(sys)
+  # function [a,b,c,d(,tsam,n,nz,stname,inname,outname,yd)] = sys2ss(sys)
+  # Convert from system data structure to state space form
+  # inputs:
+  #    sys: system data structure for the state space system
+  #
+  #      x' = Ax + Bu
+  #      y  = Cx + Du
+  #
+  #  or a similar discrete-time system.  
+  #
+  # outputs:
+  #    a,b,c,d: state space matrices for sys
+  #    tsam: sampling time of sys (0 if continuous)
+  #    n, nz: number of continuous, discrete states (discrete states come
+  #          last in state vector x)
+  #    stname, inname, outname: signal names (strings);  names of states,
+  #          inputs, and outputs, respectively
+  #    yd: binary vector; yd(ii) is nonzero if output y is discrete.
+  # 
+  # A warning message is printed if the system is a mixed 
+  # continuous/discrete system.
+
+  # Written by David Clem August 19, 1994
+  # Updates by John Ingram July 14, 1996
+  # $Revision: 1.4 $
+
+  if(nargin != 1)
+    usage("[a,b,c,d,tsam,n,nz,stname,inname,outname,yd] = sys2ss(sys)")
+  endif
+
+  if (nargout > 11)
+    warning(["sys2ss: ",num2str(nargout)," out arguments exceeds max=11"])
+    usage("[a,b,c,d,tsam,n,nz,stname,inname,outname,yd] = sys2ss(sys)")
+  endif
+
+  if( ! is_struct(sys) )
+    error("input argument must be a system data structure");
+  endif
+
+  sys = sysupdate(sys,"ss");		#make sure ss is up to date
+
+  cont = sum(sys.yd == 0) + sys.n;
+  dig = sum(sys.yd != 0) + sys.nz + sys.tsam;
+  if(cont*dig)
+    warning("sys2ss: input system is mixed continuous/discrete");
+  endif
+
+  a = sys.a;
+  b = sys.b;
+  c = sys.c;
+  d = sys.d;
+  [n,nz,m,p] = sysdimensions(sys);
+  [stname,inname,outname,yd] = sysgetsignals(sys);
+  tsam = sysgettsam(sys);
+
+endfunction
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/sys2tf.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,58 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [num,den,tsam,inname,outname] = sys2tf(Asys)
+# function [num,den,tsam,inname,outname] = sys2tf(Asys)
+# Conversion from a system data structure format to a transfer function.  The 
+# transfer function part of ASYS is returned to the user in the form:
+#
+#                num(s)
+#          G(s)=-------
+#                den(s)
+#
+# The user can also have the sampling time (TSAM), the name of the input 
+# (INNAME), and the output name (OUTNAME)
+
+# Written by R. Bruce Tenison (June 24, 1994) btenison@eng.auburn.edu
+# modified to make sys2tf by A. S. Hodel Aug 1995
+# modified again for updated system format by John Ingram July 1996
+# $Revision: 1.2 $
+
+  if(nargin != 1)
+    usage("[num,den,tsam,inname,outname] = sys2tf(Asys)");
+  endif
+
+  if( !is_struct(Asys))
+    error("Asys must be a system data structure (see ss2sys, tf2sys, zp2sys)");
+  elseif (! is_siso(Asys) )
+    [n, nz, m, p] = sysdimensions(Asys);
+    error(["system is not SISO (",num2str(m)," inputs, ...
+        ", num2str(p)," outputs"]);
+  endif
+
+  Asys = sysupdate(Asys,"tf");		# just in case
+
+  num = Asys.num;
+  den = Asys.den;
+  
+  tsam = Asys.tsam;
+  inname = Asys.inname;
+  outname = Asys.outname;
+
+endfunction
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/sys2zp.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,56 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [zer,pol,k,tsam,inname,outname] = sys2zp(sys)
+# [zer,pol,k,tsam,inname,outname] = sys2zp(sys)
+# extract zero/pole/leading coefficient information from a system data
+# structure
+# inputs: sys: system data structure
+# outputs:
+#   zer: vector of system zeros
+#   pol: vector of system poles
+#   k: scalar leading coefficient
+#   tsam: sampling period. default: 0 (continuous system)
+#   inname, outname: input/output signal names (strings)
+
+# Created by John Ingram July 15 1996
+# $Revision: 1.2 $
+
+  if(nargin != 1)
+    usage("[zer,pol,k,tsam,inname,outname] = sys2zp(sys)");
+  elseif( !is_struct(sys))
+    error("sysconnect: sys must be in system data structure form")
+  elseif (! is_siso(sys) )
+    [n, nz, m, p] = sysdimensions(sys);
+    error(["system is not SISO (",num2str(m)," inputs, ...
+	", num2str(p)," outputs"]);
+  endif
+
+  # update zero-pole form
+  sys = sysupdate(sys,"zp");
+
+  zer = sys.zer;
+  pol = sys.pol;
+  k = sys.k;
+  tsam = sys.tsam;
+  inname = sys.inname;
+  outname = sys.outname;
+
+endfunction
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/sysadd.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,97 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function sys = sysadd(Gsys,Hsys)
+# 
+# [sys] = sysadd(Gsys,Hsys)
+#
+#
+# returns transfer function sys = Gsys + Hsys
+#
+# Method: Gsys and Hsys are connected in parallel
+# The vector are connected to both systems; the outputs will be 
+# added.  The names given to the system will be the G systems names.
+#
+#                  ________
+#             ----|  Gsys  |---
+#        u   |    ----------  +|         
+#        -----                (_)----> y
+#            |     ________   +|
+#             ----|  Hsys  |---
+#                  --------
+
+# Written by John Ingram July 1996
+# $Revision: 1.2 $
+
+  save_val = implicit_str_to_num_ok;	# save for later
+  implicit_str_to_num_ok = 1;
+
+  if(nargin != 2)
+    usage("sysadd:  [sys] = sysysadd(Gsys,Hsys)");
+  endif
+
+  # check inputs
+  if(!is_struct(Gsys) | !is_struct(Hsys))
+    error("Both Gsys and Hsys must be in system data structure form");
+  endif
+
+  # check for compatibility
+  [n,nz,mg,pg] = sysdimensions(Gsys);
+  [n,nz,mh,ph] = sysdimensions(Hsys);
+  if(mg != mh)
+    error(sprintf("Gsys inputs(%d) != Hsys inputs (%d)",mg,mh));
+  elseif(pg != ph)
+    error(sprintf("Gsys outputs(%d) != Hsys outputs (%d)",pg,ph));
+  endif
+
+  [Gst, Gin, Gout, Gyd] = sysgetsignals(Gsys);
+  [Hst, Hin, Hout, Hyd] = sysgetsignals(Hsys);
+
+  # check for digital to continuous addition
+  if (Gyd != Hyd)
+    error("can not add a discrete output to a continuous output");
+  endif
+
+  if( (Gsys.sys(1) == 0) | (Hsys.sys(1) == 0) )
+    # see if adding  transfer functions with identical denominators
+    Gsys = sysupdate(Gsys,"tf");
+    Hsys = sysupdate(Hsys,"tf");
+    if(Hsys.den == Gsys.den)
+      sys = Gsys;
+      sys.sys(1) = 0;
+      sys.num = sys.num + Hsys.num;
+      return
+    endif
+  endif
+
+  # make sure in ss form
+  Gsys = sysupdate(Gsys,"ss");
+  Hsys = sysupdate(Hsys,"ss");
+
+  sys = sysgroup(Gsys,Hsys);
+
+  eyin = eye(mg);
+  eyout = eye(pg);
+
+
+  inname = Gin;
+  outname = Gout;
+
+  sys = sysscale(sys,[eyout eyout],[eyin;eyin],outname,inname);
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/sysappend.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,202 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function retsys = sysappend(sys,b,c,d,outname,inname,yd)
+  # 
+  # function retsys = sysappend(sys,b[,c,d,outname,inname,yd])
+  #
+  # This function appends new inputs and/or outputs to a system
+  # Inputs:
+  #	sys:  system data structure
+  #	b: matrix to be appended to sys "B" matrix (empty if none)
+  #	c: matrix to be appended to sys "C" matrix (empty if none)
+  #     d: revised sys d matrix (can be passed as [] if the revised d is all 
+  #        zeros)
+  #     outname: names for new outputs
+  #     inname: names for new inputs
+  #     yd: indicator for which new outputs are continuous/discrete 
+  #         (yd(i) = 0 or , respectively)
+  # result:
+  #   sys.b := [sys.b , b]
+  #   sys.c := [sys.c  ]
+  #            [ c     ]
+  #   sys.d := [sys.d | D12 ]
+  #            [D21   | D22 ]
+  #         where D12, D21, and D22 are the appropriate dimensioned blocks
+  #         of the input parameter d.  The leading block D11 of d is ignored.
+  # If inname and outname are not given as arguments, the new inputs and 
+  # outputs are be assigned default names.  
+  # yd is a vector of length rows(c), and indicates which new outputs are
+  # discrete (yd(ii) = 1) and which are continuous (yd(ii) = 0).
+  # Default value for yd is:
+  #     sys = continuous or mixed: yd = zeros(1,rows(c))
+  #     sys = discrete:            yd = ones(1,rows(c))
+  
+  # written by John Ingram August 1996
+  # $Revision: 1.2 $
+  # $Log: sysappend.m,v $
+  # Revision 1.2  1998/07/21 14:53:09  hodelas
+  # use isempty instead of size tests; use sys calls to reduce direct
+  # access to system structure elements
+  #
+  # Revision 1.1.1.1  1998/05/19 20:24:09  jwe
+  #
+  # Revision 1.2  1997/04/09 04:36:21  scotte
+  # Fixed to properly handle new names (syschnames does not let you
+  # change the number of names any more.)  a.s.hodel@eng.auburn.edu
+  #
+  
+  save_val = implicit_str_to_num_ok;	# save for later
+  implicit_str_to_num_ok = 1;
+  
+  # check input arguments
+  if ( (nargin < 2) | (nargin > 7) | (!is_struct(sys)))
+    usage("retsys = sysappend(sys,b,c[,d,outname,inname,yd]) ");
+  endif
+  
+  # update system
+  sys = sysupdate(sys,"ss");
+  sys.sys = [2 0 0 1];
+  
+  #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)+rows(sys.c),columns(b) + rows(sys.inname));
+    #disp("sysappend: default d=")
+    #disp(d)
+    #disp("/sysappend: default d=")
+  endif
+
+  # add default input names for new inputs (if any)
+  old_m = rows(sys.inname);
+  new_m = max(columns(d),columns(b)+old_m);
+  old_inname = sys.inname;
+  if(new_m)
+    sys.inname = sysdefioname(new_m,"u");
+    if(old_m)
+      sys = syschnames(sys,"in",1:old_m,old_inname);
+    endif
+    if(nargin >= 6)
+      # input names were specified, check dimensions
+      if(rows(inname) != new_m - old_m)
+        inname
+        new_m
+        old_m
+        b
+        d
+        error(["inname has ",num2str(rows(inname))," entries, should have ", ...
+	  num2str( new_m - old_m )]);
+      endif
+      sys = syschnames(sys,"in",(old_m+1):new_m,inname);
+    endif
+  endif
+
+  #add default output names for new outputs (if any)
+  old_p = rows(sys.outname);
+  new_p = max(rows(d),rows(c)+old_p);
+
+  # default yd
+  if (nargin < 7)
+    # discrete if positive sampling time, no continuous states/outputs
+    yd = ones(1,new_p)*( ...
+         (sys.tsam > 0) & (sys.n == 0)  & isempty(find(sys.yd == 0)) ) ;
+  elseif ( (rows(c) != length(yd)) & (rows(d)) != yd)
+    error(["rows(c)=",num2str(rows(c)),", length(yd)=",num2str(length(yd))])
+  endif
+  
+  old_outname = sys.outname;
+  if(new_p)
+    sys.outname = sysdefioname(new_p,"y");
+    if(old_p)
+      sys = syschnames(sys,"out",1:old_p,old_outname); 
+    endif
+    if(nargin >= 5)
+      # output names were specified, check dimensions
+      if(rows(outname) != new_p - old_p)
+        outname
+        new_p
+        old_p
+        c
+        d
+        error(["outname has ",num2str(rows(outname)), ...
+          " entries, should have ", num2str(new_p-old_p)]);
+      endif
+      sys = syschnames(sys,"out",(old_p+1):new_p,outname);
+    endif
+  endif
+
+  sys = syschnames(sys,"yd",(old_p+1):new_p,yd);
+
+  # append new b matrix (if any)
+  if( max(size(b)) )
+    if(rows(b) != sys.n + sys.nz)
+      error(["sys has ",num2str(sys.n + sys.nz)," states; b has ", ...
+  	num2str(rows(b))," rows"]);
+    else
+      if(old_m)
+        sys.b = [sys.b,b];
+      else
+        sys.b = b;
+      endif
+    endif
+  endif
+  
+  # append new c matrix (if any)
+  if(max(size(c)))
+    if(columns(c) != sys.n + sys.nz)
+      error(["sys has ",num2str(sys.n + sys.nz)," states; c has ", ...
+  	num2str(columns(c))," columns"]);
+    else
+      if(old_p)
+        sys.c = [sys.c;c];
+      else
+        sys.c = c;
+      endif
+    endif
+  endif
+  
+  if(max(size(d)))
+    if( (rows(d) != new_p) | (columns(d) != new_m) )
+      error(["d = (",num2str(rows(d)),"x",num2str(columns(d)), ...
+  	") should be (",num2str(new_p),"x",num2str(new_m),")"]);
+    else
+      if(old_m & old_p)
+        d(1:old_p, 1:old_m) = sys.d;
+      endif
+      sys.d = d;
+    endif
+  endif
+  
+  # append new input names
+
+  retsys = sys;
+  
+  implicit_str_to_num_ok = save_val;	# restore value
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/syschnames.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,141 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function retsys = syschnames(sys,opt,list,names)
+# retsys = syschnames(sys,opt,list,names)
+# change the names of selected inputs, outputs and states.
+# inputs:
+# 	sys: system data structure
+#	opt: []: change default name (output)
+#	     "out": change selected output names
+#	     "in": change selected input names
+#	     "st": change selected state names	 
+#	     "yd": change selected outputs from discrete to continuous or 
+#		   from continuous to discrete.
+#
+#     	list: vector of indices of outputs, yd, inputs, or
+#             states whose respective names should be changed
+#
+#    	names: strings or string arrays containing
+#              names corresponding to the lists above.  To
+# 	       change yd, use a vector.  Set the name to 0 for continuous, 
+#	       or 1 for discrete.
+# outputs:
+#    retsys=sys with appropriate signal names changed 
+#            (or yd values, where appropriate)
+
+# Written by John Ingram August 1996
+# $Revision: 1.3 $
+# $Log: syschnames.m,v $
+# Revision 1.3  1998/07/17 15:31:06  hodelas
+# use is_empty instead of max(size(...))
+#
+
+  save_val = implicit_str_to_num_ok;	# save for later
+  implicit_str_to_num_ok = 1;
+
+  if (nargin != 4)
+    usage("retsys=syschnames(sys,opt,list[,names])");
+  elseif (!is_struct(sys))
+    error("sys must be a system data structure");
+  elseif (isempty(opt))
+    opt = "out";
+  elseif( ! isstr(opt) )
+    error("opt must be a string");
+  elseif( ! (strcmp(opt,"out") + strcmp(opt,"yd") + ...
+    strcmp(opt,"in") + strcmp(opt,"st") ) )
+    error("opt must be one of [], ""out"", ""yd"", ""in"", or ""st""");
+  elseif(min(size(list)) > 1)
+    disp("syschnames: list=")
+    disp(list);
+    error("list must be a vector")
+  endif
+
+  if (strcmp(opt,"out"))
+    # update output names
+    sys.outname = syschnamesl(list,sys.outname,names,"outlist");
+  elseif (strcmp(opt,"in"))
+    sys.inname = syschnamesl(list,sys.inname,names, "inlist");
+  elseif (strcmp(opt,"st"))
+    sys.stname = syschnamesl(list,sys.stname,names,"stlist");
+  else
+    # it's yd
+    ym = max(size(list));
+    ys = min(size(list));
+    maxn = rows(sys.outname);
+
+    if(ym != 0)
+      if( (ym  > maxn) | (ys != 1) )
+        error(["system has ",num2str(maxn)," outputs, ", ...
+	  "list=(",num2str(rows(list)),"x",num2str(columns(list)),")"]);
+      endif
+
+      if( ym != length(names))
+        error(["list has ",num2str(ym)," entries, and names has ",...
+		num2str(length(names))," entries."]);
+      endif
+
+      if (min((names == 1) | (names == 0)) == 0)
+        error("yd must be either zero or one");
+      endif
+
+      if (max(list) > maxn)
+        error(["The largest entry in the list is ",num2str(max(list)),...
+		" exceeds number of outputs=",num2str(maxn)])
+      endif      
+
+      if (max(names) && (sys.tsam == 0) )
+        warning("syschnames: discrete outputs with tsam=0; setting tsam=1");
+        disp("	effected outputs are:")
+        if(is_siso(sys))
+          outlist(sys.outname,"	",[],list);
+        else
+          outlist(sys.outname(list,:),"	",[],list);
+        endif
+        sys.tsam = 1;
+      endif
+
+      # reshape everything as a column vector
+      sys.yd = reshape(sys.yd,length(sys.yd),1);
+      names  = reshape(names,length(names),1);
+
+	#disp("syschnames: list=")
+	#disp(list)
+	#disp("syschnames: names=")
+	#disp(names)
+	#disp("syschnames: sys.yd=")
+	#disp(sys.yd)
+
+      sys.yd(list) = names;
+    
+      if ((min(sys.yd) == 0) && (max(sys.yd) == 0) && (sys.tsam > 0) )
+        warning("discrete states but no discrete outputs selected");
+      endif
+
+    endif
+    
+  endif
+
+  retsys = sys;
+  implicit_str_to_num_ok = save_val;	# restore value
+
+  #disp("syschnames: exiting with")
+  #retsys
+  #disp("/syschnames")
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/syschnamesl.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,133 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function old_names = syschnamesl(olist,old_names,inames,listname)
+  # used internally in syschnames
+  # olist: index list
+  # old_names: original list names
+  # inames: new names
+  # listname: name of index list
+  #
+  # combines the two string lists old_names and inames
+
+  # $Revision: 1.2 $
+  # $Log: syschnamesl.m,v $
+  # Revision 1.2  1998/07/01 16:23:39  hodelas
+  # Updated c2d, d2c to perform bilinear transforms.
+  # Updated several files per bug updates from users.
+  #
+  # Revision 1.5  1997/02/28 23:47:26  hodel
+  # fixed bug in checking parameters; (inames dimension not checked against olist)
+  # a.s.hodel@eng.auburn.edu
+  #
+  # Revision 1.4  1997/02/13 15:56:37  hodel
+  # added code to convert zeros in the name matrix to blanks
+  # a.s.hodel@eng.auburn.edu
+  #
+  # Revision 1.3  1997/02/13 15:11:17  hodel
+  # fixed bug when len_my < len_out a.s.hodel@eng.auburn.edu
+  #
+  # Revision 1.2  1997/02/12 22:54:50  hodel
+  # fixed string matrix <-> numerical matrix problem
+  #
+  
+  probstr = [];
+  if( max(olist) > rows(old_names) )
+    probstr = ["index list value(s) exceed(s) number of signals (", ...
+      num2str(rows(old_names)),")"];
+
+  elseif( length(olist) > rows(inames) )
+    probstr = ["index list dimension exceeds number of replacement names (", ...
+      num2str(rows(inames)),")"];
+
+  elseif(isempty(olist))
+    probstr = [];    # do nothing, no changes
+
+  elseif(min(size(olist)) != 1 )
+    probstr = "index list must be either a vector or an empty matrix";
+
+  elseif(max(olist) > rows(old_names))
+    probstr = ["max(",listname,")=",num2str(max(olist))," > ", ...
+	num2str(rows(old_names)),", too big"];
+
+  elseif(min(olist) < 1)
+    probstr = ["min(",listname,")=",num2str(min(olist))," < 1, too small"];
+
+  else
+    if( length(olist)  == 1)
+	len_in = columns(inames);
+	len_out = columns(old_names);
+
+      if (len_in < len_out)
+        inames(1,(len_in+1):(len_out)) = zeros(1,(len_out - len_in));
+      endif
+
+      old_names(olist,1:length(inames)) = inames;
+    elseif(length(olist) > 1)
+      for ii=1:length(olist)
+        mystr = inames(ii,:);
+	len_my = columns(mystr);
+        len_out = columns(old_names);
+       
+        if (len_my < len_out)
+          mystr(1,(len_my+1):(len_out)) = " "*ones(1,(len_out - len_my));
+	  len_my = len_out;
+        endif
+
+        old_names(olist(ii),1:len_my) = mystr;
+      endfor
+    endif
+  endif
+  if(!isempty(probstr))
+    # the following lines are NOT debugging code!
+    disp("Problem in syschnames: old names are")
+    outlist(old_names,"	")
+    disp("new names are")
+    outlist(inames,"	")
+    disp("list indices are")
+    disp(olist)
+    error(sprintf("syschnames: \"%s\" dim=(%d x %d)--\n\t%s\n", ...
+	listname, rows(olist), columns(olist),probstr));
+  endif
+
+  # change zeros  to blanks
+  if( find(old_names == 0) )
+    #disp("syschnamesl: old_names contains zeros ")
+    #old_names
+    #disp("/syschnamesl");
+
+    [ii,jj] = find(old_names == 0);
+    for idx=1:length(ii)
+      old_names(ii(idx),jj(idx)) = " ";
+    endfor
+
+    #disp("syschnamesl: old_names fixed zeros ")
+    #old_names
+    #disp("/syschnamesl");
+  endif
+
+  # just in case it's not a string anymore
+  if( !isstr(old_names) )
+    old_names = setstr(old_names);
+  endif
+  
+  #disp("syschnamesl: exit, old_names=")
+  #old_names
+  #disp("/syschnamesl: exiting")
+  
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/syschtsam.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,45 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function retsys = syschtsam(sys,tsam)
+#
+# retsys = syschtsam(sys,tsam);
+#
+# This function changes the sampling time (tsam) of the system.
+
+# Written by John Ingram August 1996
+# $Revision: 1.1.1.1 $
+
+  if (nargin != 2)
+    usage("retsys = syschtsam(sys,tsam)");
+  elseif (!is_struct(sys))
+    error("sys must be in system data structure form");
+  elseif(!is_scalar(tsam))
+    disp("syschtsam:")
+    tsam
+    error("tsam must be a scalar")
+  elseif ( ! (is_sample(tsam) | (tsam == 0) ) )
+    error("tsam must be real, scalar, and greater than zero");
+  elseif (sys.tsam == 0)
+    error("The system is continuous, use c2d to make the system discrete");
+  endif
+
+  retsys = sys;  
+  retsys.tsam = tsam;
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/sysconnect.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,270 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function sys = sysconnect(sys,output_list,input_list,order,tol)
+# function retsys = sysconnect(sys,output_list,input_list[,order,tol])
+# Close the loop from specified outputs to respective specified inputs
+# 
+# inputs:
+#   sys: system data structure
+#   output_list,input_list: list of connections indices; y(output_list(ii))
+#       is connected to u(input_list(ii)).
+#   order: logical flag (default = 0)
+#	0: leave inputs and outputs in their original order
+#	1: permute inputs and outputs to the order shown in the diagram below
+#     tol: tolerance for singularities in algebraic loops
+#	    default: 200*eps
+# output: sys: resulting closed loop system:
+#
+# Operation: sysconnect internally permutes selected inputs, outputs as shown
+# below, closes the loop, and then permutes inputs and outputs back to their
+# original order
+#                      ____________________
+#                      |                  |
+#    u_1         ----->|                  |----> y_1
+#                      |        sys       |
+#              old u_2 |                  |
+#   u_2* ------>(+)--->|                  |----->y_2 
+#   (input_list) ^     |                  |    | (output_list)
+#                |     --------------------    |
+#                |                             |
+#                -------------------------------
+#
+# The input that has the summing junction added to it has an * added to the end 
+# of the input name.
+
+# A. S. Hodel August 1995
+# modified by John Ingram July 1996
+# $Revision: 1.1.1.1 $
+# $Log: sysconnect.m,v $
+# Revision 1.1.1.1  1998/05/19 20:24:09  jwe
+#
+# Revision 1.3  1997/03/03 19:21:06  hodel
+# removed calls to packsys: a.s.hodel@eng.auburn.edu
+#
+# Revision 1.2  1997/02/13 14:23:18  hodel
+# fixed bug in continuous<->discrete loop connection check.
+# a.s.hodel@eng.auburn.edu
+#
+
+  save_val = implicit_str_to_num_ok;	# save for later
+  implicit_str_to_num_ok = 1;
+
+  if( (nargin < 3) | (nargin > 5) )
+    usage("retsys = sysconnect(sys,output_list,input_list[,order,tol])");
+  endif
+
+  # check order
+  if(nargin <= 3)
+    order = 0;
+  elseif( (order != 0) & (order != 1) )
+    error("sysconnect: order must be either 0 or 1")
+  endif
+
+  if (nargin <= 4)
+    tol = 200*eps;
+  elseif( !is_sample(tol) )
+    error("sysconnect: tol must be a positive scalar");
+  elseif(tol > 1e2*sqrt(eps))
+    warning(["sysconnect: tol set to large value=",num2str(tol), ...
+	", eps=",num2str(eps)])
+  endif
+
+  # verify sizes,format of input, output lists
+  if( min(size(output_list))*min(size(input_list)) != 1)
+    error("output_list and input_list must be vectors");
+  else
+    lo = length(output_list);
+    li = length(input_list);
+    if(lo != li)
+      error("output_list and input_list must be of the same length")
+    endif
+    
+    if(is_duplicate_entry(output_list) | is_duplicate_entry(input_list) )
+      error("duplicate entry in input_list and/or output_list");
+    endif
+  endif
+  
+  mm = rows(sys.inname);
+  pp = rows(sys.outname);
+  nn = rows(sys.stname);
+
+  if( !is_struct(sys))
+    error("sys must be in structured system form")
+  elseif(pp < li)
+    error(["length(output_list)=",num2str(li),", sys has only ", ...
+	num2str(pp),"system outputs"])
+  elseif(mm < li)
+    error(["length(input_list)=",num2str(li),", sys has only ", ...
+	num2str(mm),"system inputs"])
+  endif
+
+  # check that there are enough inputs/outputs in the system for the lists
+  if(max(input_list) > mm) 
+    error("max(input_list) exceeds the number of inputs");
+  elseif(max(output_list) > pp)
+    error("max(output_list) exceeds the number of outputs");
+  endif
+
+  output_list = reshape(output_list,1,length(output_list));
+
+  # make sure we're in state space form
+  sys = sysupdate(sys,'ss');
+
+  # permute rows and columns of B,C,D matrices into pseudo-dgkf form...
+  all_inputs = sysreorder(mm,input_list);
+  all_outputs = sysreorder(pp,output_list);
+
+  sys.b = sys.b(:,all_inputs);
+  sys.c = sys.c(all_outputs,:);
+  sys.d = sys.d(all_outputs,all_inputs);
+  sys.yd = sys.yd(all_outputs);
+
+  # m1, p1 = number of inputs, outputs that are not being connected
+  m1 = mm-li;
+  p1 = pp-li;
+
+  # m2, p2: 1st column, row of B, C that is being connected
+  m2 = m1+1;
+  p2 = p1+1;
+
+  # partition system into a DGKF-like form; the loop is closed around
+  # B2, C2
+  if(m1 > 0)
+    B1 = sys.b(:,1:m1);
+    D21= sys.d(p2:pp,1:m1);
+  endif
+  B2 = sys.b(:,m2:mm);
+  if(p1 > 0)
+    C1 = sys.c(1:p1,:);
+    D12= sys.d(1:p1,m2:mm);
+  endif
+  C2 = sys.c(p2:pp,:);
+  if(m1*p1 > 0)
+    D11= sys.d(1:p1,1:m1);
+  endif
+  D22= sys.d(p2:pp,m2:mm);
+
+  if(norm(D22))
+    warning("sysconnect: possible algebraic loop, D22 non-zero");
+    D22i = (eye(size(D22))-D22);
+    C2h = D22i\C2;
+    if(m1 > 0)
+      D21h = D22i\D21;
+    endif
+    D22h = D22i\D22;
+  else
+    C2h = C2;
+    if(m1 > 0)
+      D21h = D21;
+    endif
+    D22h = D22;
+
+  endif
+
+  # check cont state -> disc output -> cont state
+  dyi = find(sys.yd(p2:pp));
+
+  #disp("sysconnect: dyi=")
+  #dyi
+  #sys.n
+  #disp("/sysconnect");
+
+  if( (sys.n > 0) & find(dyi > 0) )
+    B2con = B2(1:sys.n,dyi);	# connection to cont states
+    C2hd = C2h(dyi,1:sys.n);	# cont states -> outputs
+  else
+    B2con = C2hd = [];
+  endif
+
+  if(max(size(B2con)) & max(size(C2hd)) )
+    if(norm(B2con*C2hd))
+      warning("sysconnect: cont-state -> disc output -> cont state derivative");
+      warning("    connection made; resulting system may not be meaningful");
+    endif
+  endif
+
+  Ac = sys.a+B2*C2h;
+  if(m1 > 0)
+    B1c = B1 + B2*D21h;
+  endif
+  B2c = B2*(eye(size(D22h)) + D22h);
+  if(p1*m1 > 0)
+    D11c = D11 + D12*D21h;
+  endif
+  if(p1 > 0)
+    C1c  = C1+D12*C2h;
+    D12c = D12*(eye(size(D22h))+D22h);
+  endif
+
+  # construct system data structure
+  if(m1 > 0)
+   Bc = [B1c B2c];
+  else
+   Bc = B2c;
+  endif
+
+  if(p1 > 0)
+    Cc = [C1c;C2h];
+  else
+    Cc = C2h;
+  endif
+
+  if(m1*p1 > 0)
+    Dc = [D11c,D12c; D21h,D22h];
+  elseif(m1 > 0)
+    Dc = [D21h, D22h];
+  elseif(p1 > 0)
+    Dc = [D12c; D22h];
+  else
+    Dc = D22h;
+  endif 
+
+  # permute rows and columns of Bc, Cc, Dc back into original order
+  Im = eye(mm,mm);
+  Pi = Im(:,all_inputs);
+  back_inputs = Pi*[1:mm]';
+
+  Ip = eye(pp,pp);
+  Po = Ip(:,all_outputs);
+  back_outputs = Po*[1:pp]';
+
+  Bc = Bc(:,back_inputs);
+  Cc = Cc(back_outputs,:);
+  Dc = Dc(back_outputs,back_inputs);
+  sys.yd = sys.yd(back_outputs);
+
+  sys.a = Ac;
+  sys.b = Bc;
+  sys.c = Cc;
+  sys.d = Dc;
+
+  for ii = 1:length(input_list)
+    strval = [dezero(sys.inname(input_list(ii),:)),"*"];
+    sys.inname(input_list(ii),(1:length(strval))) = [strval];
+  endfor
+  
+  if (sys.sys(1) == 0)
+    sysupdate(sys,'tf');
+  elseif (sys.sys(1) == 1)
+    sysupdate(sys,'zp');
+  endif
+
+  implicit_str_to_num_ok = save_val;	# restore value  
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/syscont.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,80 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [csys,Acd,Ccd] = syscont(sys)
+# function [csys,Acd,Ccd] = syscont(sys)
+# returns csys = sys with discrete states./utputs omitted.
+#
+# inputs: sys is a system data structure
+# outputs: csys is the purely continuous input/output connections of
+#               sys
+#          Acd, Ccd: connections from discrete states to continuous states,
+#               discrete states to continuous outputs, respectively.
+#
+# returns csys empty if no continuous/continous path exists
+
+# Written by John Ingram August 1996
+# $Revision: 1.2 $
+
+  save_val = implicit_str_to_num_ok;	# save for later
+  save_empty = empty_list_elements_ok;
+  empty_list_elements_ok = implicit_str_to_num_ok = 1;
+
+  if (nargin != 1)
+    usage("[csys,Acd,Ccd,Dcd] = syscont(sys)");
+  elseif (!is_struct(sys))
+    error("sys must be in system data structure form");
+  endif
+
+  sys = sysupdate(sys,"ss");
+  [n_tot,st_c,st_d,y_c,y_d] = syscont_disc(sys);	# get ranges
+
+  # assume there's nothing there; build partitions as appropriate
+  Acc = Acd = Bcc = Ccc = Ccd = Dcc = [];
+
+  if(isempty(st_c) & isempty(y_c))
+    error("syscont: expecting continous states and/or continous outputs");
+  elseif (isempty(st_c))
+    warning("syscont: no continuous states");
+  elseif(isempty(y_c))
+    warning("syscont: no continuous outputs");
+  endif
+
+  [sys_a, sys_b, sys_c, sys_d ] = sys2ss(sys);
+  [sys_stname, sys_inname, sys_outname] = sysgetsignals(sys);
+  [sys_n, sys_nz, sys_m, sys_p] = sysdimensions(sys);
+  if(!isempty(st_c))
+    Acc = sys_a(st_c,st_c);
+    stname = sys_stname(st_c, :);
+    Bcc = sys_b(st_c,:);
+    Ccc = sys_c(y_c,st_c);
+    Acd = sys_a(st_c,st_d);
+  else
+    stname=[];
+  endif
+  outname = sys_outname(y_c,:);
+  Dcc = sys_d(y_c,:);
+  Ccd = sys_c(y_c,st_d);
+  inname = sys_inname;
+  
+  csys = ss2sys(Acc,Bcc,Ccc,Dcc,0,sys_n,0,stname,inname,outname);
+
+  implicit_str_to_num_ok = save_val;	# restore value
+  empty_list_elements_ok = save_empty;
+ 
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/syscont_disc.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,45 @@
+# Copyright (C) 1996,1998 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [n_tot,st_c,st_d,y_c,y_d] = syscont_disc(sys)
+# function [n_tot,st_c,st_d,y_c,y_d] = syscont_disc(sys)
+# Used internally in syscont and sysdisc.
+#
+# inputs: sys is a system data structure
+# outputs: n_tot: total number of states
+#	   st_c: vector of continuous state indices (empty if none)
+#	   st_d: vector of discrete state indices (empty if none)
+#	   y_c: vector of continuous output indices
+#	   y_d: vector of discrete output indices
+
+# Written by A. S. Hodel (a.s.hodel@eng.auburn.edu) Feb 1997
+# $Log: syscont_disc.m,v $
+# Revision 1.2  1998/07/15 12:29:13  hodelas
+# Updated to use sysdimensions.  Removed extraneous if commands (find now
+# returns empty matrix if none found)
+#
+
+  # get ranges for discrete/continuous states and outputs
+  [nn,nz,mm,pp,yd] = sysdimensions(sys);
+  n_tot = nn + nz;
+  st_c = 1:(nn);
+  st_d = nn + (1:nz);
+  y_c = find(yd == 0);		# y_c, y_d will be empty if there are none.
+  y_d = find(yd == 1);
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/sysdefioname.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,63 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function ioname = sysdefioname(n,str,m)
+# function ioname = sysdefioname(n,str[,m])
+# return default input or output names given n, str, m
+# n is the final value, str is the string prefix, and m is start value
+# ex: ioname = sysdefioname(5,"u",3)
+#
+# returns: 	ioname = 	u_3
+#				u_4
+#				u_5
+# used internally, minimal argument checking
+
+# $Log: sysdefioname.m,v $
+
+  save_val = implicit_str_to_num_ok;	# save for later
+  implicit_str_to_num_ok = 1;
+
+  if (nargin < 2 | nargin > 3)
+    usage("ioname = sysdefioname(n,str[,m])");
+  endif
+
+  if (nargin == 2)
+    m = 1;
+  endif
+
+  jj = 1;
+
+  if(n > 0 & m > 0 & m <= n)
+    for ii = m:n
+      strval = [str,"_",num2str(ii)];
+      ioname(jj,1:length(strval)) = strval;
+      jj = jj+1;
+    endfor
+  elseif(n == 0)
+    ioname = "";
+  elseif(m > n)
+    error(["start value m=",num2str(m)," > final value n=",num2str(n),"; bad!"])
+  endif
+
+  if( !isstr(ioname) )
+    ioname = setstr(ioname);
+  endif
+
+  implicit_str_to_num_ok = save_val;	# restore value
+ 
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/sysdefstname.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,50 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function stname = sysdefstname(n,nz)
+# function stname = sysdefstname(n,nz)
+# return default state names given n, nz
+# used internally, minimal argument checking
+
+# $Revision: 1.2 $
+
+  sav_val = implicit_str_to_num_ok;
+  implicit_str_to_num_ok = 1;
+
+  stname = [];
+  if(n > 0)
+    for ii = 1:n
+      strval = ["x_",num2str(ii)];
+      stname(ii,1:length(strval)) = strval;
+    endfor
+  endif
+ 
+  # Set default names for discrete states
+  if(nz > 0)
+    for ii = (n+1):(n+nz)
+      strval = ["xd_",num2str(ii)];
+      stname(ii,1:length(strval)) = strval;
+    endfor
+  endif
+
+  if( !(isstr(stname) | (rows(stname) == 0) ) )
+    stname = setstr(stname);
+  endif
+
+  implicit_str_to_num_ok = sav_val;
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/sysdimensions.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,45 @@
+# Copyright (C) 1996,1998 A. Scottedward Hodel
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+function [n,nz,m,p,yd] = sysdimensions(sys)
+# [n,nz,m,p[,yd]] = sysdimensions(sys)
+# return the number of states, inputs, and outputs in the system sys.
+# inputs: sys: system data structure
+# outputs:
+#  n: number of continuous states
+#  nz: number of discrete states
+#  m: number of system inputs
+#  p: number of system outputs
+#  yd: is the discrete output vector: yd(ii) = 1 if output ii is sampled,
+#   				    yd(ii) = 0 if output ii is continous
+#
+# see also: sysgetsignals, sysgettsam
+
+if(nargout > 5 | nargin != 1)
+  usage("[n,nz,m,p[,yd]] = sysdimensions(sys)");
+elseif(!is_struct(sys))
+  usage("[n,nz,m,p] = sysdimensions(sys)");
+endif
+
+n = sys.n;
+nz = sys.nz;
+m = rows(sys.inname);
+p = rows(sys.outname);
+yd = sys.yd;
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/sysdisc.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,90 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [dsys,Adc,Cdc] = sysdisc(sys)
+# function [dsys,Adc,Cdc] = sysdisc(sys)
+# inputs: sys = system data structure
+# outputs:
+#    dsys: purely discrete portion of sys (returned empty if there is
+#          no purely discrete path from inputs to outputs)
+#    Adc, Cdc: connections from continuous states to discrete states/discrete
+#    outputs, respectively.
+#
+
+# $Revision: 1.1.1.1 $
+
+  save_val = implicit_str_to_num_ok;	# save for later
+  save_empty = empty_list_elements_ok;
+  empty_list_elements_ok = implicit_str_to_num_ok = 1;
+
+
+  if (nargin != 1)
+    usage("[dsys,Adc,Cdc] = sysdisc(sys)");
+  elseif (!is_struct(sys))
+    error("sys must be in system data structure form");
+  endif
+
+  sys = sysupdate(sys,"ss");
+  [n_tot,st_c,st_d,y_c,y_d] = syscont_disc(sys);	# get ranges
+
+  # assume there's nothing there; build partitions as appropriate
+  Add = Adc = Bdd = Cdd = Cdc = Ddd = [];
+  
+  if(isempty(st_d) & isempty(y_d))
+    error("sysdisc: expecting discrete states and/or continous outputs");
+  elseif (isempty(st_d))
+    warning("sysdisc: no discrete states");
+  elseif(isempty(y_d))
+    warning("sysdisc: no discrete outputs");
+  endif
+
+  if(!isempty(st_d) )
+    Add = sys.a( st_d , st_d);
+    stname = sys.stname(st_d , :);
+    Bdd = sys.b( st_d , :);
+    if(!isempty(st_c))
+      Adc = sys.a( st_d , st_c);
+    endif
+    if(!isempty(y_d))
+      Cdd = sys.c(y_d , st_d);
+    endif
+  else
+    stname = [];
+  endif
+  if(!isempty(y_d))
+    Ddd = sys.d(y_d , :);
+    outname = sys.outname(y_d , :);
+    if(!isempty(st_c))
+      Cdc = sys.c(y_d , st_c);
+    endif
+  else
+    outname=[];
+  endif
+  inname = sys.inname;
+  outlist = 1:rows(outname);
+
+  if(!isempty(outname))
+    dsys = ss2sys(Add,Bdd,Cdd,Ddd,sys.tsam,0,sys.nz,stname, ...
+	inname,outname,outlist);
+  else
+    dsys=[];
+  endif
+  implicit_str_to_num_ok = save_val;	# restore value
+  empty_list_elements_ok = save_empty;
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/sysdup.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,136 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function retsys = sysdup(Asys,output_list,input_list)
+# function retsys = sysdup(Asys,output_list,input_list)
+# Duplicate specified input/output connections of a system
+# 
+#
+# inputs:
+#   Asys: system data structure (see ss2sys)
+#   output_list,input_list: list of connections indices; 
+#       duplicates are made of y(output_list(ii)) and u(input_list(ii)).
+# output: retsys: resulting closed loop system:
+#    duplicated i/o names are appended with a "+" suffix.
+#
+# Operation: sysdup creates copies of selected inputs and outputs as
+# shown below.  u1/y1 is the set of original inputs/outputs, and 
+# u2,y2 is the set of duplicated inputs/outputs in the order specified
+# in input_list,output_list, respectively
+#                      ____________________
+#                      |                  |
+#     u1         ----->|                  |----> y1
+#                      |       Asys       |
+#                      |                  |
+#     u2 ------------->|                  |----->y2 
+#     (input_list)     |                  |      (output_list)
+#                      --------------------     
+
+# A. S. Hodel August 1995
+# modified by John Ingram July 1996
+# $Revision: 1.2 $
+
+  save_val = implicit_str_to_num_ok;	# save for later
+  implicit_str_to_num_ok = 1;
+
+  if( nargin != 3)
+    usage("retsys = sysdup(Asys,output_list,input_list)");
+  endif
+
+  if( !is_struct(Asys))
+    error("Asys must be a system data structure (see ss2sys, tf2sys, or zp2sys)")
+  endif
+
+  if (Asys.sys(4) != 1)
+    Asys = sysupdate(Asys,'ss');
+  endif
+
+  mm = rows(Asys.inname);
+  pp = rows(Asys.outname);
+
+  # first duplicate inputs
+  if(is_vector(input_list))
+    for ii=1:length(input_list);
+      Asys.b(:,mm+ii) = Asys.b(:,input_list(ii));
+      Asys.d(:,mm+ii) = Asys.d(:,input_list(ii));
+    end
+  elseif(!isempty(input_list))
+    error("input_list must be a vector or empty");
+  endif
+
+
+  # now duplicate outputs
+  osize = min(size(output_list));
+  if(osize == 1)
+    for ii=1:length(output_list);
+      Asys.c(pp+ii,:) = Asys.c(output_list(ii),:);
+      Asys.d(pp+ii,:) = Asys.d(output_list(ii),:);
+    end
+  elseif(osize != 0)
+    error("output_list must be a vector or empty");
+  endif
+  
+  yd = Asys.yd(output_list);
+  Asys.yd = [Asys.yd yd];
+
+  # give default names to the added inputs
+  for ii=(mm+1):(mm+length(input_list))
+    orig_name = Asys.inname(input_list(ii-mm),:);
+
+    #disp("sysdup: orig_name=")
+    #orig_name
+    #disp("/sysdup")
+
+    strval = [dezero(orig_name),"(dup)"];
+     
+    #disp("sysdup: strval=")
+    #strval
+    #disp("/sysdup")
+
+    Asys.inname(ii,1:length(strval)) = [strval];
+     
+    #disp("sysdup: resulting Asys.inname:")
+    #Asys.inname
+    #disp("/sysdup");
+
+  endfor
+
+  # give default names to the added outputs
+  for jj=(pp+1):(pp+length(output_list))
+    if(isstr(Asys.outname))
+      orig_name =Asys.outname;
+    else
+      orig_name = Asys.outname(output_list(jj-pp),:);
+    endif
+    strval = [dezero(orig_name),"(dup)"];
+    Asys.outname(jj,1:length(strval)) = [strval];
+
+  endfor
+
+    
+
+  if(max(size(Asys.d)) > 1 )
+    Asys.sys = [2 0 0 1];	# change default form to state space
+				# tf and zp are no longer relevant
+  endif
+
+  retsys = Asys;
+
+  implicit_str_to_num_ok = save_val;	# restore value
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/sysgetsignals.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,45 @@
+# Copyright (C) 1998 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [stname,inname,outname,yd] = sysgetsignals(sys)
+  # function [stname,inname,outname,yd] = sysgetsignals(sys)
+  # Get signal names from a system
+  # inputs:
+  #    sys: system data structure for the state space system
+  #
+  # outputs:
+  #    stname, inname, outname: signal names (strings);  names of states,
+  #          inputs, and outputs, respectively
+  #    yd: binary vector; yd(ii) is nonzero if output y is discrete.
+  # 
+
+  # Adapted from ss2sys
+
+  if(nargin != 1 | nargout > 4)
+    usage("[stname,inname,outname,yd] = sysgetsignals(sys)")
+  elseif( ! is_struct(sys) )
+    error("input argument must be a system data structure");
+  endif
+  sys = sysupdate(sys,"ss");		#make sure ss is up to date
+  yd = sys.yd;
+  stname = sys.stname;
+  inname = sys.inname;
+  outname = sys.outname;
+
+endfunction
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/sysgettsam.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,20 @@
+function T = sysgettsam(sys)
+# T = sysgettsam(sys)
+# return the sampling time of the system
+
+# $Revision: 1.3 $
+# $Log: sysdimensions.m,v $
+# Revision 1.3  1997/03/10 21:35:13  scotte
+# added debugging code (commented out)
+#
+# Revision 1.2  1997/03/10 20:42:27  scotte
+# added warning message about nargout
+#
+
+if(!is_struct(sys))
+  usage("T = sysgettsam(sys)");
+endif
+
+T = sys.tsam;
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/sysgettype.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,37 @@
+# Copyright (C) 1998 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function systype = sysgettype(sys)
+# systype = sysgetype(sys)
+# return the initial system type of the system
+# inputs:
+#   sys: system data structure
+# outputs:
+#   systype: string indicating how the structure was initially 
+#            constructed:
+#      values: "ss", "zp", or "tf"
+#
+# $Log$
+
+  if(!is_struct(sys))
+    error("sysgettype: input sys is not a structure");
+  endif
+
+  typestr = ["tf";"zp";"ss"];
+  systype = typestr(sys.sys(1) + 1, :);
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/sysgroup.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,124 @@
+# Copyright (C) 1996,1998 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function sys = sysgroup(Asys,Bsys)
+# function sys = sysgroup(Asys,Bsys)
+# Combines two system data structures into a single system
+#
+# input: Asys, Bsys: system data structures
+# output: sys: Asys and Bsys are combined into a single system:
+#
+#              __________________
+#              |    ________    |
+#     u1 ----->|--> | Asys |--->|----> y1
+#              |    --------    |
+#              |    ________    |
+#     u2 ----->|--> | Bsys |--->|----> y2
+#              |    --------    |
+#              ------------------
+#                   Ksys
+# 
+# The function also rearranges the A,B,C matrices so that the 
+# continuous states come first and the discrete states come last.
+# If there are duplicate names, the second name has a unique suffix appended
+# on to the end of the name.
+
+# A. S. Hodel August 1995
+# modified by John Ingram July 1996
+# $Revision: 1.3 $
+
+  save_val = implicit_str_to_num_ok;	# save for later
+  implicit_str_to_num_ok = 1;
+
+  save_emp = empty_list_elements_ok;
+  empty_list_elements_ok = 1;
+
+  if(nargin ~= 2)
+    usage("sys = sysgroup(Asys,Bsys)");
+  elseif( !is_struct(Asys) | !is_struct(Bsys) )
+    error("sysgroup: input arguments must both be structured systems");
+  endif
+
+  # extract information from Asys, Bsys to consruct sys
+  Asys = sysupdate(Asys,"ss");
+  Bsys = sysupdate(Bsys,"ss");
+  [n1,nz1,m1,p1] = sysdimensions(Asys);
+  [n2,nz2,m2,p2] = sysdimensions(Bsys);
+  [Aa,Ab,Ac,Ad,Atsam,An,Anz,Ast,Ain,Aout,Ayd] = sys2ss(Asys);
+  [Ba,Bb,Bc,Bd,Btsam,Bn,Bnz,Bst,Bin,Bout,Byd] = sys2ss(Bsys);
+  nA = An + Anz;
+  nB = Bn + Bnz;
+
+  if(p1*m1*p2*m2 == 0)
+    error("sysgroup: argument lacks inputs and/or outputs");
+
+  elseif((Atsam + Btsam > 0) & (Atsam * Btsam == 0) )
+    warning("sysgroup: creating combination of continuous and discrete systems")
+
+  elseif(Atsam != Btsam)
+    error(["sysgroup: Asys.tsam=", ...
+       num2str(Atsam),", Bsys.tsam=",num2str(Btsam)]);
+
+  endif
+
+  A = [Aa,zeros(nA,nB); zeros(nB,nA),Ba];
+  B = [Ab,zeros(nA,m2); zeros(nB,m1),Bb];
+  C = [Ac,zeros(p1,nB); zeros(p2,nA),Bc];
+  D = [Ad,zeros(p1,m2); zeros(p2,m1),Bd];
+  tsam = max(Atsam,Btsam);
+
+  # construct combined signal names; stnames must check for pure gain blocks
+  if(isempty(Ast))
+    stname = Bst;
+  elseif(isempty(Bst))
+    stname = Ast;
+  else
+    stname  = str2mat(Ast, Bst);
+  endif
+  inname  = str2mat(Ain, Bin);
+  outname = str2mat(Aout,Bout);
+
+  # Sort states into continous first, then discrete
+  dstates = ones(1,(nA+nB));
+  if(An)
+    dstates(1:(An)) = zeros(1,An);
+  endif
+  if(Bn)
+    dstates((nA+1):(nA+Bn)) = zeros(1,Bn);
+  endif
+  [tmp,pv] = sort(dstates);
+  A = A(pv,pv);
+  B = B(pv,:);
+  C = C(:,pv);
+  stname = stname(pv,:);
+
+  # check for duplicate signal names
+  inname = sysgroupn(inname,"input");
+  stname = sysgroupn(stname,"state");
+  outname = sysgroupn(outname,"output");
+
+  # mark discrete outputs
+  outlist = find([Ayd, Byd]);
+
+  # build new system
+  sys = ss2sys(A,B,C,D,tsam,An+Bn,Anz+Bnz,stname,inname,outname);
+
+  implicit_str_to_num_ok = save_val;	# restore value  
+  empty_list_elements_ok = save_emp;
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/sysgroupn.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,57 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function names = sysgroupn(names,kind)
+# names = sysgroupn(names)
+# locate and mark duplicate names
+#
+#  used internally in sysgroup
+
+# $Revision: 1.1 $
+
+  #disp("sysgroupn: entry")
+  #names
+  #[lmatrws,lmatcls] = size(names)
+  #disp("/sysgroupn")
+
+  # check for duplicate names
+  l = rows(names);
+  if(l > 1)
+    for ii = 1:(l-1);
+      #disp(["sysgroupn: ii=",num2str(ii)])
+      #names
+      #[lmatrws,lmatcls] = size(names)
+      #disp("/sysgroupn")
+      st1 = dezero(names(ii,:));
+      for jj = (ii+1):l
+	st2 = dezero(names(jj,:));
+        if(strcmp(st1,st2))
+          suffix = ["_",num2str(jj)];
+          warning(["sysgroup: Appending ",suffix," to duplicate ",kind,...
+		" name '",st2,"'."]);
+          strval = [st2,suffix];
+
+          #disp(["sysgroupn: length(strval)=",num2str(length(strval))]);
+	  #disp(["sysgroupn: length(st2)=",num2str(length(st2))]);
+
+	  names(jj,(1:length(strval))) = strval;
+        endif
+      endfor
+    endfor
+  endif
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/sysmult.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,92 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [sys] = sysmult(Asys,Bsys)
+#
+# [sys] = sysmult(Asys,Bsys)
+#
+# returns sys = Asys*Bsys
+#
+# This function takes two systems, Asys and Bsys, and multiplies them together.
+# This has the effect of connecting the outputs of Bsys to the inputs of Asys.
+#
+#
+#     u   ----------     ----------
+#     --->|  Bsys  |---->|  Asys  |--->
+#         ----------     ----------
+#
+# A warning occurs if there is direct feed-through
+# from an input of Bsys or a continuous state of Bsys through a discrete 
+# output of Bsys to a continuous state or output in Asys (system data structure form 
+# does not recognize discrete inputs)
+
+# Written by John Ingram July 1996
+# $Revision: 1.2 $
+
+  save_val = implicit_str_to_num_ok;	# save for later
+  implicit_str_to_num_ok = 1;
+
+  if(nargin != 2)
+    usage("sysmult:  [sys] = sysmult(Asys,Bsys)");
+  endif
+
+  # check inputs
+  if(!is_struct(Asys) | !is_struct(Bsys))
+    error("Both Asys and Bsys must be in system data structure form")
+  endif
+
+  # check for compatibility
+  [An,Anz,Am,Ap] = sysdimensions(Asys);
+  [Bn,Bnz,Bm,Bp] = sysdimensions(Bsys);
+  if(Bp != Am)
+    error(["Bsys has ",num2str(Bp)," outputs, Asys has ",num2str(Am), ...
+	" inputs; mismatch."]);
+  endif
+
+  [Aa,Ab,Ac,Ad,Atsam,An,Anz,Astname,Ainname,Aoutname,Ayd] = sys2ss(Asys);
+  [Ba,Bb,Bc,Bd,Btsam,Bn,Bnz,Bstname,Binname,Boutname,Byd] = sys2ss(Bsys);
+
+  if(Byd)
+    # check direct feed-through of inputs through discrete outputs
+    alist = find(Byd);
+    if(An)
+      bd = Ab(1:An)* Bd(alist,:);	
+      if(norm(bd,1))
+        warning("sysmult: inputs -> Bsys discrete outputs -> continous states of Asys");
+      endif
+    endif
+    # check direct feed-through of continuous state through discrete outputs
+    if(Bn)
+      bc = Ab(1:An)* Bc(alist,1:(Bn));	
+      if( norm(bc,1) )
+        warning("sysmult: Bsys states -> Bsys discrete outputs -> continuous states of Asys");
+      endif
+    endif
+  endif
+
+  sys = sysgroup(Asys,Bsys);
+
+  # connect outputs of B to inputs of A
+  sys = sysconnect(sys,Ap+(1:Bp),1:Am);
+ 
+  # now keep only  outputs of A and inputs of B
+  sys = sysprune(sys,1:Ap,Am+(1:Bm));
+
+  implicit_str_to_num_ok = save_val;	# restore value  
+endfunction  
+  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/sysout.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,143 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function retsys = sysout(sys,opt)
+# function sysout(sys[,opt])
+# print out a system data structure in desired format
+#
+# sys: system data structure
+# opt: []: primary system form (default)
+#      "ss": state space form
+#      "tf": transfer function form
+#      "zp": zero-pole form
+#      "all": all of the above
+
+# Written by A S Hodel: 1995-1996
+# $Revision: 1.2 $
+
+# save for restoring at end of routine
+save_val = implicit_str_to_num_ok;
+implicit_str_to_num_ok = 1;
+
+if( (nargin < 1) || (nargin > 2) )
+  usage("sysout(sys[,opt])");
+endif
+
+if(isempty(sys))
+  retsys = sys;
+  warning("sysout: empty system")
+  return;
+endif
+
+if(! is_struct(sys))
+  disp("sysout: input must be a system structure")
+endif
+
+# set up output type array
+farray = ["tf";"zp";"ss"];
+
+if( nargin == 1 )
+  opt = farray(sys.sys(1)+1,:);
+else
+  if( ! (strcmp(opt,"ss") + strcmp(opt,"tf") + ...
+    strcmp(opt,"zp") + strcmp(opt,"all") ) )
+    error("opt must be one of [], \"ss\", \"tf\", \"zp\", or \"all\"");
+  endif
+endif
+
+# now check output for each form:
+if( !isempty(sys.inname) )
+  disp("Input(s)")
+  outlist(sys.inname,"	")
+else
+  disp("Input(s): none");
+endif
+if ( ! isempty(sys.outname) )
+  disp("Output(s):")
+  outlist(sys.outname,"	",sys.yd)
+else
+  disp("Output(s): none");
+endif
+if(sys.tsam > 0)
+  disp(["Sampling interval: ",num2str(sys.tsam)]);
+  str = "z";
+else
+  str = "s";
+endif
+
+# transfer function form
+if( strcmp(opt,"tf") + strcmp(opt,"all") )
+  sys = sysupdate(sys,"tf");		#make sure tf is up to date
+  disp("transfer function form:")
+  tfout(sys.num,sys.den,str);
+endif
+
+if( strcmp(opt,"zp") + strcmp(opt,"all") )
+  sys = sysupdate(sys,"zp");		#make sure zp is up to date
+  disp("zero-pole form:")
+  zpout(sys.zer, sys.pol,sys.k,str)
+endif
+
+if( strcmp(opt,"ss") + strcmp(opt,"all") )
+  sys = sysupdate(sys,"ss");
+  disp("state-space form:");
+  disp([num2str(sys.n)," continuous states, ",  ...
+    num2str(sys.nz)," discrete states"]);
+  if( !isempty(sys.stname) )
+    disp("State(s):")
+    xi = (sys.n+1):(sys.n+sys.nz);
+    xd = zeros(1,rows(sys.a));
+    if(!isempty(xi))
+      xd(xi) = 1;
+    endif
+    outlist(sys.stname,"	",xd);
+  else
+    disp("State(s): none");
+  endif
+
+  # display matrix values?
+  dmat = (max( [ size(sys.a) size(sys.b) size(sys.c) size(sys.d) ] ) <= 32);
+
+  disp(sprintf("A matrix: %d x %d",rows(sys.a),columns(sys.a)))
+  if(dmat)
+    disp(sys.a)
+  endif
+
+  disp(sprintf("B matrix: %d x %d",rows(sys.b),columns(sys.b)))
+  if(dmat)
+    disp(sys.b)
+  endif
+
+  disp(sprintf("C matrix: %d x %d",rows(sys.c),columns(sys.c)))
+  if(dmat)
+    disp(sys.c)
+  endif
+  disp(sprintf("D matrix: %d x %d",rows(sys.d),columns(sys.d)))
+  if(dmat)
+    disp(sys.d)
+  endif
+endif
+
+if(nargout >= 1)
+  retsys = sys;
+endif 
+  
+# restore global variable
+implicit_str_to_num_ok = save_val;
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/sysprune.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,93 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function sys = sysprune(sys,output_list,input_list)
+# function retsys = sysprune(Asys,output_list,input_list)
+# Extract specified inputs/outputs from a system
+#
+# inputs:
+#   Asys: system data structure 
+#   output_list,input_list: list of connections indices; the new
+#       system has outputs y(output_list(ii)) and inputs u(input_list(ii)).
+#       May select as [] (empty matrix) to specify all outputs/inputs.
+#
+# output: retsys: resulting system:
+#                      ____________________
+#                      |                  |
+#     u1         ----->|                  |----> y1
+#    (input_list)      |       Asys       | (output_list)
+#                      |                  |
+#   u2 (deleted) |---->|                  |----| y2  (deleted)
+#                      |                  |    
+#                      --------------------    
+
+# A. S. Hodel August 1995
+# Updated by John Ingram 7-15-96
+# $Revision: 1.2 $
+
+  if( nargin != 3  )
+    usage("retsys = sysprune(sys,output_list,input_list)");
+  endif
+
+  # default: no action
+  if(isempty(output_list))
+    outputlist = 1:rows(sys.outname);
+  endif
+  if(isempty(input_list))
+    input_list = 1:rows(sys.inname);
+  endif
+
+  # check dimensions
+  if( !(
+	(is_vector(output_list) | isempty(output_list)) 
+	& (is_vector(input_list) | isempty(input_list)) 
+  ))
+    error("sysprune: output_list and input_list must be vectors");
+  else
+    lo = length(output_list);
+    li = length(input_list);
+    
+    if(is_duplicate_entry(output_list) || is_duplicate_entry(input_list) )
+      error("sysprune: duplicate entry in input and/or output list");
+    endif
+  endif
+  
+  m = rows(sys.inname);
+  p = rows(sys.outname);
+
+  if( !is_struct(sys))
+    error("Asys must be a system data structure (see ss2sys, tf2sys, or zp2sys)")
+  elseif(p < lo)
+    error([num2str(lo)," output_list entries, system has only ", ...
+	num2str(p)," outputs"]);
+  elseif(m < li)
+    error([num2str(li)," input_list entries, system has only ", ...
+	num2str(m)," inputs"]);
+  endif
+
+  sys = sysupdate(sys,"ss");
+
+  sys.b = sys.b(:,input_list);
+  sys.c = sys.c(output_list,:);
+  sys.d = sys.d(output_list,input_list);
+
+  sys.inname = sys.inname(input_list,:);
+  sys.outname = sys.outname(output_list,:); 
+  sys.yd = sys.yd(output_list); 
+  
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/sysreorder.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,53 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function pv = sysreorder(vlen,list)
+# function pv = sysreorder(vlen,list)
+#
+# inputs: vlen: vector length
+#         list: a subset of {1:vlen}
+# pv: a permutation vector to order elements of [1:vlen] in -list-
+#         to the end of a vector
+# used internally by sysconnect to permute vector elements to their
+# desired locations.  No user-serviceable parts inside; do not attempt
+# to use this at home!
+
+# A. S. Hodel, Aug 1995
+# $Revision: 1.1.1.1 $
+  
+  #disp('sysreorder: entry')
+  
+  pv = 1:vlen;
+  # make it a row vector
+  list = reshape(list,1,length(list));
+  A = pv'*ones(size(list));
+  B = ones(size(pv'))*list;
+  X = (A != B);
+  if(!is_vector(X))
+    y = min(X');
+  else
+   y = X';
+  endif
+  z = find(y == 1);
+  if(!isempty(z))
+    pv = [z, list];
+  else
+    pv = list;
+  endif
+  
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/sysrepdemo.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,473 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function sysrepdemo()
+
+# Octave Controls toolbox demo: System representation
+
+# Written by A. S. Hodel June 1995
+# Revised Aug 1995 for system data structure format
+
+# $Revision: 1.1.1.1 $
+# $Log: sysrepdemo.m,v $
+# Revision 1.1.1.1  1998/05/19 20:24:09  jwe
+#
+# Revision 1.4  1997/02/13 15:38:26  hodel
+# fixed misprint in zp2sys demo (needed empty zeros vector in option 3)
+#
+# Revision 1.3  1997/02/13 15:22:32  hodel
+# fixed typo in menu option
+#
+# Revision 1.2  1997/02/12 11:53:22  hodel
+# *** empty log message ***
+#
+# Revision 1.1  1997/02/12 11:35:14  hodel
+# Initial revision
+#
+
+  save_val = page_screen_output;
+  page_screen_output = 1;
+
+  disp('System representation demo:')
+  num = [5 -1];
+  denom = [1 -2 6];
+  a = b = c = [];
+  syschoice = -1;
+  ch_init = 2;
+  ch_extract = ch_init+1;
+  ch_update = ch_extract+1;
+  ch_view = ch_update+1;
+  ch_details = ch_view+1;
+  ch_quit = ch_details+1;
+  while(syschoice != ch_quit)
+   disp(" ")
+    syschoice = menu('Octave System Representation Menu', ...
+      "General overview of system representation (DO THIS FIRST)", ...
+      "Initialize a system (ss2sys, tf2sys, zp2sys)", ...
+      "Extract data from a system(sys2ss, sys2tf, sys2zp)", ...
+      "Update internal representation (sysupdate)", ...
+      "View the internal contents of a system (sysout)", ...
+      "Details of internal representation", ...
+      "Return to main menu");
+    if(syschoice == 1)  # general overview
+      disp("The Octave Control Systems Toolbox (OCST) was designed to")
+      disp("provide a simple user interface to a powerful set of tools.")
+      disp(' ')
+      disp('               ----------')
+      disp(' input(s) ---->| System | ---> output(s) ')
+      disp('               ----------')
+      disp(' ')
+      disp("Like other computer-aided control system design tools, the OCST")
+      disp("enables users to enter their descriptions of dynamic systems in ")
+      disp("their preferred form (state space, transfer function, or ");
+      disp("zero-pole format).  ");
+      disp("The OCST stores system descriptions in a single variable data ");
+      disp("structure that allows for continuous time, discrete-time, or mixed ");
+      disp("(sampled-data) systems.  ");
+      disp(" ");
+      disp("This single variable description of dynamic systems greatly simplifies ");
+      disp("both the code of the OCST as well as the user interface, since only")
+      disp("one variable is passed per system, regardless of the  internal ")
+      disp("representation used in the data structure.  As a result, the ");
+      disp("likelihood of user error is greatly reduced when calling OCST")
+      disp("functions.  Further, all OCST functions have been written to")
+      disp("provide meaningful warning or error message to assist the user")
+      disp("in correcting their programming errors while using the OCST.")
+      disp("The details of the internal representation can be seen in ");
+      disp(["menu option ",num2str(ch_details)]);
+      disp("The data structure used in the OCST is called a \"system data structure.\"");
+      disp("A system data structure is contstructed with one of:")
+      disp("   fir2sys (FIR transfer function to system)")
+      disp("   ss2sys (state space matrices to system)")
+      disp("   tf2sys (SISO transfer function to system)")
+      disp("   zp2sys (SISO zero/pole/leading coefficient to system)")
+      disp(" ")
+      disp(["These functions are discussed in in menu option ",num2str(ch_init)])
+      disp("The data in a system may be extracted using ")
+      disp("   sys2fir (FIR transfer function from system")
+      disp("   sys2ss (state space matrices from system)")
+      disp("   sys2tf (SISO transfer function from system)")
+      disp("   sys2zp (SISO zero/pole/leading coefficient from system)")
+      disp(" ")
+      disp(["These functions are discussed in menu option ", ...
+	num2str(ch_extract)]);
+      disp("Other options discussed under this menu are updating the internal")
+      disp("representation form of a system data structure with sysupdate and printing")
+      disp("the description of a dynamic system to the screen with sysout.")
+      disp(" ")
+      disp("Once the user is familiar with these commands, the rest of the ")
+      disp("OCST package will be quite easy to use.")
+    elseif(syschoice == ch_init) % Initialize
+      disp("Initialization of a system:");
+      disp(' ');
+      formopt = 0;
+      while(formopt != 4)
+      disp("Three data formats may be used to initialize a system:")
+        formopt = menu("System data structure initialization menu", ...
+		"State space form       (ss2sys)", ...
+		"Transfer function form (tf2sys)", ...
+		"zero-pole form         (zp2sys)", ...
+	    	"Return to System representation menu");
+        if(formopt == 1)
+          disp('State space representation of a system is based on the usual')
+          disp('multi-variable differential equations')
+          disp(' ')
+          disp('  . ')
+          disp('  x = A x + B u      -or -   x(k+1) = A x(k) + B u(k) ')
+          disp('  y = C x + D u                y(k) = C x(k) + D u(k) ')
+          disp(' ')
+          disp('for matrices A, B, C, D of appropriate dimension.')
+          disp(' ')
+          ssopt = 0;
+          ssquit = 5;
+          while(ssopt < ssquit)
+            ssopt = menu("State space initialization examples", ...
+		"Double integrator example", ...
+		"Double delay (discrete-time) example", ...
+		"Summing junction (D-matrix only) example", ...
+		"ss2sys details (help ss2sys)", ...
+		"return to system initialization menu", ...
+		"return to system representation main menu");
+            if(ssopt == 1)
+              disp("Example: construct a system representation of a")
+              disp("double integrator via state-space form")
+              cmd = "a = [0 1; 0 0];";
+              run_cmd
+              cmd = "b = [0 ; 1];";
+              run_cmd
+              cmd = "c = [1 0];";
+              run_cmd
+              cmd = "sys = ss2sys(a,b,c);";
+              run_cmd
+              disp("The state space form of the system is seen via sysout:")
+              cmd = "sysout(sys)";
+              run_cmd
+              disp("Notice that the Octave controls  toolbox automatically")
+              disp("assigns names to the states, inputs and outputs,")
+              disp("and that the D matrix was filled in automatically.")
+              disp("We verify that it's a double integrator via sysout:")
+              cmd = "sysout(sys,""tf"")";
+              run_cmd
+              prompt
+            elseif(ssopt == 2)
+              disp("Example: discrete-time double-delay:")
+              disp("This example is identical to the double-integrator,")
+              disp("except that it is a discrete-time system, and so has")
+              disp("a sampling interval.  We arbitrarily select T=1e-3.");
+              cmd = "a = [0 1; 0 0];";
+              run_cmd
+              cmd = "b = [0 ; 1];";
+              run_cmd
+              cmd = "c = [1 0];";
+              run_cmd
+              cmd = "sys=ss2sys(a,b,c,[],1e-3);";
+              run_cmd
+              cmd = "sysout(sys)";
+              run_cmd
+              disp("Notice that the D matrix was filled in automatically.")
+              disp("This is done if D is input as the empty matrix.")
+	      disp(" ")
+	      disp("Notice also that the output y_1 is labelled as a discrete")
+	      disp("output.  The OCST data structure keeps track of states")
+	      disp("and output signals that are produced by the discrete-time")
+	      disp("portion of a system.  Discrete states and outputs are ")
+	      disp("implemented as shown in the block diagram below:")
+	      disp(" ")
+	      disp(" ")
+	      disp("       _________   ________ x(kT)  ________________")
+	      disp("f(t)-->|sampler|-->| delay |----->|zero order hold| -->")
+	      disp("       ---------   --------        ----------------")
+	      disp(" ")
+	      disp("        ___________    _______________")
+	      disp("f(t)-->| sampler |-->|zero-order hold| --> y(discrete)")
+	      disp("        -----------    ---------------")
+	      disp(" ")
+	      disp("where f(t) is an input signal to either the output or the")
+	      disp(" discrete state.")
+	      disp(" ")
+	      disp("The OCST does not implement samplers on inputs to continuous")
+	      disp("time states (i.e., there are no samplers implicit in the B")
+	      disp("or D matrices unless there are corresponding discrete")
+              disp("outputs or states.  The OCST provides warning messages when")
+	      disp("if this convention is violated.")
+	      prompt
+            elseif(ssopt == 3)
+              disp("A summing junction that computes e(t) = r(t) - y(t) may be");
+              disp("constructed as follows:");
+              disp("First, we set the matrix D:")
+              cmd = "D = [1 -1];";
+              run_cmd
+              disp("ss2sys allows the initialization of signal and state names")
+              disp("(see option 4), so we initialize these as follows:")
+              cmd = "inname =  [\"r(t)\";\"y(t)\"];";
+              run_cmd;
+              cmd = "outname = \"e(t)\";";
+	      run_cmd
+              disp("Since the system is continous time and without states,")
+              disp("the ss2sys inputs tsam, n, and nz are all zero:")
+              cmd = "sys = ss2sys([],[],[],D,0,0,0,[],inname,outname);";
+              run_cmd
+              disp("The resulting system is:")
+              cmd = "sysout(sys)";
+              run_cmd
+              disp("A discrete-time summing block can be implemented by setting")
+	      disp("the sampling time positive:")
+              cmd = "sys = ss2sys([],[],[],D,1e-3,0,0,[],inname,outname);";
+              run_cmd
+              disp("The resulting system is:")
+              cmd = "sysout(sys)";
+              run_cmd
+              prompt
+            elseif(ssopt == 4)
+              help ss2sys
+	      disp(" ")
+	      disp(" ")
+              disp("Notice that state-space form allows a single system to have")
+              disp("both continuous and discrete-time states and to have both continuous")
+              disp("and discrete-time outputs.  Since it's fairly easy to make an")
+              disp("error when mixing systems of this form, the Octave controls")
+              disp("toolbox attempts to print warning messages whenever something")
+              disp("questionable occurs.")
+	    elseif(ssopt == 6)
+	      formopt = 4;		# return to main menu
+            endif
+          endwhile
+        elseif(formopt == 2)
+	  tfopt = 0;
+          while(tfopt < 5)
+            tfopt = menu("Transfer function initialization menu", ...
+		"Continuous time initialization" , ...
+		"Discrete time initialization" , ...
+		"User specified signal names" , ...
+		"tf2sys details (help tf2sys)", ...
+		"Return to system initialization menu", ...
+		"Return to system representation main menu");
+            if(tfopt == 1) # continuous time
+              disp("A transfer function is represented by vectors of the")
+              disp("coefficients of the numerator and denominator polynomials");
+              disp(" ")
+              disp("For example: the transfer function");
+              disp(" ");
+              num = [5 -1];
+              denom = [1 -2 6];
+              tfout(num,denom);
+              disp(" ")
+              disp("is generated by the following commands:")
+              cmd = "num = [5 -1]";
+              run_cmd
+              cmd = "denom = [1 -2 6]";
+              run_cmd
+              cmd = "sys = tf2sys(num,denom);";
+              run_cmd
+	      disp("alternatively, the system can be generated in a single command:");
+	      cmd = "sys = tf2sys([5 -1],[1 -2 6]);";
+              run_cmd
+              disp("Notice the output of sys: it is an Octave data structure.")
+              disp("The details of its member variables are explained under")
+              disp("System Representation Menu option 5 (the details of system form)")
+	      disp(" ");
+              disp("The data structure can be observed with the sysout command:")
+              cmd = "sysout(sys)";
+              run_cmd
+              disp("Notice that Octave assigns names to inputs and outputs.")
+	      disp("The user may manually select input and output names; see option 3");
+	      prompt
+            elseif(tfopt == 2) # discrete time
+              disp("A transfer function is represented by vectors of the")
+              disp("coefficients of the numerator and denominator polynomials");
+              disp("Discrete-time transfer functions require ")
+              disp("the additional parameter of a sampling period:")
+              cmd = "sys=tf2sys([5 -1],[1 2 -6],1e-3);";
+              run_cmd
+              cmd = "sysout(sys)";
+              run_cmd
+	      disp("The OCST recognizes discrete-time transfer functions and")
+	      disp("accordingly prints them with the frequency domain variable z.");
+              disp("Notice that Octave assigns names to inputs and outputs.")
+	      disp("The user may set input and output names; see option 3");
+            elseif(tfopt == 3) # user specified names
+              disp("The OCST requires all signals to have names.  The OCST assigned default");
+	      disp("names to the signals in the other examples.  We may initialize a transfer");
+	      disp("function with user-specified names as follows: Consider a simple ")
+	      disp("double-integrator model of aircraft roll dynamics with ")
+	      disp("input \"aileron angle\" and output \"theta\".  A ")
+	      disp("system for this model is generated by the command")
+	      cmd = "aircraft=tf2sys(1,[1 0 0],0,\"aileron angle\",\"theta\");";	      run_cmd
+	      disp("The sampling  time parameter 0 indicates that the system")
+	      disp("is continuous time.  A positive sampling time indicates a")
+	      disp("discrete-time system (or sampled data system).")
+	      cmd = "sysout(aircraft)";
+	      run_cmd
+	      disp("Notice that the user-selected signal names are listed.")
+	      disp("These signal names are used in OCST plots and design functions.");
+	      disp("(Run the frequency response demo to see an example of the use of ");
+	      disp("signal names in plots.)")
+	      prompt
+            elseif(tfopt == 4) # help
+              help  tf2sys
+	      prompt
+            elseif(tfopt == 6) # return to main menu
+	      formopt = 4;
+            endif
+          endwhile
+        elseif (formopt == 3)
+	  zpopt = 0;
+          while(zpopt < 5)
+            zpopt = menu("Zero-pole initialization menu", ...
+		"Continuous time initialization" , ...
+		"Discrete time initialization" , ...
+		"User specified signal names" , ...
+		"zp2sys details (help zp2sys)", ...
+		"Return to system initialization menu", ...
+		"Return to system representation main menu");
+            if(zpopt == 1) # continuous time
+              disp("A zero-pole form representation of a system includes vectors")
+              disp("of the system poles and zeros and a scalar leading coefficient.");
+              disp(" ")
+              disp("For example: the transfer function");
+              disp(" ");
+              k = 5;
+              num = [5 -1];
+              denom = [1 -2 6];
+              zpout(num,denom,k);
+              disp(" ")
+              disp("is generated by the following commands:")
+              cmd = "num = [5 -1]";
+              run_cmd
+              cmd = "denom = [1 -2 6]";
+              run_cmd
+	      cmd = "k = 5";
+	      run_cmd
+              cmd = "sys = zp2sys(num,denom,k);";
+              run_cmd
+	      disp("alternatively, the system can be generated in a single command:");
+	      cmd = "sys = zp2sys([5 -1],[1 -2 6],5);";
+              run_cmd
+              disp("Notice the output of sys: it is an Octave data structure.")
+              disp("The details of its member variables are explained under")
+              disp("System Representation Menu option 5 (the details of system form)")
+	      disp(" ");
+              disp("The data structure can be observed with the sysout command:")
+              cmd = "sysout(sys)";
+              run_cmd
+              disp("Notice that Octave assigns names to inputs and outputs.")
+	      disp("The user may manually select input and output names; see option 3");
+	      prompt
+            elseif(zpopt == 2) # discrete time
+              disp("A zero-pole form representation of a system includes vectors")
+              disp("of the system poles and zeros and a scalar leading coefficient.");
+              disp(" ")
+              disp("Discrete-time systems require the additional parameter of a sampling period:")
+              cmd = "sys=zp2sys([5 -1],[1 2 -6],5,1e-3);";
+              run_cmd
+              cmd = "sysout(sys)";
+              run_cmd
+	      disp("The OCST recognizes discrete-time transfer functions and")
+	      disp("accordingly prints them with the frequency domain variable z.");
+              disp("Notice that Octave assigns names to inputs and outputs.")
+	      disp("The user may set input and output names; see option 3");
+            elseif(zpopt == 3) # user specified names
+              disp("The OCST requires all signals to have names.  The OCST assigned default");
+	      disp("names to the signals in the other examples.  We may initialize a transfer");
+	      disp("function with user-specified names as follows: Consider a simple ")
+	      disp("double-integrator model of aircraft roll dynamics with ")
+	      disp("input \"aileron angle\" and output \"theta\".  A ")
+	      disp("system for this model is generated by the command")
+	      cmd = "aircraft=zp2sys([],[0 0],1,0,\"aileron angle\",\"theta\");";	      run_cmd
+	      disp("The sampling  time parameter 0 indicates that the system")
+	      disp("is continuous time.  A positive sampling time indicates a")
+	      disp("discrete-time system (or sampled data system).")
+	      cmd = "sysout(aircraft)";
+	      run_cmd
+	      disp("Notice that the user-selected signal names are listed.")
+	      disp("These signal names are used in OCST plots and design functions.");
+	      disp("(Run the frequency response demo to see an example of the use of ");
+	      disp("signal names in plots.)")
+	      prompt
+            elseif(zpopt == 4) # help
+              help  zp2sys
+	      prompt
+            elseif(zpopt == 6) # return to main menu
+	      formopt = 4;
+            endif
+          endwhile
+        endif
+      endwhile
+    elseif(syschoice == ch_extract)  # extract system information
+      disp("Extract information from a system data structure in a selected format:")
+      disp("The actions of operations ss2sys, tf2sys, and zp2sys are reversed by")
+      disp("respective functions sys2ss, sys2tf, and sys2zp.  The latter two");
+      disp("functions are applicable only to SISO systems.")
+      formopt = 0;
+      while(formopt != 4)
+        formopt = menu("Extract system information", ...
+		"in state space form       (sys2ss)", ...
+		"in transfer function form (sys2tf)", ...
+		"in zero pole form         (sys2zp)", ...
+		"Return to system representation menu");
+        if(formopt == 1)
+	  help sys2ss
+	elseif(formopt == 2)
+	  help sys2tf
+	elseif(formopt == 3)
+	  help sys2zp
+	endif
+	prompt
+      endwhile
+    elseif(syschoice== ch_update)
+      disp("The OCST system data structure format will store a system in the same format")
+      disp("as that with which it was initialized.  For example, consider the following:")
+      cmd = "sys=zp2sys([1 2],[3 4 5],6)";
+      run_cmd
+      disp(" ")
+      disp("Notice the internal variables in the structure include zer, pol, and k,")
+      disp("the required variables for zero-pole form.  We can update the system")
+      disp("to include state-space form as follows:")
+      cmd = "sys = sysupdate(sys,\"ss\")";
+      run_cmd
+      disp(" ")
+      disp("Now the sys data structure includes variables a, b, c, and d, as well")
+      disp("the default state names stname.  sysupdate is usually used internally in")
+      disp("the OCST, but can be used manually if desired.  A full description of")
+      disp("sysupdate is as follows:")
+      help sysupdate
+      prompt
+    elseif(syschoice == ch_view)
+      disp("The sysout command can be used to view a system in any desired format.")
+      disp("For example, consider the system created as follows:")
+      cmd = "aircraft=zp2sys(1,[0 0],1,0,\"aileron angle\",\"theta\");";	      run_cmd
+      disp("The system may be viewed in its default format (zero-pole) as follows")
+      cmd = "sysout(aircraft)";
+      run_cmd
+      disp(" ")
+      disp("The system may be viewed in state-space or transfer function form as well:")
+      cmd = "sysout(aircraft,\"ss\")";
+      run_cmd
+      cmd = "sysout(aircraft,\"tf\")";
+      run_cmd
+      disp("A complete description of sysout is below:")
+      help sysout
+      prompt
+    elseif(syschoice == ch_details)
+      packedform   
+    endif
+
+  endwhile
+  page_screen_output = save_val;
+endfunction
+    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/sysscale.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,131 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function sys = sysscale(sys,outscale,inscale,outname,inname)
+#
+# function sys = sysscale(sys,outscale,inscale[,outname,inname])
+# scale inputs/outputs of a system.
+#
+# inputs:
+#   sys: structured system
+#   outscale, inscale: constant matrices of appropriate dimension
+# output: sys: resulting open loop system:
+#
+#           -----------    -------    -----------
+#     u --->| inscale |--->| sys |--->| outscale |---> y
+#           -----------    -------    -----------
+# 
+# If the input names and output names are not given and the scaling matrices
+# are not square, then default names will be given to the inputs and/or
+# outputs.
+#
+# A warning message is printed if outscale attempts to add continuous
+# system outputs to discrete system outputs; otherwise yd is set appropriately
+
+# A. S. Hodel August 1995
+# modified by John Ingram 7-15-96
+# $Revision: 1.1.1.1 $
+
+  if( (nargin < 3) || (nargin > 5)  )
+    usage("retsys = sysscale(Asys,output_list,input_list{,inname,outname})");
+  elseif (!is_struct(sys))
+    error("sys must be a structured system");
+  endif
+ 
+  # check for omitted scales
+  if(isempty(outscale))
+    outscale = eye(rows(sys.outname)); 
+  endif 
+  if(isempty(inscale))
+    inscale = eye(rows(sys.inname));
+  endif 
+
+  # check dimensions of scaling matrices
+  if((columns(sys.b)!=rows(inscale)) & (columns(sys.d)!=rows(inscale)))
+    error('inscale is not compatible with the system inputs');
+  elseif( (columns(outscale)!=rows(sys.c)) & ...
+	(columns(outscale)!=rows(sys.d)))
+    error("outscale is not compatible with the system outputs");
+  endif
+  
+  outc = find(sys.yd==0);
+  outd = find(sys.yd==1);
+
+  #disp("sysscale: outc,outd=")
+  #disp(outc)
+  #disp(outd)
+  #disp("sysscale")
+
+  if(length(outc) & length(outd))
+    for ii = 1:rows(outscale)
+      nci = norm(outscale(ii,outc));
+      ndi = norm(outscale(ii,outd));
+
+      #disp(["sysscale: ii=",num2str(ii),", nci, ndi="])
+      #disp(nci)
+      #disp(ndi)
+      #disp("syscale")
+
+      if( nci & ndi)
+        warning(["sysscale: outscale(",num2str(ii), ...
+	  ",:) sums continuous and discrete outputs; setting output to cont"])
+        yd(ii) = 0;
+      else
+        yd(ii) = (ndi != 0);
+      endif
+  
+      #disp(["sysscale: yd(,",num2str(ii),"=",num2str(yd(ii)),": press a key"]);
+      #kbhit
+    endfor
+  else
+    yd = ones(1,rows(outscale))*( length(outd) > 0);
+  endif
+  sys.yd = yd;
+
+  sys.b = (sys.b)*inscale;
+  sys.d = (sys.d)*inscale;
+  sys.c = outscale*(sys.c);
+  sys.d = outscale*(sys.d);
+
+  if( !is_square(outscale) )
+    # strip extra output names (if any)
+    sys.outname = sys.outname(1:min(rows(outscale),columns(outscale)),:);
+    if( nargin < 4)
+      warning("sysscale: outscale not square, outname not specified");
+      warning("sysscale:  using default output names");
+      outname = sysdefioname(rows(sys.c),"y");
+    endif
+  else
+    outname = sys.outname;
+  endif
+  if( !is_square(inscale) )
+    # strip extra output names (if any)
+    sys.inname = sys.inname(1:min(rows(inscale),columns(inscale)),:);
+    if(nargin < 5)
+      warning("sysscale: inscale not square, inname not specified");
+      warning("sysscale:  using default input names");
+      inname = sysdefioname(columns(sys.b),"u");
+    endif
+  else
+    inname = sys.inname;
+  endif
+
+  sys = syschnames(sys,"out",1:rows(outname),outname);
+  sys = syschnames(sys,"in",1:rows(inname),inname);
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/syssub.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,104 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function sys = syssub(Gsys,Hsys)
+# 
+# [sys] = syssub(Gsys,Hsys)
+#
+#
+# returns transfer functin sys = Gsys - Hsys
+#
+# Method: Gsys and Hsys are connected in parallel
+# The vector are connected to both systems; the outputs will be 
+# subtracted.  The names given to the system will be the G systems names.
+#
+#                  ________
+#             ----|  Gsys  |---
+#        u   |    ----------  +|         
+#        -----                (_)----> y
+#            |     ________   -|
+#             ----|  Hsys  |---
+#                  --------
+
+# Written by John Ingram July 1996
+# $Revision: 1.1.1.1 $
+
+  save_val = implicit_str_to_num_ok;	# save for later
+  implicit_str_to_num_ok = 1;
+
+  if(nargin != 2)
+    usage("syssub:  [sys] = syssub(Gsys,Hsys)");
+  endif
+
+  # check inputs
+  if(!is_struct(Gsys) | !is_struct(Hsys))
+    error("Both Gsys and Hsys must be a system data structure");
+  endif
+
+  # check for compatibility
+  if(rows(Gsys.inname) != rows(Hsys.inname))
+    error("Gsys and Hsys must have the same number of inputs");
+  elseif(rows(Gsys.outname) != rows(Hsys.outname))
+    error("Gsys and Hsys must have the same number of outputs");
+  endif
+
+  # check for digital to continuous addition
+  if (Gsys.yd != Hsys.yd)
+    error("can not add a discrete output to a continuous output");
+  endif
+
+  if( (Gsys.sys(1) == 0) | (Hsys.sys(1) == 0) )
+    # see if adding  transfer functions with identical denominators
+    Gsys = sysupdate(Gsys,"tf");
+    Hsys = sysupdate(Hsys,"tf");
+    if(Hsys.den == Gsys.den)
+      sys = Gsys;
+      sys.sys(1) = 0;
+      sys.num = sys.num - Hsys.num;
+      return
+    endif
+  endif
+
+  # make sure in ss form
+  Gsys = sysupdate(Gsys,"ss");
+  Hsys = sysupdate(Hsys,"ss");
+
+  #disp("syssub: Gsys=")
+  #sysout(Gsys,"ss");
+  #disp("syssub: Hsys=")
+  #sysout(Hsys,"ss")
+
+  sys = sysgroup(Gsys,Hsys);
+
+  eyin = eye(columns(Gsys.b));
+  eyout = eye(rows(Gsys.c));
+
+  inname = sys.inname(1:rows(Gsys.inname) , :);
+  outname = sys.outname(1:rows(Gsys.outname) , :);
+
+  #disp("syssub: before sysscale: sys.yd=")
+  #disp(sys.yd)
+  #disp("syssub:")
+
+  sys = sysscale(sys,[eyout -eyout],[eyin;eyin],outname,inname);
+
+  #disp("syssub: sys.yd=")
+  #disp(sys.yd)
+  #disp("syssub: exiting")
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/sysupdate.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,107 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function sys = sysupdate(sys,opt)
+# function retsys = sysupdate(sys,opt)
+# Update the internal representation of a system.
+# inputs:
+#  sys: system data structure
+#  opt: string:  "tf" -> update transfer function
+#                "zp" -> update zero-pole form
+#                "ss" -> update state space form
+#                "all" -> all of the above
+# outputs: retsys: contains union of data in sys and requested data.
+#     if requested data in sys is already up to date then retsys=sys.
+#
+# conversion to tf or zp exits with an error if the system is
+# mixed continuous/digital
+#
+# see also: tf2sys, ss2sys, zp2sys, sysout, sys2ss, sys2tf, sys2zp
+
+# Written by John Ingram  7-9-96
+# $Revision: 1.1.1.1 $
+
+  # check for correct number of inputs 
+  if (nargin != 2)
+    usage("newsys = sysupdate(sys,opt)");
+  elseif(! is_struct(sys) )
+   error("1st argument must be system data structure")
+  elseif(! (strcmp(opt,"tf") + strcmp(opt,"zp") + ...
+	strcmp(opt,"ss") + strcmp(opt,"all")) )
+    error("2nd argument must be \"tf\", \"zp\", \"ss\", or \"all\"");
+  endif
+
+  # check to make sure not trying to make a SISO system out of a MIMO sys
+  if ( (strcmp(opt,"tf") + strcmp(opt,"zp") + strcmp(opt,"all")) ...
+	& (sys.sys(1) == 2) &  (! is_siso(sys) ) )
+    error("MIMO -> SISO update requested");
+  endif
+
+  # update transfer function if desired
+  if ( (strcmp(opt, "tf") + strcmp(opt,"all"))&&  (!sys.sys(2)))
+    # check to make sure the system is not discrete and continuous
+    is_digital(sys);
+
+    # if original system zero-pole
+    if (sys.sys(1) == 1)
+      [sys.num,sys.den] = zp2tf(sys.zer,sys.pol,sys.k);
+      sys.sys(2) = 1;
+    # if original system is state-space
+    elseif(sys.sys(1) == 2)
+      [sys.num,sys.den] = ss2tf(sys.a,sys.b,sys.c,sys.d);
+      sys.sys(2) = 1; 
+    endif
+  endif
+
+
+  # update zero-pole if desired
+  if ( (strcmp(opt, "zp") + strcmp(opt,"all")) && (! sys.sys(3)) )
+    # check to make sure the system is not discrete and continuous
+    is_digital(sys);
+
+    # original system is transfer function
+    if (sys.sys(1) == 0)
+      [sys.zer,sys.pol,sys.k] = tf2zp(sys.num,sys.den);
+      sys.sys(3) = 1;
+    # original system is state-space
+
+    elseif(sys.sys(1) == 2)
+      [sys.zer,sys.pol,sys.k] = ss2zp(sys.a,sys.b,sys.c,sys.d);
+      sys.sys(3) = 1; 
+    endif
+
+  endif
+
+  # update state-space if desired
+  if ( (strcmp(opt, "ss") + strcmp(opt,"all")) && (! sys.sys(4)) )
+    # original system is transfer function
+    if (sys.sys(1) == 0)
+      [sys.a,sys.b,sys.c,sys.d] = tf2ss(sys.num,sys.den);
+      sys.sys(4) = 1;
+    # original system is zero-pole
+    elseif(sys.sys(1) == 1)
+      [sys.a,sys.b,sys.c,sys.d] = zp2ss(sys.zer,sys.pol,sys.k);
+      sys.sys(4) = 1; 
+    endif
+
+    # create new state names
+    sys.stname = sysdefstname(sys.n, sys.nz);
+  endif
+  
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/tf2ss.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,92 @@
+# Copyright (C) 1996,1998 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [a,b,c,d] = tf2ss(num,den)
+  # Conversion from tranfer function to state-space.
+  # The state space system
+  #      .
+  #      x = Ax + Bu
+  #      y = Cx + Du
+  #
+  # is obtained from a transfer function
+  #
+  #                num(s)
+  #          G(s)=-------
+  #                den(s)
+  #
+  # via the function call [a,b,c,d] = tf2ss(num,den).
+  # The vector 'den' must contain only one row, whereas the vector 'num'
+  # may contain as many rows as there are outputs of the system 'y'.
+  # The state space system matrices obtained from this function will be
+  # in controllable canonical form as described in "Modern Control Theory",
+  # [Brogan, 1991].
+
+
+  # Written by R. Bruce Tenison (June 22, 1994) btenison@eng.auburn.edu
+  # mod A S Hodel July, Aug  1995
+  # $Revision: 1.1.1.1 $
+  # $Log$ 
+
+  if(nargin != 2)        error("tf2ss: wrong number of input arguments")
+  elseif(isempty(num))   error("tf2ss: empty numerator");
+  elseif(isempty(den))   error("tf2ss: empy denominator");
+  elseif(!is_vector(num)) 
+    error(sprintf("num(%dx%d) must be a vector",rows(num),columns(num)));
+  elseif(!is_vector(den)) 
+    error(sprintf("den(%dx%d) must be a vector",rows(den),columns(den)));
+  endif
+
+  # strip leading zeros from num, den
+  nz = find(num != 0);
+  if(isempty(nz)) num = 0;
+  else num = num(nz(1):length(num));         endif
+  nz = find(den != 0);
+  if(isempty(nz)) error("denominator is 0.");
+  else den = den(nz(1):length(den));         endif
+
+  # force num, den to be row vectors
+  num = vec(num)';        den = vec(den)';
+  nn = length(num);       nd = length(den);
+  if(nn > nd) error(sprintf("deg(num)=%d > deg(den)= %d",nn,nd)); endif
+
+   # Check sizes
+   if (nd == 1)      a = []; b = []; c = []; d = num(:,1) / den(1); 
+   else
+    # Pad num so that length(num) = length(den)
+    if (nd-nn > 0) num = [zeros(1,nd-nn), num]; endif
+
+    # Normalize the numerator and denominator vector w.r.t. the leading 
+    # coefficient
+    d1 = den(1);    num = num / d1;    den = den(2:nd)/d1;
+    sw = nd-1:-1:1;
+
+    # Form the A matrix
+    if(nd > 2)      a = [zeros(nd-2,1),eye(nd-2,nd-2);-den(sw)];
+    else            a = -den(sw);                                endif
+
+    # Form the B matrix
+    b = zeros(nd-1,1);           b(nd-1,1) = 1;
+
+    # Form the C matrix
+    c = num(:,2:nd)-num(:,1)*den;        c = c(:,sw);
+
+    # Form the D matrix
+    d = num(:,1);
+  endif
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/tf2sys.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,126 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function outsys = tf2sys(num,den,tsam,inname,outname)
+  #
+  # sys = tf2sys(num,den{,tsam,inname,outname})
+  # build system data structure from transfer function format data
+  # inputs:
+  #   num, den: coefficients of numerator/denominator polynomials
+  #   tsam: sampling interval. default: 0 (continuous time)
+  #   inname, outname: input/output signal names (string variables)
+  # outputs: sys = system data structure
+   
+  #  Written by R. Bruce Tenison  July 29, 1994
+  #  Name changed to TF2SYS July 1995
+  #  updated for new system data structure format July 1996
+  # $Revision: 1.4 $
+  # $Log: tf2sys.m,v $
+  # Revision 1.4  1998/08/24 15:50:30  hodelas
+  # updated documentation
+  #
+  # Revision 1.2  1998/07/01 16:23:39  hodelas
+  # Updated c2d, d2c to perform bilinear transforms.
+  # Updated several files per bug updates from users.
+  #
+  # Revision 1.2  1997/02/12 22:45:57  hodel
+  # added debugging code (commented out)
+  #
+
+  save_val = implicit_str_to_num_ok;
+  implicit_str_to_num_ok = 1;
+
+  #  Test for the correct number of input arguments
+  if ((nargin < 2) || (nargin > 5))
+    usage('outsys=tf2sys(num,den[,tsam,inname,outname])');
+    return
+  endif
+
+  # check input format 
+  if( ! ( (is_vector(num) || is_scalar(num)) && ...
+	(is_vector(den) || is_scalar(den))) )
+    error(['num (',num2str(rows(num)),'x',num2str(columns(num)), ...
+      ') and den (',num2str(rows(den)),'x',num2str(columns(den)), ...
+      ') must be vectors'])
+  endif
+  
+  # strip leading zero coefficients
+  num = tf2sysl(num);
+  den = tf2sysl(den);
+
+  if (length(num) >  length(den))
+    error([ 'number of poles (', num2str(length(den)-1), ...
+	') < number of zeros (', num2str(length(num)-1),')']);
+  endif
+
+  # check sampling interval (if any)
+  if(nargin <= 2)
+    tsam = 0;		# default
+  elseif (isempty(tsam))
+    tsam = 0;
+  endif
+  if ( (! (is_scalar(tsam) && (imag(tsam) == 0) )) || (tsam < 0) )
+    error('tsam must be a positive real scalar')
+  endif
+
+  outsys.num = num;
+  outsys.den = den;
+
+  #  Set the system vector:  active = 0(tf), updated = [1 0 0];
+  outsys.sys = [0 1 0 0];
+
+  #  Set defaults
+  outsys.tsam = tsam;
+  outsys.n = length(den)-1;
+  outsys.nz = 0;
+  outsys.yd = 0;	# assume discrete-time
+  # check discrete time
+  if(tsam > 0)
+    [outsys.n,outsys.nz] = swap(outsys.n, outsys.nz);
+    outsys.yd = 1;
+  endif
+
+  outsys.inname = sysdefioname(1,"u");
+  outsys.outname = sysdefioname(1,"y");
+  outsys.stname = sysdefstname(outsys.n,outsys.nz);
+
+  #  Set name of input
+  if (nargin > 3)
+    if (rows(inname) > 1)
+      warning(["tf2sys: ",num2str(rows(inname))," input names given, 1st used"]);
+      inname = inname(1,:);
+    endif
+    outsys.inname(1,1:length(inname)) = inname;
+  endif
+
+  #  Set name of output
+  if (nargin > 4)
+    if (rows(outname) > 1)
+      warning(["tf2sys: ",num2str(rows(outname)), ...
+	" output names given, 1st used"]);
+      outname = outname(1,:);  
+    endif
+    outsys.outname(1,1:length(outname)) = outname;  
+  endif 
+
+  #disp("tf2sys: returning")
+  #outsys
+  #disp("/tf2sys")
+  
+  implicit_str_to_num_ok = save_val;
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/tf2sysl.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,34 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function vec = tf2sysl(vec)
+# vec = tf2sysl(vec)
+#
+# used internally in tf2sys
+# strip leading zero coefficients to get the true polynomial length
+
+# $Revision: 1.1 $
+
+while( (length(vec) > 1) & (vec(1) == 0) )
+  vec = vec(2:length(vec));
+endwhile
+if(vec(1) == 0)
+  warning("tf2sys: polynomial has no nonzero coefficients!")
+endif
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/tf2zp.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,39 @@
+# Copyright (C) 1996,1998 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [zer,pol,k] = tf2zp(num,den)
+# Converts transfer functions to poles / zeros.
+#
+# [zer,pol,k] = tf2zp(num,den) returns the zeros and poles of the SISO system
+# defined by num/den.  K is a gain associated with the system zeros.
+
+# Written by A. S. Hodel, etc.
+# $Revision: 1.2 $
+# $Log: tf2zp.m,v $
+
+  if(nargin == 2)
+    if(length(den) > 1)          pol = roots(den);
+    else                         pol=[];                   endif
+    if(length(num) > 1)         zer = roots(num);
+    else                        zer=[];                    endif
+  else                    error("Incorrect number of input arguments");
+  endif
+
+  [a,b,c,d] = tf2ss(num,den);
+  [dum,k] = tzero(a,b,c,d);
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/tfout.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,65 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function tfout(num,denom,x)
+#
+# usage: tfout(num,denom[,x])
+#
+# print formatted transfer function num(s)/d(s) 
+# to the screen
+# x defaults to the string "s"
+#
+#  SEE ALSO: polyval, polyvalm, poly, roots, conv, deconv, residue, 
+#	filter, polyderiv, polyinteg, polyout
+
+# Written by A. Scottedward Hodel (scotte@eng.auburn.edu) June 1995)
+# $Revision: 1.2 $
+  
+  save_val = implicit_str_to_num_ok;
+  save_empty = empty_list_elements_ok;
+  empty_list_elements_ok = implicit_str_to_num_ok = 1;
+  
+  if (nargin < 2 ) | (nargin > 3) | (nargout != 0 ) 
+    usage("tfout(num,denom[,x])");
+  endif
+
+  if ( (!is_vector(num)) | (!is_vector(denom)) )
+    error("tfout: first two argument must be vectors");
+  endif
+  
+  if (nargin == 2)
+    x = 's';
+  elseif( ! isstr(x) )
+    error("tfout: third argument must be a string");
+  endif
+
+  numstring = polyout(num,x);
+  denomstring = polyout(denom,x);
+  len = max(length(numstring),length(denomstring));
+  if(len > 0)
+    y = strrep(blanks(len)," ","-");
+    disp(numstring)
+    disp(y)
+    disp(denomstring)
+  else
+    error('tfout: empty transfer function')
+  end
+
+  implicit_str_to_num_ok = save_val;
+  empty_list_elements_ok = save_empty;
+endfunction
--- a/scripts/control/tzero.m	Thu Nov 05 04:24:46 1998 +0000
+++ b/scripts/control/tzero.m	Fri Nov 06 16:16:31 1998 +0000
@@ -1,66 +1,130 @@
-## Copyright (C) 1996, 1997 John W. Eaton
-##
-## 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-1307, USA.
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [zer, gain] = tzero(A,B,C,D)
+  # [zer{,gain}] = tzero(A,B,C,D) -or-
+  # [zer{,gain}] = tzero(Asys)
+  # Compute transmission zeros of a continuous
+  #      .
+  #      x = Ax + Bu
+  #      y = Cx + Du
+  #
+  # or discrete
+  #      x(k+1) = A x(k) + B u(k)
+  #      y(k)   = C x(k) + D u(k)
+  #
+  # system.
+  #
+  # outputs: 
+  #   zer: transmission zeros of the system
+  #   gain: leading coefficient (pole-zero form) of SISO transfer function
+  #         returns gain=0 if system is multivariable
+  # References:
+  # Hodel, "Computation of Zeros with Balancing," 1992 Lin. Alg. Appl.
+  
+  # R. Bruce Tenison July 4, 1994
+  # A. S. Hodel Aug 1995: allow for MIMO and system data structures
+  # $Revision: 1.16 $ 
+  # $Log: tzero.m,v $
+  # Revision 1.16  1998-11-06 16:15:37  jwe
+  # *** empty log message ***
+  #
+  # Revision 1.7  1998/08/24 15:50:30  hodelas
+  # updated documentation
+  #
+  # Revision 1.4  1998/08/12 20:34:36  hodelas
+  # Updated to use system access calls instead of direct structure access
+  #
+  # Revision 1.3  1998/07/21 14:53:11  hodelas
+  # use isempty instead of size tests; use sys calls to reduce direct
+  # access to system structure elements
+  #
+  # Revision 1.2  1997/02/13 11:58:05  hodel
+  # tracked down error in zgfslv; added Log message
 
-## Usage: zr = tzero (a, b, c, d, bal)
-##
-## Compute the transmission zeros of a, b, c, d.
-##
-## bal = balancing option (see balance); default is "B".
-##
-## Needs to incorporate mvzero algorithm to isolate finite zeros.
-
-## Author: A. S. Hodel <scotte@eng.auburn.edu>
-## Created: August 1993
-## Adapted-By: jwe
-
-function zr = tzero (a, b, c, d, bal)
-
-  if (nargin == 4)
-    bal = "B";
-  elseif (nargin != 5)
-    error ("tzero: invalid number of arguments");
+  # get A,B,C,D and Asys variables, regardless of initial form
+  if(nargin == 4)
+    Asys = ss2sys(A,B,C,D);
+  elseif( (nargin == 1) && (! is_struct(A)))
+    usage("[zer,gain] = tzero(A,B,C,D) or zer = tzero(Asys)");
+  elseif(nargin != 1)
+    usage("[zer,gain] = tzero(A,B,C,D) or zer = tzero(Asys)");
+  else
+    Asys = A;
+    [A,B,C,D] = sys2ss(Asys);
   endif
 
-  [n, m, p] = abcddim (a, b, c, d);
+  Ao = Asys;			# save for leading coefficient
+  siso = is_siso(Asys);
+  digital = is_digital(Asys);	# check if it's mixed or not
+
+  # see if it's a gain block
+  if(isempty(A))
+    zer = [];
+    gain = D;
+    return;
+  endif
 
-  if (n > 0 && m > 0 && p > 0)
-    if (m != p)
-      warning ("tzero: number of inputs,outputs differ.  squaring up");
-      if (p > m)
-	warning ("       by padding b and d with zeros.");
-	b = [b, (zeros (n, p-m))];
-	d = [d, (zeros (p, p-m))];
-	m = p;
-      else
-	warning ("       by padding c and d with zeros.");
-	c = [c; (zeros (m-p, n))];
-	d = [d; (zeros (m-p, m))];
-	p = m;
-      endif
-      warning ("This is a kludge.  Try again with SISO system.");
-    endif
-    ab = [-a, -b; c, d];
-    bb = [(eye (n)), (zeros (n, m)); (zeros (p, n)), (zeros (p, m))];
-    [ab, bb] = balance (ab, bb);
-    zr = -qzval (ab, bb);
-  else
-    error ("tzero: a, b, c, d not compatible");
+  # First, balance the system via the zero computation generalized eigenvalue
+  # problem balancing method (Hodel and Tiller, Linear Alg. Appl., 1992)
+
+  Asys = zgpbal(Asys); [A,B,C,D] = sys2ss(Asys);   # balance coefficients
+  meps = 2*eps*norm([A B; C D],'fro');
+  Asys = zgreduce(Asys,meps);  [A, B, C, D] = sys2ss(Asys); # ENVD algorithm
+  if(!isempty(A))
+    # repeat with dual system
+    Asys = ss2sys(A', C', B', D');   Asys = zgreduce(Asys,meps);
+
+    # transform back
+    [A,B,C,D] = sys2ss(Asys);    Asys = ss2sys(A', C', B', D');
   endif
 
+  zer = [];			# assume none
+  [A,B,C,D] = sys2ss(Asys);
+  if( !isempty(C) )
+    [W,r,Pi] = qr([C D]');
+    [nonz,ztmp] = zgrownorm(r,meps);
+    if(nonz)
+      # We can now solve the generalized eigenvalue problem.
+      [pp,mm] = size(D);
+      nn = rows(A);
+      Afm = [A , B ; C D] * W';
+      Bfm = [eye(nn), zeros(nn,mm); zeros(pp,nn+mm)]*W';
+
+      jdx = (mm+1):(mm+nn);
+      Af = Afm(1:nn,jdx);
+      Bf = Bfm(1:nn,jdx);
+      zer = qz(Af,Bf);
+    endif
+  endif
+  
+  mz = length(zer);
+  [A,B,C,D] = sys2ss(Ao);		# recover original system
+  #compute leading coefficient
+  if ( (nargout == 2) && siso)
+    n = rows(A);
+    if ( mz == n)
+      gain = D;
+    elseif ( mz < n )
+      gain = C*(A^(n-1-mz))*B;
+    endif
+  else
+    gain = [];
+  endif
 endfunction
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/tzero2.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,65 @@
+# Copyright (C) 1993 John W. Eaton
+# 
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+function zr = tzero2 (a, b, c, d, bal)
+
+# Usage: zr = tzero2 (a, b, c, d, bal)
+#
+# Compute the transmission zeros of a, b, c, d.
+#
+# bal = balancing option (see balance); default is "B".
+#
+# Needs to incorporate mvzero algorithm to isolate finite zeros.
+
+# Written by A. S. Hodel (scotte@eng.auburn.edu) August 1993.
+# $Revision: 1.1.1.1 $
+# $Log$
+
+  if (nargin == 4)
+    bal = "B";
+  elseif (nargin != 5)
+    error ("tzero: illegal number of arguments");
+  endif
+
+  [n, m, p] = abcddim (a, b, c, d);
+
+  if (n > 0 && m > 0 && p > 0)
+    if (m != p)
+      fprintf (stderr, "tzero: number of inputs,outputs differ.  squaring up");
+      if (p > m)
+	fprintf (stderr, "       by padding b and d with zeros.");
+	b = [b, zeros (n, p-m)];
+	d = [d, zeros (p, p-m)];
+	m = p;
+      else
+	fprintf (stderr, "       by padding c and d with zeros.");
+	c = [c; zeros (m-p, n)];
+	d = [d; zeros (m-p, m)];
+	p = m;
+      endif
+      fprintf (stderr, "This is a kludge.  Try again with SISO system.");
+    endif
+    ab = [-a, -b; c, d];
+    bb = [eye (n), zeros (n, m); zeros (p, n), zeros (p, m)];
+    [ab,bb] = balance (ab, bb);
+    zr = -qz (ab, bb);
+  else
+    error ("tzero: a, b, c, d not compatible.  exiting");
+  endif
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/ugain.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,49 @@
+# Copyright (C) 1997 Kai P. Mueller
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function outsys = ugain(n)
+  # function outsys = ugain(n)
+  # Creates a system with unity gain, no states.
+  # This trivial system is sometimes needed to create arbitrary
+  # complex systems from simple systems with buildssic.
+  # Watch out if you are forming sampled systems since "ugain"
+  # does not contain a sampling period.  
+  #
+  # See also: hinfdemo (MIMO H_infinty example, Boeing 707-321 aircraft model)
+
+  # Written by Kai P. Mueller April, 1998
+  # Updates
+  # $Revision: 1.1.1.1 $
+  # $Log: ugain.m,v $
+  # Revision 1.1.1.1  1998/05/19 20:24:10  jwe
+  #
+  # Revision 1.1  1998/05/05 17:04:45  scotte
+  # Initial revision
+  #
+# Revision 1.1  1998/05/04  15:15:37  mueller
+# Initial revision
+#
+  #
+# Initial revision
+#
+
+  if((nargin != 1) || (nargout > 1))
+    usage("outsys = ugain(n)")
+  endif
+  outsys = ss2sys([],[],[],eye(n));
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/unpacksys.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,30 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [a,b,c,d] = unpacksys(syst)
+  # [a,b,c,d] = unpacksys(sys)
+  # Obsolete.  Use sys2ss instead.
+
+  # Written by David Clem August 19, 1994
+  # $Revision: 1.1.1.1 $
+
+  warning("unpacksys obsolete; calling sys2ss");
+  [a,b,c,d] = sys2ss(syst);
+
+endfunction
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/wgt1o.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,68 @@
+# Copyright (C) 1998 Kai P. Mueller
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function wsys = wgt1o(vl, vh, fc)
+# wgt10  State space description of a first order weighting function.
+#
+#     wsys = wgt1o(vl, vh, fc)
+#
+# Weighting function are needed by the H2/H_infinity design procedure.
+# These function are part of thye augmented plant P (see hinfdemo
+# for an applicattion example).
+#
+# vl = Gain @ low frequencies
+# vh = Gain @ high frequencies
+# fc = Corner frequency (in Hz, *not* in rad/sec)
+
+# Written by Kai P. Mueller September 30, 1997
+# $Revision: 1.1.1.1 $
+# $Log: wgt1o.m,v $
+# Revision 1.1.1.1  1998/05/19 20:24:10  jwe
+#
+# Revision 1.1  1998/05/05 17:04:56  scotte
+# Initial revision
+#
+# Revision 1.2  1998/05/05  09:01:22  mueller
+# comments added
+#
+# Revision 1.1  1998/05/04  15:08:46  mueller
+# Initial revision
+#
+#
+
+  if (nargin != 3)
+    usage("wsys = wgt1o(vl, vh, fc)");
+  endif
+
+  if(nargout > 1)
+    usage("wsys = wgt1o(vl, vh, fc)");
+  endif
+
+  if (vl == vh)
+      a = [];
+      b = [];
+      c = [];
+  else
+      a = [-2*pi*fc];
+      b = [-2*pi*fc];
+      c = [vh-vl];
+  endif
+  d=[vh];
+
+  wsys = ss2sys(a,b,c,d);
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/zgfmul.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,84 @@
+# Copyright (C) 1996,1998 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function y = zgfmul(a,b,c,d,x)
+  # y = zgfmul(a,b,c,d,x)
+  # 
+  # Compute product of zgep incidence matrix F with vector x.
+  # Used by zgepbal (in zgscal) as part of generalized conjugate gradient
+  # iteration.
+  #
+  # References:
+  # ZGEP: Hodel, "Computation of Zeros with Balancing," Linear algebra and
+  #    its Applications, 1993
+  # Generalized CG: Golub and Van Loan, "Matrix Computations, 2nd ed" 1989
+  
+  # A. S. Hodel July 24 1992
+  # Conversion to Octave July 3, 1994
+  # $Revision: 1.1 $
+  # $Log: zgfmul.m,v $
+# Revision 1.1  1998/11/04  14:35:42  hodel
+# Initial revision
+#
+  
+  [n,m] = size(b);
+  [p,m1] = size(c);
+  nm = n+m;
+  y = zeros(nm+p,1);
+
+  # construct F column by column
+  for jj=1:n
+    Fj = zeros(nm+p,1);
+
+    #rows 1:n: F1
+    aridx = complement(jj,find(a(jj,:) != 0)); 
+    acidx = complement(jj,find(a(:,jj) != 0));
+    bidx = find(b(jj,:) != 0);
+    cidx = find(c(:,jj) != 0);
+
+    Fj(aridx) = Fj(aridx) - 1;      # off diagonal entries of F1
+    Fj(acidx) = Fj(acidx) - 1;
+    # diagonal entry of F1
+    Fj(jj) = length(aridx)+length(acidx) + length(bidx) + length(cidx);
+    
+    if(!isempty(bidx)) Fj(n+bidx) = 1;     endif # B' incidence
+    if(!isempty(cidx)) Fj(n+m+cidx) = -1;  endif # -C incidence
+    y = y + x(jj)*Fj;   # multiply by corresponding entry of x
+  endfor
+
+  for jj=1:m
+    Fj = zeros(nm+p,1);
+    bidx = find(b(:,jj) != 0);   
+    if(!isempty(bidx)) Fj(bidx) = 1; endif     # B incidence
+    didx = find(d(:,jj) != 0);   
+    if(!isempty(didx)) Fj(n+m+didx) = 1; endif # D incidence
+    Fj(n+jj) = length(bidx) + length(didx);         # F2 is diagonal
+    y = y + x(n+jj)*Fj;   # multiply by corresponding entry of x
+  endfor
+
+  for jj=1:p
+    Fj = zeros(nm+p,1);
+    cidx = find(c(jj,:) != 0);   
+    if(!isempty(cidx)) Fj(cidx) = -1; endif  # -C' incidence
+    didx = find(d(jj,:) != 0);   
+    if(!isempty(didx)) Fj(n+didx) = 1;  endif # D' incidence
+    Fj(n+m+jj) = length(cidx) + length(didx);     # F2 is diagonal
+    y = y + x(n+m+jj)*Fj;   # multiply by corresponding entry of x
+  endfor
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/zgfslv.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,66 @@
+# Copyright (C) 1996,1998 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function x = zgfslv(n,m,p,b)
+  # x = zgfslv(n,m,p,b)
+  # solve system of equations for dense zgep problem
+  
+  # Written by A. Scotte Hodel
+  # Converted to Octave by R Bruce Tenison, July 3, 1994
+  # $Revision: 1.2 $
+  # $Log: zgfslv.m,v $
+
+  nmp = n+m+p;
+  gam1 = (2*n)+m+p;    gam2 = n+p;     gam3 = n+m;
+
+  G1 = givens(sqrt(m),-sqrt(p))';
+  G2 = givens(m+p,sqrt(n*(m+p)))';
+
+  x = b;
+
+  # 1) U1 e^n = sqrt(n)e_1^n
+  # 2) U2 e^m = sqrt(m)e_1^m
+  # 3) U3 e^p = sqrt(p)e_1^p
+  xdx1 = 1:n; xdx2 = n+(1:m); xdx3 = n+m+(1:p);
+  x(xdx1,1) = zgshsr(x(xdx1,1));
+  x(xdx2,1) = zgshsr(x(xdx2,1));
+  x(xdx3,1) = zgshsr(x(xdx3,1));
+
+  # 4) Givens rotations to reduce stray non-zero elements
+  idx1 = [n+1,n+m+1];     idx2 = [1,n+1];
+  x(idx1) = G1'*x(idx1);
+  x(idx2) = G2'*x(idx2);
+
+  # 6) Scale x, then back-transform to get x
+  en = ones(n,1);  em = ones(m,1);   ep = ones(p,1);
+  lam = [gam1*en;gam2*em;gam3*ep]; 
+  lam(1) = n+m+p; 
+  lam(n+1) = 1;       # dummy value to avoid divide by zero
+  lam(n+m+1)=n+m+p;
+
+  x = x ./ lam;       x(n+1) = 0;  # minimum norm solution
+
+  # back transform now.
+  x(idx2) = G2*x(idx2);
+  x(idx1) = G1*x(idx1);
+  x(xdx3,1) = zgshsr(x(xdx3,1));
+  x(xdx2,1) = zgshsr(x(xdx2,1));
+  x(xdx1,1) = zgshsr(x(xdx1,1));
+
+endfunction
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/zginit.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,85 @@
+# Copyright (C) 1996,1998 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function zz = zginit(a,b,c,d)
+  # zz = zginit(a,b,c,d)
+  # construct right hand side vector zz
+  # for the zero-computation generalized eigenvalue problem
+  # balancing procedure
+  # called by zgepbal
+  # References:
+  # ZGEP: Hodel, "Computation of Zeros with Balancing," Linear Algebra and
+  #              its Applications, 1993
+  # Generalized CG: Golub and Van Loan, "Matrix Computations, 2nd ed" 1989
+  
+  # A. S. Hodel July 24 1992
+  # Conversion to Octave by R. Bruce Tenison, July 3, 1994
+  # $Revision: 1.1 $
+  # $Log: zginit.m,v $
+
+  [nn,mm] = size(b);
+  [pp,mm] = size(d);
+
+  nmp = nn+mm+pp;
+
+  # set up log vector zz
+  zz = zeros(nmp,1);
+
+  # zz part 1:
+  for i=1:nn
+    # nonzero off diagonal entries of a
+    nidx = complement(i,1:nn);
+    a_row_i = a(i,nidx);                 a_col_i = a(nidx,i);
+    arnz = a_row_i(find(a_row_i != 0));  acnz = a_col_i(find(a_col_i != 0));
+
+    # row of b
+    bidx = find(b(i,:) != 0);
+    b_row_i = b(i,bidx);
+
+    # column of c
+    cidx = find(c(:,i) != 0);
+    c_col_i = c(cidx,i);
+   
+    # sum the entries
+    zz(i) = sum(log(abs(acnz))) - sum(log(abs(arnz))) ...
+            - sum(log(abs(b_row_i))) + sum(log(abs(c_col_i)));
+  endfor
+
+  # zz part 2:
+  bd = [b;d];
+  for i=1:mm
+    i1 = i+nn;
+
+    # column of [b;d]
+    bdidx = find(bd(:,i) != 0);
+    bd_col_i = bd(bdidx,i);
+    zz(i1) = sum(log(abs(bd_col_i)));
+  endfor
+
+  # zz part 3:
+  cd = [c d];
+  for i=1:pp
+    i1 = i+nn+mm;
+    cdidx = find(cd(i,:) != 0);
+    cd_row_i = cd(i,cdidx);
+    zz(i1) = -sum(log(abs(cd_row_i)));
+  endfor
+
+  # now set zz as log base 2
+  zz = zz*(1/log(2));
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/zgpbal.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,118 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [retsys] = zgpbal(Asys)
+  # function [retsys] = zgpbal(Asys)
+  #
+  # used internally in tzero; minimal argument checking performed
+  #
+  # implementation of zero computation generalized eigenvalue problem 
+  # balancing method (Hodel and Tiller, Allerton Conference, 1991)
+  # Based on Ward's balancing algorithm (SIAM J. Sci Stat. Comput., 1981)
+  #
+  # zgpbal computes a state/input/output weighting that attempts to 
+  # reduced the range of the magnitudes of the nonzero elements of [a,b,c,d]
+  # The weighting uses scalar multiplication by powers of 2, so no roundoff
+  # will occur.  
+  #
+  # zgpbal should be followed by zgpred
+  # References:
+  # ZGEP: Hodel, "Computation of Zeros with Balancing," 1992, Linear Algebra
+  # and its Applications
+  # Generalized CG: Golub and Van Loan, "Matrix Computations, 2nd ed" 1989
+  
+  # A. S. Hodel July 24 1992
+  # Conversion to Octave by R. Bruce Tenison July 3, 1994
+  # $Revision: 1.1 $
+  # $Log: zgpbal.m,v $
+# Revision 1.1  1998/11/04  14:35:42  hodel
+# Initial revision
+#
+  # Revision 1.2  1998/08/24 15:50:31  hodelas
+  # updated documentation
+  #
+  # Revision 1.1.1.1  1998/05/19 20:24:10  jwe
+  #
+  # Revision 1.2  1997/02/13 11:54:59  hodel
+  # added debugging code (commented out).
+  #
+
+  if( (nargin != 1) | (!is_struct(Asys)))
+    usage("retsys = zgpbal(Asys)");
+  endif
+
+  Asys = sysupdate(Asys,"ss");
+  [a,b,c,d] = sys2ss(Asys);
+
+  [nn,mm,pp] = abcddim(a,b,c,d);
+  
+  np1 = nn+1;
+  nmp = nn+mm+pp;
+
+  # set up log vector zz, incidence matrix ff
+  zz = zginit(a,b,c,d);
+
+  #disp("zgpbal: zginit returns")
+  #zz
+  #disp("/zgpbal")
+
+  if (norm(zz))
+    # generalized conjugate gradient approach
+    xx = zgscal(a,b,c,d,zz,nn,mm,pp);
+    
+    for i=1:nmp
+      xx(i) = floor(xx(i)+0.5);
+      xx(i) = 2.0^xx(i);
+    endfor
+    
+    # now scale a
+    # block 1: a = sigma a inv(sigma)
+    for i=1:nn
+      a(i,1:nn) = a(i,1:nn)*xx(i);
+      a(1:nn,i) = a(1:nn,i)/xx(i);
+    endfor
+    # block 2: b= sigma a phi
+    for j=1:mm
+      j1 = j+nn;
+      b(1:nn,j) = b(1:nn,j)*xx(j1);
+    endfor
+    for i=1:nn
+      b(i,1:mm) = b(i,1:mm)*xx(i);
+    endfor
+    for i=1:pp
+      i1 = i+nn+mm;
+      #   block 3: c = psi C inv(sigma)
+      c(i,1:nn) = c(i,1:nn)*xx(i1);
+    endfor
+    for j=1:nn
+      c(1:pp,j) = c(1:pp,j)/xx(j);
+    endfor
+    #   block 4: d = psi D phi
+    for j=1:mm
+      j1 = j+nn;
+      d(1:pp,j) = d(1:pp,j)*xx(j1);
+    endfor
+    for i=1:pp
+      i1 = i + nn + mm;
+      d(i,1:mm) = d(i,1:mm)*xx(i1);
+    endfor
+  endif
+  
+  retsys = ss2sys(a,b,c,d);
+endfunction
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/zgreduce.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,142 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function retsys = zgreduce(Asys,meps)
+# function retsys = zgreduce(Asys,meps)
+# implementation of procedure REDUCE in (Emami-Naeini and Van Dooren, 
+# Automatica, # 1982).
+#
+# used internally in tzero; minimal argument checking performed
+
+#$Revision: 1.1.1.1 $
+# SYS_INTERNAL accesses members of system data structure
+
+is_digital(Asys);		# make sure it's pure digital/continuous
+
+exit_1 = 0;			# exit_1 = 1 or 2 on exit of loop
+
+if(Asys.n + Asys.nz == 0)
+  exit_1 = 2;			# there are no finite zeros
+endif
+
+while (! exit_1)
+  [Q,R,Pi] = qr(Asys.d);		# compress rows of D
+  Asys.d = Q'*Asys.d;
+  Asys.c = Q'*Asys.c;
+
+  # check row norms of Asys.d
+  [sig,tau] = zgrownorm(Asys.d,meps);
+
+  #disp("=======================================")
+  #disp(["zgreduce: meps=",num2str(meps), ", sig=",num2str(sig), ...
+  #	", tau=",num2str(tau)])
+  #sysout(Asys)
+
+  if(tau == 0)
+    exit_1 = 1;		# exit_1 - reduction complete and correct
+  else
+    Cb = Db = [];
+    if(sig)
+      Cb = Asys.c(1:sig,:);
+      Db = Asys.d(1:sig,:);
+    endif
+    Ct =Asys.c(sig+(1:tau),:);
+
+    # compress columns of Ct
+    [pp,nn] = size(Ct);
+    rvec = nn:-1:1;
+    [V,Sj,Pi] = qr(Ct');
+    V = V(:,rvec);
+    [rho,gnu] = zgrownorm(Sj,meps);
+
+    #disp(["zgreduce: rho=",num2str(rho),", gnu=",num2str(gnu)])
+    #Cb
+    #Db
+    #Ct
+    #Sj'
+
+    if(rho == 0)
+      exit_1 = 1;	# exit_1 - reduction complete and correct
+    elseif(gnu == 0)
+      exit_1 = 2;	# there are no zeros at all
+    else
+      mu = rho + sig;
+
+      # update system with Q
+      M = [Asys.a , Asys.b ];
+      [nn,mm] = size(Asys.b);
+
+      pp = rows(Asys.d);
+      Vm =[V,zeros(nn,mm) ; zeros(mm,nn), eye(mm)];
+      if(sig)
+        M = [M; Cb, Db];
+        Vs =[V',zeros(nn,sig) ; zeros(sig,nn), eye(sig)];
+      else
+        Vs = V';
+      endif
+      #disp("zgreduce: before transform: M=");
+      #M
+      #Vs   
+      #Vm
+
+      M = Vs*M*Vm;
+      
+      #disp("zgreduce: after transform: M=");
+      #M
+
+      #disp("debugging code:")
+      #Mtmp = [Asys.a Asys.b; Asys.c Asys.d]
+      #Vl = [V', zeros(nn,mm); zeros(mm,nn),Q]
+      #Vr =[V,zeros(nn,mm) ; zeros(mm,nn), eye(mm)];
+      #Mtmpf = Vl*Mtmp*Vr
+
+      idx = 1:gnu;
+      jdx = nn + (1:mm);
+      sdx = gnu + (1:mu);
+
+      Asys.a = M(idx,idx);
+      Asys.b = M(idx,jdx);
+      Asys.c = M(sdx,idx);
+      Asys.d = M(sdx,jdx);
+
+      #disp(["zgreduce: resulting system: nn =",num2str(nn)," mu=",num2str(mu)])
+      #sysout(Asys)
+      #idx
+      #jdx
+      #sdx
+    endif
+  endif
+endwhile
+
+#disp(["zgreduce: while loop done: exit_1=",num2str(exit_1)]);
+
+if(exit_1 == 2)
+  # there are no zeros at all!
+  Asys.a = Asys.b = Asys.c = [];
+endif
+
+# update dimensions
+if(is_digital(Asys))
+  Asys.nz = rows(Asys.a);
+else
+  Asys.n = rows(Asys.a);
+endif
+
+retsys = Asys;
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/zgrownorm.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,35 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [sig, tau] = zgrownorm(mat,meps)
+# function [nonz, zer] = zgrownorm(mat,meps)
+# used internally in tzero
+# returns nonz = number of rows of mat whose two norm exceeds meps
+#         zer = number of rows of mat whose two norm is less than meps
+
+# $Revision: 1.1 $
+
+  rownorm = [];
+  for ii=1:rows(mat)
+    rownorm(ii) = norm(mat(ii,:));
+  endfor
+  sig = sum(rownorm > meps);
+  tau = sum(rownorm <= meps);
+
+endfunction
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/zgscal.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,107 @@
+# Copyright (C) 1996,1998 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function x = zgscal(a,b,c,d,z,n,m,p)
+  # x = zgscal(f,z,n,m,p) generalized conjugate gradient iteration to 
+  # solve zero-computation generalized eigenvalue problem balancing equation 
+  # fx=z
+  # called by zgepbal
+  #
+  # References:
+  # ZGEP: Hodel, "Computation of Zeros with Balancing," 1992, submitted to  LAA
+  # Generalized CG: Golub and Van Loan, "Matrix Computations, 2nd ed" 1989
+  
+  # A. S. Hodel July 24 1992
+  # Conversion to Octave R. Bruce Tenison July 3, 1994
+  # $Revision: 1.2 $
+
+  #**************************************************************************
+  #initialize parameters:
+  #  Givens rotations, diagonalized 2x2 block of F, gcg vector initialization
+  #**************************************************************************
+  nmp = n+m+p;
+  
+  #x_0 = x_{-1} = 0, r_0 = z
+  x = zeros(nmp,1);
+  xk1 = x;
+  xk2 = x;
+  rk1 = z;
+  k = 0;
+
+  #initialize residual error norm
+  rnorm = norm(rk1,1);
+
+  xnorm = 0;
+  fnorm = 1e-12 * norm([a,b;c,d],1);
+
+  # dummy defines for MATHTOOLS compiler
+  gamk2 = 0;      omega1 = 0;      ztmz2 = 0;
+
+  #do until small changes to x
+  len_x = length(x);
+  while ((k < 2*len_x) & (xnorm> 0.5) & (rnorm>fnorm))|(k == 0)
+    k = k+1;
+    
+    #  solve F_d z_{k-1} = r_{k-1}
+    zk1= zgfslv(n,m,p,rk1);
+
+    # Generalized CG iteration
+    # gamk1 = (zk1'*F_d*zk1)/(zk1'*F*zk1);
+    ztMz1 = zk1'*rk1;
+    gamk1 = ztMz1/(zk1'*zgfmul(a,b,c,d,zk1));
+
+    if(rem(k,len_x) == 1) omega = 1;
+    else                  omega = 1/(1-gamk1*ztMz1/(gamk2*omega1*ztmz2));
+    endif
+
+    # store x in xk2 to save space
+    xk2 = xk2 + omega*(gamk1*zk1 + xk1 - xk2);
+
+    # compute new residual error: rk = z - F xk, check end conditions
+    rk1 = z - zgfmul(a,b,c,d,xk2);
+    rnorm = norm(rk1);
+    xnorm = max(abs(xk1 - xk2));
+
+    #printf("zgscal: k=%d, gamk1=%e, gamk2=%e, \nztMz1=%e ztmz2=%e\n", ...
+    #	k,gamk1, gamk2, ztMz1, ztmz2);
+    # xk2_1_zk1 = [xk2 xk1 zk1]
+    # ABCD = [a,b;c,d]
+    # prompt
+
+    #  get ready for next iteration
+    gamk2 = gamk1;
+    omega1 = omega;
+    ztmz2 = ztMz1;
+    [xk1,xk2] = swap(xk1,xk2);
+  endwhile
+  x = xk2;
+
+  # check convergence
+  if (xnorm> 0.5 & rnorm>fnorm) 
+    warning("zgscal(tzero): GCG iteration failed; solving with pinv");
+
+    # perform brute force least squares; construct F
+    Am = eye(nmp);
+    for ii=1:nmp
+      Am(:,ii) = zgfmul(a,b,c,d,Am(:,ii));
+    endfor
+
+    # now solve with qr factorization
+    x = pinv(Am)*z;
+  endif
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/zgsgiv.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,32 @@
+# Copyright (C) 1996,1998 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [a,b] = zgsgiv(c,s,a,b)
+  # [a,b] = zgsgiv(c,s,a,b)
+  # apply givens rotation c,s to row vectors a,b
+  # No longer used in zero-balancing (zgpbal); kept for backward compatibility
+  
+  # A. S. Hodel July 29, 1992
+  # Convertion to Octave by R. Bruce Tenison July 3, 1994
+  # $Revision: 1.1.1.1 $
+
+  t1 = c*a + s*b;
+  t2 = -s*a + c*b;
+  a = t1;
+  b = t2;
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/zgshsr.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,42 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function x = zgshsr(y)
+  # x = zgshsr(y)
+  # apply householder vector based on e^(m) to 
+  # (column vector) y.
+  # Called by zgfslv
+
+  # A. S. Hodel July 24, 1992
+  # Conversion to Octave by R. Bruce Tenison July 3, 1994
+  # $Revision: 1.1.1.1 $
+
+  if(!is_vector(y))
+    error(sprintf("y(%dx%d) must be a vector",rows(y),columns(y)));
+  endif
+  x = vec(y);
+  m = length(x);
+  if (m>1)
+    beta = (1 + sqrt(m))*x(1) + sum(x(2:m));
+    beta = beta/(m+sqrt(m));
+    x(1) = x(1) - beta*(1.0d0+sqrt(m));
+    x(2:m) = x(2:m) - beta*ones(m-1,1);
+  else
+    x = -x;
+  endif
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/zp2ss.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,140 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [a,b,c,d] = zp2ss(zer,pol,k)
+# Conversion from zero / pole to state space.
+# The state space system
+#      .
+#      x = Ax + Bu
+#      y = Cx + Du
+#
+# is obtained from a vector of zeros and a vector of poles via the
+# function call [a,b,c,d] = zp2ss(zer,pol,k).  The vectors 'zer' and 
+# 'pol' may either be row or column vectors.  Each zero and pole that
+# has an imaginary part must have a conjugate in the list.
+# The number of poles must at least equal the number of zeros.
+# k is a gain that is associated with the zero vector.
+
+# Written by David Clem August 15, 1994
+# $Revision: 1.4 $
+# $Log: zp2ss.m,v $
+# Revision 1.4  1998/07/10 17:51:29  hodelas
+# Fixed bug in zp2ss system construction; overhauled zp2ssg2
+#
+#
+# calls: tf2sys, sysmult
+
+  sav_val = empty_list_elements_ok;
+  empty_list_elements_ok = 1;
+
+  if(nargin != 3)
+    error("Incorrect number of input arguments");
+  endif
+ 
+  if(! (is_vector(zer) | isempty(zer)) )
+    error(["zer(",num2str(rows(zer)),",",num2str(columns(zer)), ...
+	") should be a vector"]);
+  elseif(! (is_vector(pol) | isempty(pol) ) )
+    error(["pol(",num2str(rows(pol)),",",num2str(columns(pol)), ...
+	") should be a vector"]);
+  elseif(! is_scalar(k))
+    error(["k(",num2str(rows(k)),",",num2str(columns(k)), ...
+	") should be a scalar"]);
+  elseif( k != real(k))
+    warning("zp2ss: k is complex")
+  endif
+
+  zpsys = ss2sys([],[],[],k);
+
+  # Find the number of zeros and the number of poles
+  nzer=length(zer);
+  npol =length(pol);
+
+  if(nzer > npol)
+    error([num2str(nzer)," zeros, exceeds number of poles=",num2str(npol)]);
+  endif
+
+  # Sort to place complex conjugate pairs together
+  zer=sortcom(zer);
+  pol=sortcom(pol);
+
+  # construct the system as a series connection of poles and zeros
+  # problem: poles and zeros may come in conjugate pairs, and not
+  # matched up!
+
+  # approach: remove poles/zeros from the list as they are included in
+  # the ss system
+ 
+  while(length(pol))
+
+    # search for complex poles, zeros
+    cpol=[];    czer = [];
+    if(!isempty(pol))
+      cpol = find(imag(pol) != 0);
+    endif
+    if(!isempty(zer))
+      czer = find(imag(zer) != 0);
+    endif
+
+    if(isempty(cpol) & isempty(czer))
+      pcnt = 1;
+    else 
+      pcnt = 2;
+    endif
+
+    num=1;	# assume no zeros left.
+    switch(pcnt)
+    case(1)
+      # real pole/zero combination
+      if(length(zer))
+        num = [1 -zer(1)];  
+        zer = zer(2:length(zer));
+      endif
+      den = [1 -pol(1)];
+      pol = pol(2:length(pol));
+    case(2)
+      # got a complex pole or zero, need two roots (if available)
+      if(length(zer) > 1)
+        [num,zer] = zp2ssg2(zer);	# get two zeros
+      elseif(length(zer) == 1)
+        num = [1 -zer];			# use last zero (better be real!)
+        zer = [];
+      endif
+      [den,pol] = zp2ssg2(pol);		# get two poles
+    otherwise
+      error(["pcnt = ",num2str(pcnt)])
+    endswitch
+
+    # pack tf into system form and put in series with earlier realization
+    zpsys1 = tf2sys(num,den,0,"u","yy");
+
+    # change names to avoid warning messages from sysgroup
+    zpsys = syschnames(zpsys,"in",1,"u1");
+    zpsys1 = sysupdate(zpsys1,"ss");
+    zpsys = syschnames(zpsys,"st",(1:zpsys.n),sysdefioname(zpsys.n,"x"));
+    zpsys1 = syschnames(zpsys1,"st",(1:zpsys1.n),sysdefioname(zpsys1.n,"xx"));
+
+    zpsys = sysmult(zpsys,zpsys1);
+
+  endwhile 
+
+  [a,b,c,d] = sys2ss(zpsys);
+
+  empty_list_elements_ok = sav_val;
+endfunction
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/zp2ssg2.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,66 @@
+# Copyright (C) 1996,1998 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [poly,rvals] = zp2ssg2(rvals)
+# [poly,rvals] = zp2ssg2(rvals)
+#
+#  used internally in zp2ss
+# extract 2 values from rvals (if possible) and construct
+# a polynomial with those roots.
+
+# $Revision: 1.2 $
+# A. S. Hodel Aug 1996
+
+# locate imaginary roots (if any)
+cidx = find(imag(rvals));
+
+if(!isempty(cidx))
+  # select first complex root, omit from cidx
+  r1i = cidx(1);      r1 = rvals(r1i);     cidx = complement(r1i,cidx);
+
+  # locate conjugate root (must be in cidx list, just in case there's
+  # roundoff)
+  err = abs(rvals(cidx) - r1');
+  minerr = min(err);
+  c2i = find(err == minerr);
+  r2i = cidx(c2i);
+  r2 = rvals(r2i);
+  cidx = complement(r2i,cidx);
+
+  # don't check for divide by zero, since 0 is not complex.
+  if(abs(r2 - r1')/abs(r1) > 1e-12)
+    error(sprintf("r1=(%f,%f); r2=(%f,%f), not conjugates.", ...
+      real(r1),imag(r1),real(r2),imag(r2)));
+  endif
+
+  # complex conjugate pair
+  poly = [1, -2*real(r1), real(r1)^2+imag(r1)^2];
+else
+  # select two roots (they're all real)
+  r1 = rvals(1);
+  r2 = rvals(2);
+  poly = [1, -(r1+r2), (r1*r2)];
+  r1i = 1;  r2i = 2;
+endif
+
+# remove roots used
+idx = complement([r1i r2i],1:length(rvals));
+rvals = rvals(idx);
+
+endfunction
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/zp2sys.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,116 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function  outsys = zp2sys (zer,pol,k,tsam,inname,outname)
+  # sys = zp2sys (zer,pol,k{,tsam,inname,outname})
+  # Create system data structure from zero-pole data
+  # inputs:
+  #   zer: vector of system zeros
+  #   pol: vector of system poles
+  #   k: scalar leading coefficient
+  #   tsam: sampling period. default: 0 (continuous system)
+  #   inname, outname: input/output signal names (strings)
+  # outputs: sys: system data structure
+
+  #  Modified by John Ingram  July 20, 1996  
+  # $Revision: 1.2 $
+
+  save_val = implicit_str_to_num_ok;	# save for restoring later
+  implicit_str_to_num_ok = 1;
+
+  #  Test for the correct number of input arguments
+  if ((nargin < 3) || (nargin > 6))
+    usage("outsys = zp2sys(zer,pol,k[,tsam,inname,outname])");
+  endif
+
+  # check input format 
+  if( ! (is_vector(zer) | isempty(zer) ) )
+    error("zer must be a vector or empty");
+  endif
+  zer = reshape(zer,1,length(zer));		# make it a row vector
+
+  if( ! (is_vector(pol) | isempty(pol)))
+    error("pol must be a vector");
+  endif
+  pol = reshape(pol,1,length(pol));
+
+  if (! is_scalar(k))
+     error('k must be a scalar');
+  endif
+
+  #  Test proper numbers of poles and zeros.  The number of poles must be 
+  #  greater than or equal to the number of zeros.
+  if (length(zer) >  length(pol))
+    error(["number of poles (", num2str(length(pol)), ...
+	") < number of zeros (", num2str(length(zer)),")"]);
+  endif
+
+  #  Set the system transfer function
+  outsys.zer = zer;
+  outsys.pol = pol;
+  outsys.k = k;
+
+  #  Set the system vector:  active = 1, updated = [0 1 0];
+  outsys.sys = [1 0 1 0];
+
+  #  Set defaults
+  outsys.tsam = 0;
+   outsys.n = length(pol);
+  outsys.nz = 0;
+  outsys.yd = 0;	# assume (for now) continuous time outputs
+
+  #  Set the type of system
+  if (nargin > 3)
+    if( !is_scalar(tsam) )
+      error("tsam must be a nonnegative scalar");
+    endif
+    if (tsam < 0)
+      error("sampling time must be positve")
+    elseif (tsam > 0)
+      [outsys.n,outsys.nz] = swap(outsys.n, outsys.nz);
+      outsys.yd = 1;		# discrete-time output
+    endif
+
+    outsys.tsam = tsam;
+  endif
+
+  outsys.inname = sysdefioname(1,"u");
+  outsys.outname = sysdefioname(1,"y");
+  outsys.stname = sysdefstname(outsys.n,outsys.nz);
+
+  #  Set name of input
+  if (nargin > 4)
+    if (rows(inname) > 1)
+      warning("zp2sys: ",num2str(rows(inname))," input names given, 1st used");
+      inname = inname(1,:);
+    endif
+    outsys.inname(1,1:length(inname)) = inname;
+  endif
+
+  #  Set name of output
+  if (nargin > 5)
+    if (rows(outname) > 1)
+      warning("zp2sys: ",num2str(rows(outname)), ...
+	" output names given, 1st used");
+      outname = outname(1,:);  
+    endif
+    outsys.outname(1,1:length(outname)) = outname;  
+  endif 
+
+  implicit_str_to_num_ok = save_val;
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/zp2tf.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,67 @@
+# Copyright (C) 1996,1998 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [num,den] = zp2tf(zer,pol,k)
+# [num,den] = zp2tf(zer,pol,k)
+# Converts zeros / poles to a transfer function.
+#
+# Inputs:
+#   zer, pol: vectors of (possibly complex) poles and zeros of a transfer
+#             function.  Complex values should appear in conjugate pairs
+#   k: real scalar (leading coefficient)
+# Forms the transfer function num/den from
+# the vectors of poles and zeros.  K is a scalar gain associated with the
+# zeros.
+
+# Find out whether data was entered as a row or a column vector and
+# convert to a column vector if necessary
+# Written by A. S. Hodel with help from students Ingram, McGowan.
+# a.s.hodel@eng.auburn.edu
+# $Revision: 1.2 $
+#
+
+  [rp,cp] = size(pol);
+  [rz,cz] = size(zer);
+
+  if(!(is_vector(zer) | isempty(zer)) )
+    error(sprintf("zer(%dx%d) must be a vector",rz,cz));
+  elseif(!(is_vector(pol) | isempty(pol)) )
+    error(sprintf("pol(%dx%d) must be a vector",rp,cp));
+  elseif(length(zer) > length(pol))
+    error(sprintf("zer(%dx%d) longer than pol(%dx%d)",rz,cz,rp,cp));
+  endif
+
+  num = k;  den = 1;		# initialize converted polynomials
+
+  # call zp2ssg2 if there are complex conjugate pairs left, otherwise
+  # construct real zeros one by one.  Repeat for poles.
+  while(!isempty(zer))
+    if( max(abs(imag(zer))) )     [poly,zer] = zp2ssg2(zer);
+    else                          poly = [1 -zer(1)];  
+                                  zer = zer(2:length(zer));      endif
+    num = conv(num,poly);
+  endwhile
+
+  while(!isempty(pol))
+    if( max(abs(imag(pol))) )     [poly,pol] = zp2ssg2(pol);
+    else                          poly = [1 -pol(1)];  
+                                  pol = pol(2:length(pol));      endif
+    den = conv(den,poly);
+  endwhile
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/control/zpout.m	Fri Nov 06 16:16:31 1998 +0000
@@ -0,0 +1,112 @@
+# Copyright (C) 1996 A. Scottedward Hodel 
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function zpout(zer,pol,k,x)
+#
+# usage: zpout(zer,pol,k,[,x])
+#  
+# print formatted zero-pole form
+# to the screen
+# x defaults to the string "s"
+#
+#  SEE ALSO: polyval, polyvalm, poly, roots, conv, deconv, residue, 
+#	filter, polyderiv, polyinteg, polyout
+
+# Written by A. Scottedward Hodel (scotte@eng.auburn.edu) June 1995)
+# $Log$
+
+  save_val = implicit_str_to_num_ok;
+  save_empty = empty_list_elements_ok;
+  empty_list_elements_ok = 1;
+
+  implicit_str_to_num_ok = 1;
+
+  if (nargin < 3 ) | (nargin > 4) | (nargout != 0 )
+    usage("zpout(zer,pol,k[,x])");
+  endif
+ 
+  if( !(is_vector(zer) | isempty(zer)) | !(is_vector(pol) | isempty(pol)) )
+    error("zer, pol must be vectors or empty");
+  endif
+
+  if(!is_scalar(k))
+    error("zpout: argument k must be a scalar.")
+  endif
+ 
+  if (nargin == 3)
+    x = 's';
+  elseif( ! isstr(x) )
+    error("zpout: third argument must be a string");
+  endif
+ 
+  numstring = num2str(k);
+
+  if(length(zer))
+    # find roots at z,s = 0
+    nzr = sum(zer == 0);
+    if(nzr)
+      if(nzr > 1)
+        numstring = [numstring,sprintf(" %s^%d",x,nzr)];
+      else
+        numstring = [numstring,sprintf(" %s",x)];
+      endif
+    endif
+    zer = sortcom(-zer);
+    for ii=1:length(zer)
+      if(zer(ii) != 0)
+        numstring = [numstring,sprintf(" (%s %s)",x,com2str(zer(ii),1) ) ];
+      endif
+    endfor
+  endif
+
+  if(length(pol))
+    # find roots at z,s = 0
+    nzr = sum(pol == 0);
+    if(nzr)
+      if(nzr > 1)
+        denomstring = [sprintf("%s^%d",x,nzr)];
+      else
+        denomstring = [sprintf("%s",x)];
+      endif
+    else
+      denomstring = " ";
+    endif
+    pol = sortcom(-pol);
+    for ii=1:length(pol)
+      if(pol(ii) != 0)
+        denomstring = [denomstring,sprintf(" (%s %s)",x,com2str(pol(ii),1))];
+      endif
+    endfor
+  endif
+
+  len = max(length(numstring),length(denomstring));
+  if(len > 0)
+    y = strrep(blanks(len)," ","-");
+    disp(numstring)
+    if(length(denomstring))
+      disp(y)
+      disp(denomstring)
+    endif
+  else
+    error('zpout: empty transfer function')
+  end
+
+  implicit_str_to_num_ok = save_val;
+  empty_list_elements_ok = save_empty;
+
+endfunction