changeset 13175:8aaaef4a69aa

maint: periodic merge of stable to default
author John W. Eaton <jwe@octave.org>
date Tue, 20 Sep 2011 15:38:24 -0400
parents 536c6a5ab705 (diff) bd2cd4fd3edf (current diff)
children 9b8e786bbf3c
files scripts/general/accumarray.m scripts/plot/axis.m scripts/sparse/gmres.m
diffstat 684 files changed, 23704 insertions(+), 15452 deletions(-) [+]
line wrap: on
line diff
--- a/.dir-locals.el	Tue Sep 20 15:33:10 2011 -0400
+++ b/.dir-locals.el	Tue Sep 20 15:38:24 2011 -0400
@@ -1,5 +1,10 @@
-((nil . ((indent-tabs-mode . nil)
-         (fill-column . 72)))
- (c-default-mode "gnu")
+((nil .
+      ((c-file-style . "gnu")
+       (indent-tabs-mode . nil)
+       (fill-column . 72)
+       (eval . (when (string-match "\\.h\\'" (buffer-file-name))
+                 (unless (string-match "/gnulib/" (buffer-file-name))
+                   (c++-mode)
+                   (c-set-style "gnu"))))))
  (change-log-mode . ((indent-tabs-mode . t)))
  (makefile-mode . ((indent-tabs-mode . t))))
--- a/NEWS	Tue Sep 20 15:33:10 2011 -0400
+++ b/NEWS	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,85 @@
+Summary of important user-visible changes for version 3.6:
+---------------------------------------------------------
+
+ ** The PCRE library is now required to build Octave.
+
+ ** Octave now features a profiler, thanks to the work of Daniel Kraft
+    under the Google Summer of Code mentorship program.  The manual has
+    been updated to reflect this addition.
+
+ ** Overhaul of statistical distribution functions
+
+    Functions now return "single" outputs for inputs of class "single".
+
+    75% reduction in memory usage through use of logical indexing.
+
+    Random sample functions now use the same syntax as rand() and accept
+    a comma separated list of dimensions or a dimension vector.
+
+    Functions have been made Matlab-compatible with regard to special
+    cases (probability on boundaries, probabilities for values outside
+    distribution, etc.).  This may cause subtle changes to existing
+    scripts.
+
+    negative binomial function has been extended to real, non-integer inputs.
+    discrete_inv() now returns v(1) for 0 instead of NaN.
+    nbincdf() recoded to use closed form solution with betainc().
+
+ ** strread, textscan, and textread have been completely revamped.
+
+    They now support nearly all Matlab functionality including:
+
+    * ML-compatible whitespace and delimiter defaults
+
+    * ML-compatible options: 'whitespace', treatasempty',
+    format string repeat count, user-specified comment style, uneven-length
+    output arrays, %n and %u conversion specifiers (provisionally)
+
+ ** Certain string functions have been modified for greater Matlab compatibility
+    and for 15X greater performance when operating on cell array of strings.
+
+    deblank : Now requires character or cellstr input.
+    strtrim : Now requires character or cellstr input.
+              No longer trims nulls ("\0") from string for ML compatibility.
+    strmatch: Follows documentation precisely and ignores trailing spaces
+              in pattern and in string.  Note that Matlab documents this 
+              behavior but the implementation does *not* always follow it.
+ 
+ ** New functions added.
+
+    iscolumn
+    issrow
+    zscore
+    profile
+    profshow
+
+ ** Deprecated functions.
+
+    The following functions were deprecated in Octave 3.2 and have been
+    removed from Octave 3.6.
+                                           
+      create_set          spcholinv    splu   
+      dmult               spcumprod    spmax
+      iscommand           spcumsum     spmin
+      israwcommand        spdet        spprod
+      lchol               spdiag       spqr
+      loadimage           spfind       spsum
+      mark_as_command     sphcat       spsumsq
+      mark_as_rawcommand  spinv        spvcat 
+      spatan2             spkron       str2mat
+      spchol              splchol      unmark_command
+      spchol2inv          split        unmark_rawcommand
+
+    The following functions have been deprecated in Octave 3.6 and will
+    be removed from Octave 3.10 (or whatever version is the second major
+    release after 3.6):
+
+      cut                is_duplicate_entry
+      cor                polyderiv
+      corrcoef           studentize
+      __error_text__     sylvester_matrix
+      error_text
+
 Summary of important user-visible changes for version 3.4.2:
 -----------------------------------------------------------
 
--- a/build-aux/bootstrap.conf	Tue Sep 20 15:33:10 2011 -0400
+++ b/build-aux/bootstrap.conf	Tue Sep 20 15:38:24 2011 -0400
@@ -20,6 +20,7 @@
 gnulib_modules="
   c-strcase
   copysign
+  closedir
   crypto/md5
   fclose
   fcntl
@@ -42,6 +43,7 @@
   mktime
   nanosleep
   nproc
+  opendir
   pathmax
   progname
   readlink
--- a/build-aux/common.mk	Tue Sep 20 15:33:10 2011 -0400
+++ b/build-aux/common.mk	Tue Sep 20 15:38:24 2011 -0400
@@ -162,8 +162,6 @@
 
 RDYNAMIC_FLAG = @RDYNAMIC_FLAG@
 
-RLD_FLAG = @RLD_FLAG@
-
 FLIBS = @FLIBS@
 
 LIBOCTINTERP = @LIBOCTINTERP@
@@ -535,8 +533,12 @@
   -e "s|%OCTAVE_CONF_MAGICK_LDFLAGS%|\"${MAGICK_LDFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_MAGICK_LIBS%|\"${MAGICK_LIBS}\"|" \
   -e 's|%OCTAVE_CONF_MKOCTFILE_DL_LDFLAGS%|\"@MKOCTFILE_DL_LDFLAGS@\"|' \
+  -e "s|%OCTAVE_CONF_OCTAVE_LINK_DEPS%|\"${OCTAVE_LINK_DEPS}\"|" \
+  -e "s|%OCTAVE_CONF_OCTAVE_LINK_OPTS%|\"${OCTAVE_LINK_OPTS}\"|" \
   -e "s|%OCTAVE_CONF_OCTINCLUDEDIR%|\"${octincludedir}\"|" \
   -e "s|%OCTAVE_CONF_OCTLIBDIR%|\"${octlibdir}\"|" \
+  -e "s|%OCTAVE_CONF_OCT_LINK_DEPS%|\"${OCT_LINK_DEPS}\"|" \
+  -e "s|%OCTAVE_CONF_OCT_LINK_OPTS%|\"${OCT_LINK_OPTS}\"|" \
   -e "s|%OCTAVE_CONF_OPENGL_LIBS%|\"${OPENGL_LIBS}\"|" \
   -e "s|%OCTAVE_CONF_PREFIX%|\"${prefix}\"|" \
   -e "s|%OCTAVE_CONF_PTHREAD_CFLAGS%|\"${PTHREAD_CFLAGS}\"|" \
@@ -551,7 +553,6 @@
   -e "s|%OCTAVE_CONF_RDYNAMIC_FLAG%|\"${RDYNAMIC_FLAG}\"|" \
   -e "s|%OCTAVE_CONF_READLINE_LIBS%|\"${READLINE_LIBS}\"|" \
   -e "s|%OCTAVE_CONF_REGEX_LIBS%|\"${REGEX_LIBS}\"|" \
-  -e "s|%OCTAVE_CONF_RLD_FLAG%|\"${RLD_FLAG}\"|" \
   -e "s|%OCTAVE_CONF_SED%|\"${SED}\"|" \
   -e "s|%OCTAVE_CONF_SHARED_LIBS%|\"${SHARED_LIBS}\"|" \
   -e "s|%OCTAVE_CONF_SHLEXT%|\"${SHLEXT}\"|" \
--- a/configure.ac	Tue Sep 20 15:33:10 2011 -0400
+++ b/configure.ac	Tue Sep 20 15:38:24 2011 -0400
@@ -27,13 +27,13 @@
 EXTERN_CFLAGS="$CFLAGS"
 EXTERN_CXXFLAGS="$CXXFLAGS"
 
-AC_INIT([GNU Octave], [3.4.2], [http://octave.org/bugs.html], [octave])
+AC_INIT([GNU Octave], [3.5.0+], [http://octave.org/bugs.html], [octave])
 
 dnl PACKAGE_VERSION is set by the AC_INIT VERSION arg
 OCTAVE_VERSION="$PACKAGE_VERSION"
-OCTAVE_API_VERSION_NUMBER="45"
+OCTAVE_API_VERSION_NUMBER="44"
 OCTAVE_API_VERSION="api-v$OCTAVE_API_VERSION_NUMBER+"
-OCTAVE_RELEASE_DATE="2011-06-24"
+OCTAVE_RELEASE_DATE="2011-01-22"
 OCTAVE_COPYRIGHT="Copyright (C) 2011 John W. Eaton and others."
 AC_SUBST(OCTAVE_VERSION)
 AC_SUBST(OCTAVE_API_VERSION_NUMBER)
@@ -1157,7 +1157,7 @@
 
 AC_ARG_ENABLE([dl],
   [AS_HELP_STRING([--enable-dl],
-    [create shared libraries (not all systems)])], [
+    [allow loading of dynamically linked modules (not all systems)])], [
   case "${enableval}" in
     yes) ENABLE_DYNAMIC_LINKING=true ;;
     no) ENABLE_DYNAMIC_LINKING=false ;;
@@ -1170,16 +1170,6 @@
   AC_MSG_ERROR([You can't disable building static AND shared libraries!])
 fi
 
-AC_ARG_ENABLE(rpath,
-  [AS_HELP_STRING([--enable-rpath],
-     [override the default link options for rpath; e.g., --enable-rpath='-rpath $(octlibdir)'])],
-  [ if test "$enableval" = no; then use_rpath=false;
-    else
-      use_rpath=true
-      if test "$enableval" = yes; then true;
-      else enable_rpath_arg="$enableval"; fi
-    fi], [use_rpath=true])
-
 CPICFLAG=-fPIC
 CXXPICFLAG=-fPIC
 FPICFLAG=-fPIC
@@ -1200,7 +1190,6 @@
 DL_LDFLAGS='$(SH_LDFLAGS)'
 MKOCTFILE_DL_LDFLAGS='$(DL_LDFLAGS)'
 SONAME_FLAGS=
-RLD_FLAG=
 NO_OCT_FILE_STRIP=false
 TEMPLATE_AR='$(AR)'
 TEMPLATE_ARFLAGS="$ARFLAGS"
@@ -1221,14 +1210,12 @@
   ;;
   *-*-freebsd*)
     SH_LDFLAGS="-shared -Wl,-x"
-    RLD_FLAG='-Wl,-rpath -Wl,$(octlibdir)'
   ;;
   alpha*-dec-osf*)
     CPICFLAG=
     CXXPICFLAG=
     FPICFLAG=
     SH_LDFLAGS="-shared -Wl,-expect_unresolved -Wl,'*'"
-    RLD_FLAG='-Wl,-rpath -Wl,$(octlibdir)'
   ;;
   *-*-darwin*)
     DL_LDFLAGS='-bundle -bundle_loader $(top_builddir)/src/octave $(LDFLAGS)'
@@ -1335,11 +1322,9 @@
   *-*-linux* | *-*-gnu*)
     MKOCTFILE_DL_LDFLAGS="-shared -Wl,-Bsymbolic"
     SONAME_FLAGS='-Wl,-soname -Wl,$@'
-    RLD_FLAG='-Wl,-rpath -Wl,$(octlibdir)'
   ;;
   i[[3456]]86-*-sco3.2v5*)
     SONAME_FLAGS='-Wl,-h -Wl,$@'
-    RLD_FLAG=
     SH_LDFLAGS=-G
   ;;
   rs6000-ibm-aix* | powerpc-ibm-aix*)
@@ -1356,7 +1341,6 @@
     fi
     SHLEXT=sl
     SH_LDFLAGS="-shared -fPIC"
-    RLD_FLAG='-Wl,+b -Wl,$(octlibdir)'
     library_path_var=SHLIB_PATH
   ;;
   ia64*-hp-hpux*)
@@ -1366,13 +1350,11 @@
       FPICFLAG=+Z
     fi
     SH_LDFLAGS="-shared -fPIC"
-    RLD_FLAG='-Wl,+b -Wl,$(octlibdir)'
   ;;
   *-sgi-*)
     CPICFLAG=
     CXXPICFLAG=
     FPICFLAG=
-    RLD_FLAG='-rpath $(octlibdir)'
   ;;
   sparc-sun-sunos4*)
     if test "$ac_cv_f77_compiler_gnu" = yes; then
@@ -1382,7 +1364,6 @@
     fi
     SH_LD=ld
     SH_LDFLAGS="-assert nodefinitions"
-    RLD_FLAG='-L$(octlibdir)'
   ;;
   sparc-sun-solaris2* | i386-pc-solaris2*)
     if test "$ac_cv_f77_compiler_gnu" = yes; then
@@ -1402,7 +1383,6 @@
       CXXPICFLAG=-KPIC
       SH_LDFLAGS=-G
     fi
-    RLD_FLAG='-R $(octlibdir)'
     ## Template closures in archive libraries need a different mechanism.
     if test "$GXX" = yes; then
       true
@@ -1416,14 +1396,6 @@
 AM_CONDITIONAL([AMCOND_BUILD_COMPILED_AUX_PROGRAMS],
   [test x$BUILD_COMPILED_AUX_PROGRAMS = xtrue])
 
-if $use_rpath; then
-  if test -n "$enable_rpath_arg"; then
-    RLD_FLAG="$enable_rpath_arg"
-  fi
-else
-  RLD_FLAG=""
-fi
-
 AC_MSG_NOTICE([defining FPICFLAG to be $FPICFLAG])
 AC_MSG_NOTICE([defining CPICFLAG to be $CPICFLAG])
 AC_MSG_NOTICE([defining CXXPICFLAG to be $CXXPICFLAG])
@@ -1445,7 +1417,6 @@
 AC_MSG_NOTICE([defining MKOCTFILE_DL_LDFLAGS to be $MKOCTFILE_DL_LDFLAGS])
 AC_MSG_NOTICE([defining SONAME_FLAGS to be $SONAME_FLAGS])
 AC_MSG_NOTICE([defining NO_OCT_FILE_STRIP to be $NO_OCT_FILE_STRIP])
-AC_MSG_NOTICE([defining RLD_FLAG to be $RLD_FLAG])
 AC_MSG_NOTICE([defining TEMPLATE_AR to be $TEMPLATE_AR])
 AC_MSG_NOTICE([defining TEMPLATE_ARFLAGS to be $TEMPLATE_ARFLAGS])
 AC_MSG_NOTICE([defining CRUFT_DLL_DEFS to be $CRUFT_DLL_DEFS])
@@ -1474,7 +1445,6 @@
 AC_SUBST(MKOCTFILE_DL_LDFLAGS)
 AC_SUBST(SONAME_FLAGS)
 AC_SUBST(NO_OCT_FILE_STRIP)
-AC_SUBST(RLD_FLAG)
 AC_SUBST(TEMPLATE_AR)
 AC_SUBST(TEMPLATE_ARFLAGS)
 AC_SUBST(CRUFT_DLL_DEFS)
@@ -1488,28 +1458,42 @@
 
 AC_CHECK_FUNCS(getpwnam, [], [AC_CHECK_LIB(sun, getpwnam)])
 
-NO_UNDEFINED_LDFLAG=
 case "$canonical_host_type" in
   *-*-mingw*)
     if test "$have_msvc" = "yes"; then
       AC_CHECK_LIB(dirent, opendir)
       LIBS="$LIBS -ladvapi32 -lgdi32 -lws2_32 -luser32 -lkernel32"
-      NO_UNDEFINED_LDFLAG=-no-undefined
     else
       LIBS="$LIBS -lgdi32 -lws2_32 -luser32 -lkernel32"
-      NO_UNDEFINED_LDFLAG=-no-undefined
     fi
     LIBS="$LIBS -lgdi32 -lws2_32 -luser32 -lkernel32"
-    NO_UNDEFINED_LDFLAG=-no-undefined
   ;;
   *-*-msdosmsvc*)
     AC_CHECK_LIB(dirent, opendir)
     LIBS="$LIBS -ladvapi32 -lgdi32 -lws2_32 -luser32 -lkernel32"
-    NO_UNDEFINED_LDFLAG=-no-undefined
   ;;
 esac
+
+AC_ARG_ENABLE([no-undefined],
+  [AS_HELP_STRING([--enable-no-undefined],
+    [pass -no-undefined to libtool when linking linking Octave and its shared libraries (on by default)])],
+  [case "${enableval}" in
+    yes) NO_UNDEFINED_LDFLAG="-no-undefined" ;;
+    no)  NO_UNDEFINED_LDFLAG="" ;;
+    *) AC_MSG_ERROR([bad value ${enableval} for --enable-link-all-depenencies]) ;;
+   esac], [NO_UNDEFINED_LDFLAG="-no-undefined"])
 AC_SUBST(NO_UNDEFINED_LDFLAG)
 
+AC_ARG_ENABLE([link-all-dependencies],
+  [AS_HELP_STRING([--enable-link-all-dependencies],
+    [link Octave and its shared libraries with all dependencies, not just those immediately referenced (should not be needed on most systems)])],
+  [case "${enableval}" in
+    yes) link_all_deps=true ;;
+    no)  link_all_deps=false ;;
+    *) AC_MSG_ERROR([bad value ${enableval} for --enable-link-all-depenencies]) ;;
+   esac], [link_all_deps=false])
+AM_CONDITIONAL([AMCOND_LINK_ALL_DEPS], [test x$link_all_deps = xtrue])
+
 ### Type stuff.
 
 AC_TYPE_MODE_T
@@ -1685,7 +1669,7 @@
       OCTAVE_CXX_FLAG(-rdynamic, [RDYNAMIC_FLAG=-rdynamic])
     ;;
     shl_load)
-      shl_load_api=true
+      shl_load_api=truenn
       DL_API_MSG="(shl_load)"
       AC_DEFINE(HAVE_SHL_LOAD_API, 1, [Define if your system has shl_load and shl_findsym for dynamic linking])
     ;;
@@ -1704,12 +1688,18 @@
   DL_LIBS="$lt_cv_dlopen_libs"
   AC_SUBST(DL_LIBS)
 
+  ## Disable dynamic linking if capability is not present.
   if $dlopen_api || $shl_load_api || $loadlibrary_api || $dyld_api; then
-    ENABLE_DYNAMIC_LINKING=true
-    AC_DEFINE(ENABLE_DYNAMIC_LINKING, 1, [Define if using dynamic linking])
+    true
+  else
+    ENABLE_DYNAMIC_LINKING=false
   fi
 fi
 
+if $ENABLE_DYNAMIC_LINKING; then
+  AC_DEFINE(ENABLE_DYNAMIC_LINKING, 1, [Define if using dynamic linking])
+fi
+
 AM_CONDITIONAL([AMCOND_ENABLE_DYNAMIC_LINKING],
   [test x$ENABLE_DYNAMIC_LINKING = xtrue])
 
--- a/doc/faq/OctaveFAQ.texi	Tue Sep 20 15:33:10 2011 -0400
+++ b/doc/faq/OctaveFAQ.texi	Tue Sep 20 15:38:24 2011 -0400
@@ -63,7 +63,7 @@
 * Getting Octave::
 * Installation::
 * Common problems::
-* How do I ...?::
+* Using Octave::
 * @sc{Matlab} compatibility::
 * Index::
 @end menu
@@ -780,15 +780,16 @@
 @end itemize
 @end itemize
 
-@node How do I ...?
-@chapter  How do I ...?
+@node Using Octave
+@chapter  Using Octave
 
 @menu
 * How do I set the number of displayed decimals?::
+* How does Octave solve linear systems?::
 @end menu
 
 @cindex Tips and tricks
-@cindex How do I @dots{} ?
+@cindex Using Octave
 
 @node How do I set the number of displayed decimals?
 @section How do I set the number of displayed decimals?
@@ -804,6 +805,18 @@
 @end group
 @end example
 
+@node How does Octave solve linear systems?
+@section How does Octave solve linear systems?
+
+@cindex backslash operator
+
+In addition to consulting Octave's source for the precise details, the
+Octave manual contains a complete high-level description of the
+algorithm that Octave uses to decide how to solve a particular linear
+system, e.g. how the backslash operator @code{A\x} will be interpreted.
+Sections ``Techniques Used for Linear Algebra'' and ``Linear Algebra on
+Sparse Matrices'' from the manual describe this procedure.
+
 @node @sc{Matlab} compatibility
 @chapter Porting programs from @sc{Matlab} to Octave
 
--- a/doc/interpreter/container.txi	Tue Sep 20 15:33:10 2011 -0400
+++ b/doc/interpreter/container.txi	Tue Sep 20 15:38:24 2011 -0400
@@ -563,16 +563,11 @@
 @example
 @group
 c@{1:2@}
+     @result{} ans = a string
      @result{} ans =
           
-          (,
-            [1] = a string
-            [2] =
-          
                0.593993   0.627732
                0.377037   0.033643
-          
-          ,)
 @end group
 @end example
 
--- a/doc/interpreter/contributors.in	Tue Sep 20 15:33:10 2011 -0400
+++ b/doc/interpreter/contributors.in	Tue Sep 20 15:38:24 2011 -0400
@@ -1,5 +1,6 @@
 Ben Abbott
 Andy Adler
+Giles Anderson
 Joel Andersson
 Muthiah Annamalai
 Shai Ayal
@@ -8,6 +9,7 @@
 Alexander Barth
 David Bateman
 Heinz Bauschke
+Roman Belov
 Karl Berry
 David Billinghurst
 Don Bindner
@@ -143,14 +145,17 @@
 G. D. McBain
 Alexander Mamonov
 Christoph Mayer
+Júlio Hoffimann Mendes
 Thorsten Meyer
 Petr Mikulik
 Stefan Monnier
 Antoine Moreau
 Kai P. Mueller
+Hannes Müller
 Victor Munoz
 Carmen Navarrete
 Todd Neal
+Philip Nienhuis
 Al Niessner
 Rick Niles
 Takuji Nishimura
@@ -206,6 +211,7 @@
 Daniel J. Sebald
 Dmitri A. Sergatskov
 Baylis Shanks
+Andriy Shinkarchuck
 Joseph P. Skudlarek
 John Smith
 Julius Smith
@@ -232,6 +238,7 @@
 Frederick Umminger
 Utkarsh Upadhyay
 Stefan van der Walt
+David Wells
 Peter Van Wieren
 James R. Van Zandt
 Gregory Vanuxem
@@ -244,6 +251,7 @@
 Andreas Weingessel
 Michael Weitzel
 Fook Fah Yap
+Sean Young
 Michael Zeising
 Federico Zenith
 Alex Zvoleff
--- a/doc/interpreter/debug.txi	Tue Sep 20 15:33:10 2011 -0400
+++ b/doc/interpreter/debug.txi	Tue Sep 20 15:38:24 2011 -0400
@@ -35,6 +35,8 @@
 * Breakpoints::
 * Debug Mode::
 * Call Stack::
+* Profiling::
+* Profiler Example::
 @end menu
 
 @node Entering Debug Mode
@@ -182,3 +184,256 @@
 @DOCSTRING(dbup)
 
 @DOCSTRING(dbdown)
+
+@node Profiling
+@section Profiling
+@cindex profiler
+@cindex code profiling
+
+Octave supports profiling of code execution on a per-function level. If
+profiling is enabled, each call to a function (supporting built-ins,
+operators, functions in oct- and mex-files, user-defined functions in
+Octave code and anonymous functions) is recorded while running Octave
+code. After that, this data can aid in analyzing the code behaviour, and
+is in particular helpful for finding ``hot spots'' in the code which use
+up a lot of computation time and are the best targets to spend
+optimization efforts on.
+
+The main command for profiling is @code{profile}, which can be used to
+start or stop the profiler and also to query collected data afterwards.
+The data is returned in an Octave data structure which can then be
+examined or further processed by other routines or tools.
+
+@DOCSTRING(profile)
+
+An easy way to get an overview over the collected data is
+@code{profshow}. This function takes the profiler data returned by
+@code{profile} as input and prints a flat profile, for instance:
+
+@example
+@group
+ Function Attr     Time (s)        Calls
+----------------------------------------
+   >myfib    R        2.195        13529
+binary <=             0.061        13529
+ binary -             0.050        13528
+ binary +             0.026         6764
+@end group
+@end example
+
+This shows that most of the runtime was spent executing the function
+@samp{myfib}, and some minor proportion evaluating the listed binary
+operators. Furthermore, it is shown how often the function was called
+and the profiler also records that it is recursive.
+
+@DOCSTRING(profshow)
+
+@node Profiler Example
+@section Profiler Example
+
+Below, we will give a short example of a profiler session. See also
+@ref{Profiling} for the documentation of the profiler functions in
+detail. Consider the code:
+
+@example
+@group
+global N A;
+
+N = 300;
+A = rand (N, N);
+
+function xt = timesteps (steps, x0, expM)
+  global N;
+
+  if (steps == 0)
+    xt = NA (N, 0);
+  else
+    xt = NA (N, steps);
+    x1 = expM * x0;
+    xt(:, 1) = x1;
+    xt(:, 2 : end) = timesteps (steps - 1, x1, expM);
+  endif
+endfunction
+
+function foo ()
+  global N A;
+
+  initial = @@(x) sin (x);
+  x0 = (initial (linspace (0, 2 * pi, N)))';
+
+  expA = expm (A);
+  xt = timesteps (100, x0, expA);
+endfunction
+
+function fib = bar (N)
+  if (N <= 2)
+    fib = 1;
+  else
+    fib = bar (N - 1) + bar (N - 2);
+  endif
+endfunction
+@end group
+@end example
+
+If we execute the two main functions, we get:
+
+@example
+@group
+tic; foo; toc;
+@result{} Elapsed time is 2.37338 seconds.
+
+tic; bar (20); toc;
+@result{} Elapsed time is 2.04952 seconds.
+@end group
+@end example
+
+But this does not give much information about where this time is spent;
+for instance, whether the single call to @code{expm} is more expensive
+or the recursive time-stepping itself. To get a more detailed picture,
+we can use the profiler.
+
+@example
+@group
+profile on;
+foo;
+profile off;
+
+data = profile ('info');
+profshow (data, 10);
+@end group
+@end example
+
+This prints a table like:
+
+@example
+@group
+   #  Function Attr     Time (s)        Calls
+---------------------------------------------
+   7      expm             1.034            1
+   3  binary *             0.823          117
+  41  binary \             0.188            1
+  38  binary ^             0.126            2
+  43 timesteps    R        0.111          101
+  44        NA             0.029          101
+  39  binary +             0.024            8
+  34      norm             0.011            1
+  40  binary -             0.004          101
+  33   balance             0.003            1
+@end group
+@end example
+
+The entries are the individual functions which have been executed (only
+the 10 most important ones), together with some information for each of
+them. The entries like @samp{binary *} denote operators, while other
+entries are ordinary functions. They include both built-ins like
+@code{expm} and our own routines (for instance @code{timesteps}). From
+this profile, we can immediately deduce that @code{expm} uses up the
+largest proportion of the processing time, even though it is only called
+once. The second expensive operation is the matrix-vector product in the
+routine @code{timesteps}. @footnote{We only know it is the binary
+multiplication operator, but fortunately this operator appears only at
+one place in the code and thus we know which occurence takes so much
+time. If there were multiple places, we would have to use the
+hierarchical profile to find out the exact place which uses up the time
+which is not covered in this example.}
+
+Timing, however, is not the only information available from the profile.
+The attribute column shows us that @code{timesteps} calls itself
+recursively. This may not be that remarkable in this example (since it's
+clear anyway), but could be helpful in a more complex setting. As to the
+question of why is there a @samp{binary \} in the output, we can easily
+shed some light on that too. Note that @code{data} is a structure array
+(@ref{Structure Arrays}) which contains the field @code{FunctionTable}.
+This stores the raw data for the profile shown. The number in the first
+column of the table gives the index under which the shown function can
+be found there. Looking up @code{data.FunctionTable(41)} gives:
+
+@example
+@group
+  scalar structure containing the fields:
+
+    FunctionName = binary \
+    TotalTime =  0.18765
+    NumCalls =  1
+    IsRecursive = 0
+    Parents =  7
+    Children = [](1x0)
+@end group
+@end example
+
+Here we see the information from the table again, but have additional
+fields @code{Parents} and @code{Children}. Those are both arrays, which
+contain the indices of functions which have directly called the function
+in question (which is entry 7, @code{expm}, in this case) or been called
+by it (no functions). Hence, the backslash operator has been used
+internally by @code{expm}.
+
+Now let's take a look at @code{bar}. For this, we start a fresh
+profiling session (@code{profile on} does this; the old data is removed
+before the profiler is restarted):
+
+@example
+@group
+profile on;
+bar (20);
+profile off;
+
+profshow (profile ('info'));
+@end group
+@end example
+
+This gives:
+
+@example
+   #            Function Attr     Time (s)        Calls
+-------------------------------------------------------
+   1                 bar    R        2.091        13529
+   2           binary <=             0.062        13529
+   3            binary -             0.042        13528
+   4            binary +             0.023         6764
+   5             profile             0.000            1
+   8               false             0.000            1
+   6              nargin             0.000            1
+   7           binary !=             0.000            1
+   9 __profiler_enable__             0.000            1
+@end example
+
+Unsurprisingly, @code{bar} is also recursive. It has been called 13,529
+times in the course of recursively calculating the Fibonacci number in a
+suboptimal way, and most of the time was spent in @code{bar} itself.
+
+Finally, let's say we want to profile the execution of both @code{foo}
+and @code{bar} together. Since we already have the runtime data
+collected for @code{bar}, we can restart the profiler without clearing
+the existing data and collect the missing statistics about @code{foo}.
+This is done by:
+
+@example
+@group
+profile resume;
+foo;
+profile off;
+
+profshow (profile ('info'), 10);
+@end group
+@end example
+
+As you can see in the table below, now we have both profiles mixed
+together.
+
+@example
+@group
+   #  Function Attr     Time (s)        Calls
+---------------------------------------------
+   1       bar    R        2.091        13529
+  16      expm             1.122            1
+  12  binary *             0.798          117
+  46  binary \             0.185            1
+  45  binary ^             0.124            2
+  48 timesteps    R        0.115          101
+   2 binary <=             0.062        13529
+   3  binary -             0.045        13629
+   4  binary +             0.041         6772
+  49        NA             0.036          101
+@end group
+@end example
--- a/doc/interpreter/dir	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
--*- Text -*-
-This is the file .../info/dir, which contains the topmost node of the
-Info hierarchy.	 The first time you invoke Info you start off
-looking at that node, which is (dir)Top.
-
-File: dir	Node: Top	This is the top of the INFO tree
-  This (the Directory node) gives a menu of major topics. 
-  Typing "d" returns here, "q" exits, "?" lists all INFO commands, "h" 
-  gives a primer for first-timers, "mItem<Return>" visits the menu
-  item named `Item', etc.
-
-* Menu: The list of major topics begins on the next line.
-
-* Octave: (octave).	Interactive language for numerical computations.
--- a/doc/interpreter/doccheck/mk_undocumented_list	Tue Sep 20 15:33:10 2011 -0400
+++ b/doc/interpreter/doccheck/mk_undocumented_list	Tue Sep 20 15:38:24 2011 -0400
@@ -82,7 +82,6 @@
 comma
 debug
 dbnext
-error_text
 exit
 F_DUPFD
 F_GETFD
--- a/doc/interpreter/eos.txi	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,515 +0,0 @@
-@c Copyright (C) 1996-2011 Kurt Hornik
-@c
-@c This file is part of Octave.
-@c
-@c Octave is free software; you can redistribute it and/or modify it
-@c under the terms of the GNU General Public License as published by the
-@c Free Software Foundation; either version 3 of the License, or (at
-@c your option) any later version.
-@c 
-@c Octave is distributed in the hope that it will be useful, but WITHOUT
-@c ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-@c FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-@c for more details.
-@c 
-@c You should have received a copy of the GNU General Public License
-@c along with Octave; see the file COPYING.  If not, see
-@c <http://www.gnu.org/licenses/>.
-
-@c Written by Kurt Hornik <Kurt.Hornik@wu-wien.ac.at> on 1996/05/17.
-@c Last updated by KH on 1997/07/31.
-
-@node Emacs
-@chapter Emacs Octave Support
-
-The development of Octave code can greatly be facilitated using Emacs
-with Octave mode
-automatically indent the code, do some of the typing (with Abbrev mode)
-and show keywords, comments, strings, etc.@: in different faces (with
-Font-lock mode on devices that support it).
-
-It is also possible to run Octave from within Emacs, either by directly
-entering commands at the prompt in a buffer in Inferior Octave mode, or
-by interacting with Octave from within a file with Octave code.  This is
-useful in particular for debugging Octave code.
-
-Finally, you can convince Octave to use the Emacs info reader for
-@kbd{help -i}.
-
-All functionality is provided by the Emacs Lisp package EOS (for ``Emacs
-Octave Support'').  This chapter describes how to set up and use this
-package.
-
-Please contact @email{Kurt.Hornik@@wu-wien.ac.at} if you have any questions
-or suggestions on using EOS.
-
-@menu
-* Installing EOS::              
-* Using Octave Mode::           
-* Running Octave From Within Emacs::  
-* Using the Emacs Info Reader for Octave::  
-@end menu
-
-@node Installing EOS
-@section Installing EOS
-
-The Emacs package EOS consists of the three files @file{octave-mod.el},
-@file{octave-inf.el}, and @file{octave-hlp.el}.  These files, or better
-yet their byte-compiled versions, should be somewhere in your Emacs
-load-path.
-
-If you have GNU Emacs with a version number at least as high as 19.35,
-you are all set up, because EOS is respectively will be part of GNU
-Emacs as of version 19.35.
-
-Otherwise, copy the three files from the @file{emacs} subdirectory of
-the Octave distribution to a place where Emacs can find them (this
-depends on how your Emacs was installed).  Byte-compile them for speed
-if you want.
-
-@node Using Octave Mode
-@section Using Octave Mode
-
-If you are lucky, your sysadmins have already arranged everything so
-that Emacs automatically goes into Octave mode whenever you visit an
-Octave code file as characterized by its extension @file{.m}.  If not,
-proceed as follows.
-
-@enumerate
-@item
-To begin using Octave mode for all @file{.m} files you visit, add the
-following lines to a file loaded by Emacs at startup time, typically
-your @file{~/.emacs} file:
-
-@lisp
-(autoload 'octave-mode "octave-mod" nil t)
-(setq auto-mode-alist
-      (cons '(\"\\\\.m$\" . octave-mode) auto-mode-alist))
-@end lisp
-
-@item
-Finally, to turn on the abbrevs, auto-fill and font-lock features
-automatically, also add the following lines to one of the Emacs startup
-files:
-@lisp
-(add-hook 'octave-mode-hook
-          (lambda ()
-            (abbrev-mode 1)
-            (auto-fill-mode 1)
-            (if (eq window-system 'x)
-                (font-lock-mode 1))))
-@end lisp
-See the Emacs manual for more information about how to customize
-Font-lock mode.
-@end enumerate
-
-In Octave mode, the following special Emacs commands can be used in
-addition to the standard Emacs commands.
-
-@table @kbd
-@item C-h m
-Describe the features of Octave mode.
-
-@item LFD
-Reindent the current Octave line, insert a newline and indent the new
-line (@code{octave-reindent-then-newline-and-indent}).  An abbrev before
-point is expanded if @code{abbrev-mode} is non-@code{nil}.
-
-@item TAB
-Indents current Octave line based on its contents and on previous
-lines (@code{indent-according-to-mode}). 
-
-@item ;
-Insert an ``electric'' semicolon (@code{octave-electric-semi}).  If
-@code{octave-auto-indent} is non-@code{nil}, reindent the current line.
-If @code{octave-auto-newline} is non-@code{nil}, automagically insert a
-newline and indent the new line.
-
-@item `
-Start entering an abbreviation (@code{octave-abbrev-start}).  If Abbrev
-mode is turned on, typing @kbd{`C-h} or @kbd{`?} lists all abbrevs.
-Any other key combination is executed normally.  Note that all Octave
-abbrevs start with a grave accent.
-
-@item M-LFD
-Break line at point and insert continuation marker and alignment
-(@code{octave-split-line}).
-
-@item M-TAB
-Perform completion on Octave symbol preceding point, comparing that
-symbol against Octave's reserved words and built-in variables
-(@code{octave-complete-symbol}). 
-
-@item M-C-a
-Move backward to the beginning of a function
-(@code{octave-beginning-of-defun}).
-With prefix argument @var{N}, do it that many times if @var{N} is
-positive; otherwise, move forward to the @var{N}-th following beginning
-of a function.
-
-@item M-C-e
-Move forward to the end of a function (@code{octave-end-of-defun}).
-With prefix argument @var{N}, do it that many times if @var{N} is
-positive; otherwise, move back to the @var{N}-th preceding end of a
-function.
-
-@item M-C-h
-Puts point at beginning and mark at the end of the current Octave
-function, i.e., the one containing point or following point
-(@code{octave-mark-defun}).
-
-@item M-C-q
-Properly indents the Octave function which contains point
-(@code{octave-indent-defun}).
-
-@item M-;
-If there is no comment already on this line, create a code-level comment
-(started by two comment characters) if the line is empty, or an in-line
-comment (started by one comment character) otherwise
-(@code{octave-indent-for-comment}).
-Point is left after the start of the comment which is properly aligned.
-
-@item C-c ;
-Puts the comment character @samp{#} (more precisely, the string value of
-@code{octave-comment-start}) at the beginning of every line in the
-region (@code{octave-comment-region}).  With just @kbd{C-u} prefix
-argument, uncomment each line in the region.  A numeric prefix argument
-@var{N} means use @var{N} comment characters.
-
-@item C-c :
-Uncomments every line in the region (@code{octave-uncomment-region}).
-
-@item C-c C-p
-Move one line of Octave code backward, skipping empty and comment lines
-(@code{octave-previous-code-line}).  With numeric prefix argument
-@var{N}, move that many code lines backward (forward if @var{N} is
-negative).
-
-@item C-c C-n
-Move one line of Octave code forward, skipping empty and comment lines
-(@code{octave-next-code-line}).  With numeric prefix argument @var{N},
-move that many code lines forward (backward if @var{N} is negative).
-
-@item C-c C-a
-Move to the `real' beginning of the current line
-(@code{octave-beginning-of-line}).  If point is in an empty or comment
-line, simply go to its beginning; otherwise, move backwards to the
-beginning of the first code line which is not inside a continuation
-statement, i.e., which does not follow a code line ending in @samp{...}
-or @samp{\}, or is inside an open parenthesis list.
-
-@item C-c C-e
-Move to the `real' end of the current line (@code{octave-end-of-line}).
-If point is in a code line, move forward to the end of the first Octave
-code line which does not end in @samp{...} or @samp{\} or is inside an
-open parenthesis list.  Otherwise, simply go to the end of the current
-line.
-
-@item C-c M-C-n
-Move forward across one balanced begin-end block of Octave code
-(@code{octave-forward-block}).  With numeric prefix argument @var{N},
-move forward across @var{n} such blocks (backward if @var{N} is
-negative).
-
-@item C-c M-C-p
-Move back across one balanced begin-end block of Octave code
-(@code{octave-backward-block}).  With numeric prefix argument @var{N},
-move backward across @var{N} such blocks (forward if @var{N} is
-negative).
-
-@item C-c M-C-d
-Move forward down one begin-end block level of Octave code
-(@code{octave-down-block}).  With numeric prefix argument, do it that
-many times; a negative argument means move backward, but still go down
-one level.
-
-@item C-c M-C-u
-Move backward out of one begin-end block level of Octave code
-(@code{octave-backward-up-block}).  With numeric prefix argument, do it
-that many times; a negative argument means move forward, but still to a
-less deep spot.
-
-@item C-c M-C-h
-Put point at the beginning of this block, mark at the end
-(@code{octave-mark-block}).
-The block marked is the one that contains point or follows point.
-
-@item C-c ]
-Close the current block on a separate line (@code{octave-close-block}).
-An error is signaled if no block to close is found.
-
-@item C-c f
-Insert a function skeleton, prompting for the function's name, arguments
-and return values which have to be entered without parentheses
-(@code{octave-insert-defun}).
-
-@item C-c C-h
-Search the function, operator and variable indices of all info files
-with documentation for Octave for entries (@code{octave-help}).  If used
-interactively, the entry is prompted for with completion.  If multiple
-matches are found, one can cycle through them using the standard
-@samp{,} (@code{Info-index-next}) command of the Info reader.
-
-The variable @code{octave-help-files} is a list of files to search
-through and defaults to @code{'("octave")}.  If there is also an Octave
-Local Guide with corresponding info file, say, @file{octave-LG}, you can
-have @code{octave-help} search both files by 
-@lisp
-(setq octave-help-files '("octave" "octave-LG"))
-@end lisp
-@noindent
-in one of your Emacs startup files.
-
-@end table
-
-A common problem is that the @key{RET} key does @emph{not} indent the
-line to where the new text should go after inserting the newline.  This
-is because the standard Emacs convention is that @key{RET} (aka
-@kbd{C-m}) just adds a newline, whereas @key{LFD} (aka @kbd{C-j}) adds a
-newline and indents it.  This is particularly inconvenient for users with
-keyboards which do not have a special @key{LFD} key at all; in such
-cases, it is typically more convenient to use @key{RET} as the @key{LFD}
-key (rather than typing @kbd{C-j}).  
-
-You can make @key{RET} do this by adding
-@lisp
-(define-key octave-mode-map "\C-m"
-  'octave-reindent-then-newline-and-indent)
-@end lisp
-@noindent
-to one of your Emacs startup files.  Another, more generally applicable
-solution is
-@lisp
-(defun RET-behaves-as-LFD ()
-  (let ((x (key-binding "\C-j")))
-    (local-set-key "\C-m" x)))
-(add-hook 'octave-mode-hook 'RET-behaves-as-LFD)
-@end lisp
-@noindent
-(this works for all modes by adding to the startup hooks, without having
-to know the particular binding of @key{RET} in that mode!).  Similar
-considerations apply for using @key{M-RET} as @key{M-LFD}.  As Barry
-A. Warsaw @email{bwarsaw@@cnri.reston.va.us} says in the documentation for his
-@code{cc-mode}, ``This is a very common question.  @code{:-)} If you want
-this to be the default behavior, don't lobby me, lobby RMS!''
-
-The following variables can be used to customize Octave mode.
-
-@table @code
-@item octave-auto-indent
-Non-@code{nil} means auto-indent the current line after a semicolon or
-space.  Default is @code{nil}.
-
-@item octave-auto-newline
-Non-@code{nil} means auto-insert a newline and indent after semicolons
-are typed.  The default value is @code{nil}.
-
-@item octave-blink-matching-block
-Non-@code{nil} means show matching begin of block when inserting a space,
-newline or @samp{;} after an else or end keyword.  Default is @code{t}.
-This is an extremely useful feature for automatically verifying that the
-keywords match---if they don't, an error message is displayed.
-
-@item octave-block-offset
-Extra indentation applied to statements in block structures.
-Default is 2.
-
-@item octave-continuation-offset
-Extra indentation applied to Octave continuation lines.
-Default is 4. 
-
-@item octave-continuation-string
-String used for Octave continuation lines.
-Normally @samp{\}.
-
-@item octave-mode-startup-message
-If @code{t} (default), a startup message is displayed when Octave mode
-is called.
-
-@end table
-
-If Font Lock mode is enabled, Octave mode will display
-@itemize @bullet
-@item
-strings in @code{font-lock-string-face}
-
-@item
-comments in @code{font-lock-comment-face}
-
-@item
-the Octave reserved words (such as all block keywords) and the text
-functions (such as @samp{cd} or @samp{who}) which are also reserved
-using @code{font-lock-keyword-face}
-
-@item
-the built-in operators (@samp{&&}, @samp{==}, @dots{}) using
-@code{font-lock-reference-face}
-
-@item
-and the function names in function declarations in
-@code{font-lock-function-name-face}.
-@end itemize
-
-There is also rudimentary support for Imenu (currently, function names
-can be indexed).
-
-Customization of Octave mode can be performed by modification of the
-variable @code{octave-mode-hook}.  It the value of this variable is
-non-@code{nil}, turning on Octave mode calls its value.
-
-If you discover a problem with Octave mode, you can conveniently send a
-bug report using @kbd{C-c C-b} (@code{octave-submit-bug-report}).  This
-automatically sets up a mail buffer with version information already
-added.  You just need to add a description of the problem, including a
-reproducible test case and send the message.
-
-@node Running Octave From Within Emacs
-@section Running Octave From Within Emacs
-
-The package @file{octave} provides commands for running an inferior
-Octave process in a special Emacs buffer.  Use 
-@lisp
-M-x run-octave
-@end lisp
-@noindent
-to directly start an inferior Octave process.  If Emacs does not know
-about this command, add the line
-@lisp
-(autoload 'run-octave "octave-inf" nil t)
-@end lisp
-@noindent
-to your @file{.emacs} file.
-
-This will start Octave in a special buffer the name of which is
-specified by the variable @code{inferior-octave-buffer} and defaults to
-@code{"*Inferior Octave*"}.  From within this buffer, you can
-interact with the inferior Octave process `as usual', i.e., by entering
-Octave commands at the prompt.  The buffer is in Inferior Octave mode,
-which is derived from the standard Comint mode, a major mode for
-interacting with an inferior interpreter.  See the documentation for
-@code{comint-mode} for more details, and use @kbd{C-h b} to find out
-about available special keybindings.
-
-You can also communicate with an inferior Octave process from within
-files with Octave code (i.e., buffers in Octave mode), using the
-following commands.
-
-@table @kbd
-@item C-c i l
-Send the current line to the inferior Octave process
-(@code{octave-send-line}).
-With positive prefix argument @var{N}, send that many lines.
-If @code{octave-send-line-auto-forward} is non-@code{nil}, go to the
-next unsent code line.
-
-@item C-c i b
-Send the current block to the inferior Octave process
-(@code{octave-send-block}).
-
-@item C-c i f
-Send the current function to the inferior Octave process
-(@code{octave-send-defun}).
-
-@item C-c i r
-Send the region to the inferior Octave process
-(@code{octave-send-region}).
-
-@item C-c i s
-Make sure that `inferior-octave-buffer' is displayed
-(@code{octave-show-process-buffer}).
-
-@item C-c i h
-Delete all windows that display the inferior Octave buffer
-(@code{octave-hide-process-buffer}).
-
-@item C-c i k
-Kill the inferior Octave process and its buffer
-(@code{octave-kill-process}).
-@end table
-
-The effect of the commands which send code to the Octave process can be
-customized by the following variables.
-@table @code
-@item octave-send-echo-input
-Non-@code{nil} means echo input sent to the inferior Octave process.
-Default is @code{t}.
-
-@item octave-send-show-buffer
-Non-@code{nil} means display the buffer running the Octave process after
-sending a command (but without selecting it).
-Default is @code{t}.
-@end table
-
-If you send code and there is no inferior Octave process yet, it will be
-started automatically.
-
-The startup of the inferior Octave process is highly customizable.
-The variable @code{inferior-octave-startup-args} can be used for
-specifying command lines arguments to be passed to Octave on startup
-as a list of strings.  For example, to suppress the startup message and
-use `traditional' mode, set this to @code{'("-q" "--traditional")}.
-You can also specify a startup file of Octave commands to be loaded on
-startup; note that these commands will not produce any visible output
-in the process buffer.  Which file to use is controlled by the variable
-@code{inferior-octave-startup-file}.  If this is @code{nil}, the file
-@file{~/.emacs-octave} is used if it exists.
-
-And finally, @code{inferior-octave-mode-hook} is run after starting the
-process and putting its buffer into Inferior Octave mode.  Hence, if you
-like the up and down arrow keys to behave in the interaction buffer as
-in the shell, and you want this buffer to use nice colors, add
-@lisp
-(add-hook 'inferior-octave-mode-hook
-          (lambda ()
-            (turn-on-font-lock)
-            (define-key inferior-octave-mode-map [up]
-              'comint-previous-input)
-            (define-key inferior-octave-mode-map [down]
-              'comint-next-input)))
-@end lisp
-@noindent
-to your @file{.emacs} file.  You could also swap the roles of @kbd{C-a}
-(@code{beginning-of-line}) and @code{C-c C-a} (@code{comint-bol}) using
-this hook.
-
-@quotation
-@strong{Note:}
-If you set your Octave prompts to something different from the defaults,
-make sure that @code{inferior-octave-prompt} matches them.
-Otherwise, @emph{nothing} will work, because Emacs will have no idea
-when Octave is waiting for input, or done sending output.
-@end quotation
-
-@node Using the Emacs Info Reader for Octave
-@section Using the Emacs Info Reader for Octave
-
-You can also set up the Emacs Info reader for dealing with the results
-of Octave's @samp{help -i}.  For this, the package @file{gnuserv} needs
-to be installed, which unfortunately still does not come with GNU Emacs
-(it does with XEmacs).  It can be retrieved from any GNU Emacs Lisp Code
-Directory archive, e.g.@:
-@url{ftp://ftp.cis.ohio-state.edu/pub/gnu/emacs/elisp-archive},
-in the @file{packages} subdirectory.  The alpha version of an enhanced
-version of gnuserv is available at 
-@url{ftp://ftp.wellfleet.com/netman/psmith/emacs/gnuserv-2.1alpha.tar.gz}.
-
-If @file{gnuserv} is installed, add the lines
-@lisp
-(autoload 'octave-help "octave-hlp" nil t)
-(require 'gnuserv)
-(gnuserv-start)
-@end lisp
-@noindent
-to your @file{.emacs} file.
-
-You can use either `plain' Emacs Info or the function @code{octave-help}
-as your Octave info reader (for @samp{help -i}).  In the former case,
-set the Octave variable @w{@env{INFO_PROGRAM}} to @code{"info-emacs-info"}.
-The latter is perhaps more attractive because it allows to look up keys
-in the indices of @emph{several} info files related to Octave (provided
-that the Emacs variable @code{octave-help-files} is set correctly).  In
-this case, set @w{@env{INFO_PROGRAM}} to @code{"info-emacs-octave-help"}.
-
-If you use Octave from within Emacs, these settings are best done in the
-@file{~/.emacs-octave} startup file (or the file pointed to by the Emacs
-variable @code{inferior-octave-startup-file}).
--- a/doc/interpreter/expr.txi	Tue Sep 20 15:33:10 2011 -0400
+++ b/doc/interpreter/expr.txi	Tue Sep 20 15:38:24 2011 -0400
@@ -1239,51 +1239,62 @@
 any such mistake.
 
 When operators of equal precedence are used together, the leftmost
-operator groups first, except for the assignment and exponentiation
-operators, which group in the opposite order.  Thus, the expression
-@code{a - b + c} groups as @code{(a - b) + c}, but the expression
-@code{a = b = c} groups as @code{a = (b = c)}.
+operator groups first, except for the assignment operators, which group
+in the opposite order.  Thus, the expression @code{a - b + c} groups as
+@code{(a - b) + c}, but the expression @code{a = b = c} groups as
+@code{a = (b = c)}.
 
 The precedence of prefix unary operators is important when another
 operator follows the operand.  For example, @code{-x^2} means
 @code{-(x^2)}, because @samp{-} has lower precedence than @samp{^}.
 
-Here is a table of the operators in Octave, in order of increasing
-precedence.
+Here is a table of the operators in Octave, in order of decreasing
+precedence.  Unless noted, all operators group left to right.
 
 @table @code
-@item statement separators
-@samp{;}, @samp{,}.
+@item function call and array indexing, cell array indexing, and structure element indexing
+@samp{()}  @samp{@{@}} @samp{.}
+
+@item postfix increment, and postfix decrement
+@samp{++}  @samp{--}
+
+These operators group right to left.
+
+@item transpose and exponentiation
+@samp{'} @samp{.'} @samp{^} @samp{**} @samp{.^} @samp{.**}
 
-@item assignment
-@samp{=}, @samp{+=}, @samp{-=}, @samp{*=},@samp{/=}.  This operator
-groups right to left.
+@item unary plus, unary minus, prefix increment, prefix decrement, and logical "not"
+@samp{+} @samp{-} @samp{++}  @samp{--} @samp{~} @samp{!}
+
+@item multiply and divide
+@samp{*} @samp{/} @samp{\} @samp{.\} @samp{.*} @samp{./}
 
-@item logical "or" and "and"
-@samp{||}, @samp{&&}.
+@item add, subtract
+@samp{+} @samp{-}
 
-@item element-wise "or" and "and"
-@samp{|}, @samp{&}.
+@item colon
+@samp{:}
 
 @item relational
-@samp{<}, @samp{<=}, @samp{==}, @samp{>=}, @samp{>}, @samp{!=},
-@samp{~=}.
+@samp{<} @samp{<=} @samp{==} @samp{>=} @samp{>} @samp{!=}
+@samp{~=}
 
-@item colon
-@samp{:}.
+@item element-wise "and"
+@samp{&}
 
-@item add, subtract
-@samp{+}, @samp{-}.
+@item element-wise "or"
+@samp{|}
 
-@item multiply, divide
-@samp{*}, @samp{/}, @samp{\}, @samp{.\}, @samp{.*}, @samp{./}.
+@item logical "and"
+@samp{&&}
 
-@item transpose
-@samp{'}, @samp{.'}
+@item logical "or"
+@samp{||}
 
-@item unary plus, minus, increment, decrement, and ``not''
-@samp{+}, @samp{-}, @samp{++}, @samp{--}, @samp{!}, @samp{~}.
+@item assignment
+@samp{=} @samp{+=} @samp{-=} @samp{*=} @samp{/=} @samp{\=}
+@samp{^=} @samp{.*=} @samp{./=} @samp{.\=} @samp{.^=} @samp{|=}
+@samp{&=}
 
-@item exponentiation
-@samp{^}, @samp{**}, @samp{.^}, @samp{.**}.
+These operators group right to left.
 @end table
--- a/doc/interpreter/install.txi	Tue Sep 20 15:33:10 2011 -0400
+++ b/doc/interpreter/install.txi	Tue Sep 20 15:38:24 2011 -0400
@@ -32,7 +32,7 @@
 under the terms of the GNU General Public License as published by the
 Free Software Foundation.
 
-@strong{Note:} This file is automatically generated from
+@strong{Note}: This file is automatically generated from
 @file{doc/interpreter/install.txi} in the Octave sources.  To update
 the documentation make changes to the .txi source file rather than this
 derived file.
--- a/doc/interpreter/linalg.txi	Tue Sep 20 15:33:10 2011 -0400
+++ b/doc/interpreter/linalg.txi	Tue Sep 20 15:38:24 2011 -0400
@@ -187,6 +187,8 @@
 @node Specialized Solvers
 @section Specialized Solvers
 
+@DOCSTRING(bicg)
+
 @DOCSTRING(bicgstab)
 
 @DOCSTRING(cgs)
--- a/doc/interpreter/matrix.txi	Tue Sep 20 15:33:10 2011 -0400
+++ b/doc/interpreter/matrix.txi	Tue Sep 20 15:38:24 2011 -0400
@@ -257,8 +257,6 @@
 
 @DOCSTRING(rosser)
 
-@DOCSTRING(sylvester_matrix)
-
 @DOCSTRING(toeplitz)
 
 @DOCSTRING(vander)
--- a/doc/interpreter/mkoctfile.1	Tue Sep 20 15:33:10 2011 -0400
+++ b/doc/interpreter/mkoctfile.1	Tue Sep 20 15:38:24 2011 -0400
@@ -95,28 +95,29 @@
 Print configuration variable \fIVAR\fP.  Recognized variables are:
 .RS
 .Vb
-   ALL_CFLAGS                FFTW3F_LDFLAGS
-   ALL_CXXFLAGS              FFTW3F_LIBS
-   ALL_FFLAGS                FLIBS
-   ALL_LDFLAGS               FPICFLAG
-   BLAS_LIBS                 INCFLAGS
-   CC                        LAPACK_LIBS
-   CFLAGS                    LDFLAGS
-   CPICFLAG                  LD_CXX
-   CPPFLAGS                  LD_STATIC_FLAG
-   CXX                       LFLAGS
-   CXXFLAGS                  LIBCRUFT
-   CXXPICFLAG                LIBOCTAVE
-   DEPEND_EXTRA_SED_PATTERN  LIBOCTINTERP
-   DEPEND_FLAGS              LIBS
-   DL_LD                     OCTAVE_LIBS
-   DL_LDFLAGS                RDYNAMIC_FLAG
-   EXEEXT                    READLINE_LIBS
-   F77                       RLD_FLAG
-   F77_INTEGER_8_FLAG        SED
-   FFLAGS                    XTRA_CFLAGS
-   FFTW3_LDFLAGS             XTRA_CXXFLAGS
-   FFTW3_LIBS
+    ALL_CFLAGS                FFTW3F_LIBS
+    ALL_CXXFLAGS              FLIBS
+    ALL_FFLAGS                FPICFLAG
+    ALL_LDFLAGS               INCFLAGS
+    BLAS_LIBS                 LAPACK_LIBS
+    CC                        LDFLAGS
+    CFLAGS                    LD_CXX
+    CPICFLAG                  LD_STATIC_FLAG
+    CPPFLAGS                  LFLAGS
+    CXX                       LIBCRUFT
+    CXXFLAGS                  LIBOCTAVE
+    CXXPICFLAG                LIBOCTINTERP
+    DEPEND_EXTRA_SED_PATTERN  LIBS
+    DEPEND_FLAGS              OCTAVE_LIBS
+    DL_LD                     OCTAVE_LINK_DEPS
+    DL_LDFLAGS                OCT_LINK_DEPS
+    EXEEXT                    RDYNAMIC_FLAG
+    F77                       READLINE_LIBS
+    F77_INTEGER_8_FLAG        SED
+    FFLAGS                    XTRA_CFLAGS
+    FFTW3_LDFLAGS             XTRA_CXXFLAGS
+    FFTW3_LIBS
+    FFTW3F_LDFLAGS
 .Ve
 .RE
 .TP
--- a/doc/interpreter/plot.txi	Tue Sep 20 15:33:10 2011 -0400
+++ b/doc/interpreter/plot.txi	Tue Sep 20 15:38:24 2011 -0400
@@ -2396,7 +2396,11 @@
 may override the factory defaults.
 
 Although default values may be set for any object, they are set in
-parent objects and apply to child objects.  For example,
+parent objects and apply to child objects, of the specified object type.
+For example, seeting the default @code{color} property of @code{line}
+objects to "green", for the @code{root} object, will result in all
+@code{line} objects inheriting the @code{color} "green" as the default
+value.
 
 @example
 set (0, "defaultlinecolor", "green");
--- a/doc/interpreter/stats.txi	Tue Sep 20 15:33:10 2011 -0400
+++ b/doc/interpreter/stats.txi	Tue Sep 20 15:38:24 2011 -0400
@@ -114,7 +114,7 @@
 
 @DOCSTRING(center)
 
-@DOCSTRING(studentize)
+@DOCSTRING(zscore)
 
 @DOCSTRING(histc)
 
@@ -168,9 +168,7 @@
 
 @DOCSTRING(cov)
 
-@DOCSTRING(cor)
-
-@DOCSTRING(corrcoef)
+@DOCSTRING(corr)
 
 @DOCSTRING(spearman)
 
--- a/doc/refcard/refcard.tex	Tue Sep 20 15:33:10 2011 -0400
+++ b/doc/refcard/refcard.tex	Tue Sep 20 15:38:24 2011 -0400
@@ -863,14 +863,14 @@
 gray2ind ({\it i}, {\it n})&convert gray scale to Octave image\cr
 image ({\it img}, {\it zoom})&display an Octave image matrix\cr
 imagesc ({\it img}, {\it zoom})&display scaled matrix as image\cr
+imread ({\it file})&load an image file\cr
 imshow ({\it img}, {\it map})&display Octave image\cr
 imshow ({\it i}, {\it n})&display gray scale image\cr
 imshow ({\it r}, {\it g}, {\it b})&display RGB image\cr
+imwrite ({\it img}, {\it file})&write images in various file formats\cr
 ind2gray ({\it img}, {\it map})&convert Octave image to gray scale\cr
 ind2rgb ({\it img}, {\it map})&convert indexed image to RGB\cr
-loadimage ({\it file})&load an image file\cr
 rgb2ind ({\it r}, {\it g}, {\it b})&convert RGB to Octave image\cr
-\omit\tt saveimage ({\it file}, {\it img}, {\it fmt}, {\it map})\quad\rm
 save a matrix to {\it file}\span\cr
 \endsec
 
--- a/etc/OLD-ChangeLogs/ChangeLog	Tue Sep 20 15:33:10 2011 -0400
+++ b/etc/OLD-ChangeLogs/ChangeLog	Tue Sep 20 15:38:24 2011 -0400
@@ -2,6 +2,10 @@
 
 	* NEWS: Add colstyle to list of new functions for 3.4
 
+2011-04-08  Rik  <octave@nomad.inbox5.com>
+
+	* NEWS: Deprecate studentize(), add new function zscore().
+
 2011-04-04  Rik  <octave@nomad.inbox5.com>
 
 	* NEWS: Add perror, strerror to list of functions deprecated in 3.4
@@ -88,6 +92,11 @@
 
 	* NEWS: Use indentation of 2 spaces rather than 3 in code examples.
 
+2011-02-08  John W. Eaton  <jwe@octave.org>
+
+	* NEWS: New section for 3.6.  List deprecated functions that
+	have been removed for 3.6.
+
 2011-02-08  Ben Abbott  <bpabbott@mac.com>
 
 	* README.MacOS: Add detail.
--- a/etc/OLD-ChangeLogs/doc-ChangeLog	Tue Sep 20 15:33:10 2011 -0400
+++ b/etc/OLD-ChangeLogs/doc-ChangeLog	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,7 @@
+2011-04-16  Ben Abbott  <bpabbott@mac.com>
+
+	* interpreter/plot.txi: Clarify that inheritance of default property
+	values only applies to the named object type.
 2011-04-14  Rik  <octave@nomad.inbox5.com>
 
 	* interpreter/plot.txi: Add colstyle function to documentation.
@@ -16,6 +20,11 @@
 	* interpreter/func.txi: Add discussion of isargout to Ignoring
 	Arguments section of documentation.
 
+2011-04-08  Rik  <octave@nomad.inbox5.com>
+
+	* interpreter/stats.txi: Deprecate studentize(), replace with
+	zscore().
+
 2011-04-07  Rik  <octave@nomad.inbox5.com>
 
 	* interpreter/Makefile.am: Add spellcheck target to documentation
@@ -42,7 +51,7 @@
 
 2011-04-04  Rik  <octave@nomad.inbox5.com>
 
-	* interpreter/doccheck/aspell-octave.en.pws, interpreter/nonlin.txi, 
+	* interpreter/doccheck/aspell-octave.en.pws, interpreter/nonlin.txi,
 	interpreter/tips.txi: Spellcheck documentation for 3.4.1 release.
 
 2011-04-04  Rik  <octave@nomad.inbox5.com>
--- a/etc/OLD-ChangeLogs/liboctave-ChangeLog	Tue Sep 20 15:33:10 2011 -0400
+++ b/etc/OLD-ChangeLogs/liboctave-ChangeLog	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,7 @@
+2011-04-12  Rik  <octave@nomad.inbox5.com>
+
+	* LSODE.cc: Add semicolon to error messages to prevent run-together text.
+
 2011-04-01  Jordi Gutiérrez Hermoso  <jordigh@gmail.com>
 
 	* MatrixType (MatrixType::operator =): Plug memory leak due to
--- a/etc/OLD-ChangeLogs/scripts-ChangeLog	Tue Sep 20 15:33:10 2011 -0400
+++ b/etc/OLD-ChangeLogs/scripts-ChangeLog	Tue Sep 20 15:38:24 2011 -0400
@@ -1,8 +1,47 @@
+2011-04-18  Paul Boven  <p.boven@xs4all.nl>
+
+	* image/image.m: Fixed naming of variables in texinfo
+
+2011-04-17  Patrick Häcker  <magicmuscleman>
+
+	* strings/mat2str.m: Limit the number of digits to one less than
+	available for double.
+
+2011-04-15  Kai Habel  <kai.habel@gmx.de>
+
+	* general/interp1.m, polynomial/mkpp.m, polynomial/pchip.m,
+	polynomial/ppder.m, polynomial/ppint.m, polynomial/ppjumps.m,
+	polynomial/ppval.m, polynomial/spline.m, polynomial/unmkpp.m:
+	Make functions more compatible with respect to handling of
+	picewise polynoms (pp). Rename pp-struct elements.
+	Handle nD-arguments correctly. Tests added.
+	(bugs #32040, #32045)
+
 2011-04-13  David Bateman  <dbateman@free.fr>
 
 	* plot/colstyle.m : New function.
 	* plot/module.mk plot_FCN_FILES) : Add it here.
 
+2011-04-13  Rik  <octave@nomad.inbox5.com>
+
+	* help/__makeinfo__.m: Simplify function by using regular expressions.
+	Eliminate third input argument see_also function.
+
+2011-04-13  Rik  <octave@nomad.inbox5.com>
+
+	* general/isdir.m, general/isequal.m, general/isequalwithequalnans.m,
+	general/isscalar.m, general/issquare.m, general/isvector.m: Refactor
+	code to put input validation first.
+
+	* general/iscolumn.m, general/isrow.m : Remove useless initialization
+	of output variable.
+
+	* general/isa.m: Add additional tests for various classes.
+
+2011-04-13  Rik  <octave@nomad.inbox5.com>
+
+	* ChangeLog: Remove results of bad merge in ChangeLog.
+
 2011-04-12  Ben Abbott  <bpabbott@mac.com>
 
 	* miscellaneous/getappdata.m: If no property name is provided, return
@@ -20,10 +59,21 @@
 
 2011-04-08  Rik  <octave@nomad.inbox5.com>
 
+	* deprecated/module.mk, statistics/base/center.m,
+	statistics/base/module.mk: Deprecate studentize(), replace with
+	zscore().
+
+2011-04-08  Rik  <octave@nomad.inbox5.com>
+
 	* linear-algebra/cond.m, linear-algebra/expm.m, linear-algebra/logm.m,
 	linear-algebra/null.m, linear-algebra/orth.m, linear-algebra/rank.m,
 	linear-algebra/rref.m: Improve docstrings.
 
+2011-04-08  Rik  <octave@nomad.inbox5.com>
+
+	* statistics/base/mode.m, statistics/base/quantile.m: Return output
+	of same class as input.
+
 2011-04-06  Rik  <octave@nomad.inbox5.com>
 
 	* miscellaneous/pack.m: Improve docstring.
@@ -397,6 +447,25 @@
 
 	* plot/__go_draw_axes__.m: Properly set fontspec for legends.
 
+2011-02-08  John W. Eaton  <jwe@octave.org>
+
+	* deprecated/complement.m, deprecated/create_set.m,
+	deprecated/dmult.m, deprecated/iscommand.m,
+	deprecated/israwcommand.m, deprecated/lchol.m,
+	deprecated/loadimage.m, deprecated/mark_as_command.m,
+	deprecated/mark_as_rawcommand.m, deprecated/spatan2.m,
+	deprecated/spchol2inv.m, deprecated/spcholinv.m,
+	deprecated/spchol.m, deprecated/spcumprod.m,
+	deprecated/spcumsum.m, deprecated/spdet.m, deprecated/spdiag.m,
+	deprecated/spfind.m, deprecated/spinv.m, deprecated/spkron.m,
+	deprecated/splchol.m, deprecated/split.m, deprecated/splu.m,
+	deprecated/spmax.m, deprecated/spmin.m, deprecated/spprod.m,
+	deprecated/spqr.m, deprecated/spsum.m, deprecated/spsumsq.m,
+	deprecated/str2mat.m, deprecated/unmark_command.m,
+	deprecated/unmark_rawcommand.m:
+	Remove functions deprecated in version 3.2.
+	* module.mk (deprecated_FCN_FILES): Remove them from the list.
+
 2011-02-05  David Bateman  <dbateman@free.fr>
 
 	* plot/legend.m: Allow the location and orientation to be set
--- a/etc/OLD-ChangeLogs/src-ChangeLog	Tue Sep 20 15:33:10 2011 -0400
+++ b/etc/OLD-ChangeLogs/src-ChangeLog	Tue Sep 20 15:38:24 2011 -0400
@@ -1,10 +1,15 @@
+2011-04-19  Kai Habel  <kai.habel@gmx.de>
+
+	* src/DLD-FUNCTIONS/__init_fltk__.cc(plot_window::plot_window):
+	Instantiate canvas before uimenu.
+
 2011-04-13  Rik  <octave@nomad.inbox5.com>
 
 	* help.cc: Add spaces after commas in @seealso blocks.
 
 2011-04-12  Rik  <octave@nomad.inbox5.com>
 
-	* load-path.cc (restoredefaultpath): Correct use of it's -> its in 
+	* load-path.cc (restoredefaultpath): Correct use of it's -> its in
 	documentation.
 
 2011-04-10  John Eaton  <jwe@octave.org>
@@ -90,7 +95,7 @@
 
 	* DLD-FUNCTIONS/inv.cc (inv, inverse), DLD-FUNCTIONS/tril.cc (tril),
 	data.cc (cumsum, szie), file-io.cc (fgets), ov-typeinfo.cc (typeinfo),
-	ov-usr-fcn.cc (nargout), utils.cc (make_absolute_filename), 
+	ov-usr-fcn.cc (nargout), utils.cc (make_absolute_filename),
 	variables.cc (who): Improve docstrings
 
 2011-03-25  John W. Eaton  <jwe@octave.org>
@@ -342,6 +347,10 @@
 
 2011-02-08  John W. Eaton  <jwe@octave.org>
 
+	* DLD-FUNCTIONS/chol.cc: Delete obsolete test of spcholinv.
+
+2011-02-08  John W. Eaton  <jwe@octave.org>
+
 	* oct-parse.yy (parse_fcn_file): Don't warn about coercing
 	nested functions to subfunctions if yyparse failed.
 
--- a/etc/OLD-ChangeLogs/test-ChangeLog	Tue Sep 20 15:33:10 2011 -0400
+++ b/etc/OLD-ChangeLogs/test-ChangeLog	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,9 @@
+2011-04-11  Rik  <octave@nomad.inbox5.com>
+
+	* fntests.m: Remove deprecated and private functions from list of 
+	functions requiring tests.  Count functions with %!demo blocks as
+	having tests.
+
 2011-04-03  Rik  <octave@nomad.inbox5.com>
 
 	* test_diag_perm.m: Reverse previous changeset.  Return 3-input form
--- a/etc/README.MacOS	Tue Sep 20 15:33:10 2011 -0400
+++ b/etc/README.MacOS	Tue Sep 20 15:38:24 2011 -0400
@@ -334,67 +334,83 @@
 includes a port file for octave-devel.  To build and run the most recent
 development snapshots, enter the commands below.
 
-    sudo port selfupdate
-    sudo port install octave-devel
+  sudo port selfupdate
+  sudo port install octave-devel
 
 To build the developers sources in one's own way, or if MacPorts' version is
 outdated, a custom port file can be added.  This requires setting up a local
 port file repository (link below).
 
-    http://guide.macports.org/#development.local-repositories
+  http://guide.macports.org/#development.local-repositories
 
 The octave-devel port file may be used as an initial starting point.  The port
 file is accessible from the web at the link below.
 
-    http://trac.macports.org/browser/trunk/dports/math/octave-devel/Portfile
+  http://trac.macports.org/browser/trunk/dports/math/octave-devel/Portfile
 
 It is also available locally at the location below.  The parameter ${prefix} is
 corresponds to where MacPorts is install, which by default is "/opt/local".
 
-    ${prefix}/var/macports/sources/rsync.macports.org/release/ports/math/octave-devel/Portfile
+  ${prefix}/var/macports/sources/rsync.macports.org/release/ports/math/octave-devel/Portfile
+
+If the Portfile is missing the dependencies, epstools, epstoedit, and transfig,
+those should be installed manually or added to the Portfile. To install
+manually, type the command below.
+
+  sudo port install epstools epstoedit transfig
 
 The local source tarball must be placed in the location below, where ${name}
 and ${distname} are each specified in the port file.
 
-    ${prefix}/var/macports/distfiles/${name}/${disname}.tar.gz
+  ${prefix}/var/macports/distfiles/${name}/${disname}.tar.gz
 
 
 2.4.2 Building for Active Development of Octave
 -----------------------------------------------
 
-To satisfy Octave's dependencies, first install the octave-devel port.
-
-    sudo port selfupdate
-    sudo port install octave-devel
+To satisfy most of Octave's dependencies, first install the octave-devel port.
 
-Next run octave to determine the configure options needed to build Octave
-using MacPorts.  At Octave's prompt type the command below and make note of
-the result, ${config_opts}.
-
-    octave:1> octave_config_info.config_opts
+  sudo port selfupdate
+  sudo port install octave-devel
 
 Now uninstall the Octave port.
 
-    sudo port deactivate octave-devel
+  sudo port deactivate octave-devel
+
+This will remove Octave and leave its dependencies in place. Some additional
+dependencies may be needed.
+
+  sudo port install epstools epstoedit transfig
+
+Octave may now be built from a local mercurial archive by typing the commands
+below (these assume gcc-4.4 is installed by macports).
 
-This will remove Octave and leave its dependencies in place.  Now Octave may
-be built from the local mercurial archive by typing the commands below, where
-the configure options mentioned above are substituted for the parameter
-${config_opts}.  If the sources being built are from the mercurial archive,
-then ./autogen.sh must be run prior to ./configure.
-
-    ./configure ${config_opts}
-    make
+  ./autogen.sh
+  export PREFIX=/opt/local
+  export CC=/opt/local/bin/gcc-mp-4.4
+  export CXX=/opt/local/bin/g++-mp-4.4
+  export CXXCPP="/opt/local/bin/g++-mp-4.4 -E"
+  export F77=/opt/local/bin/gfortran-mp-4.4
+  export FC=/opt/local/bin/gfortran-mp-4.4
+  export CXXFLAGS="-pipe -O2 -m64"
+  export FFLAGS="$CXXFLAGS -D_THREAD_SAFE -pthread"
+  export CFLAGS="$FFLAGS -lstdc++"
+  export LDFLAGS=-L$PREFIX/lib
+  export CPPFLAGS=-I$PREFIX/include
+  export BLAS_LIBS="-lcblas -lf77blas -latlas"
+  export LAPACK_LIBS=-llapack
+  ./configure --prefix="/opt/local" --without-framework-carbon --with-x
+  make
 
 Octave's integrated tests may be run.
 
-    make check
+  make check
 
-However, "make install" should not be run as it may damage or corrupt the
-MacPorts installation.  To run Octave, type the command below from the root of
-the mercurial archive.
+"make install" should not be run as it will bypass the macports package 
+management.  To run Octave, type the command below from the root of the
+mercurial archive.
 
-    ./run-octave
+  ./run-octave
 
 
 John W. Eaton
--- a/libcruft/Makefile.am	Tue Sep 20 15:33:10 2011 -0400
+++ b/libcruft/Makefile.am	Tue Sep 20 15:38:24 2011 -0400
@@ -3,17 +3,17 @@
 # Copyright (C) 1993-2011 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 3 of the License, 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, see
 # <http://www.gnu.org/licenses/>.
@@ -34,6 +34,13 @@
   @CRUFT_DLL_DEFS@ \
   $(AM_CPPFLAGS)
 
+include link-deps.mk
+
+libcruft_la_LIBADD = \
+  libranlib.la \
+  ../libgnu/libgnu.la \
+  $(LIBCRUFT_LINK_DEPS)
+
 # Increment these as needed and according to the rules in the libtool
 # manual:
 libcruft_current = 0
@@ -46,13 +53,8 @@
   -version-info $(libcruft_version_info) \
   $(NO_UNDEFINED_LDFLAG) \
   @XTRA_CRUFT_SH_LDFLAGS@ \
-  -bindir $(bindir)
-
-libcruft_la_LIBADD = \
-  ../libgnu/libgnu.la \
-  libranlib.la \
-  $(LAPACK_LIBS) $(BLAS_LIBS) \
-  $(FLIBS)
+  -bindir $(bindir) \
+  $(LIBCRUFT_LINK_OPTS)
 
 libcruft_la_DEPENDENCIES = cruft.def
 
--- a/libcruft/blas-xtra/cdotc3.f	Tue Sep 20 15:33:10 2011 -0400
+++ b/libcruft/blas-xtra/cdotc3.f	Tue Sep 20 15:38:24 2011 -0400
@@ -19,7 +19,7 @@
 c <http://www.gnu.org/licenses/>.
 c
       subroutine cdotc3(m,n,k,a,b,c)
-c purpose:      a 3-dimensional dot product. 
+c purpose:      a 3-dimensional dot product.
 c               c = sum (conj (a) .* b, 2), where a and b are 3d arrays.
 c arguments:
 c m,n,k (in)    the dimensions of a and b
--- a/libcruft/blas-xtra/cmatm3.f	Tue Sep 20 15:33:10 2011 -0400
+++ b/libcruft/blas-xtra/cmatm3.f	Tue Sep 20 15:38:24 2011 -0400
@@ -19,7 +19,7 @@
 c <http://www.gnu.org/licenses/>.
 c
       subroutine cmatm3(m,n,k,np,a,b,c)
-c purpose:      a 3-dimensional matrix product. 
+c purpose:      a 3-dimensional matrix product.
 c               given a (m,k,np) array a and (k,n,np) array b,
 c               calculates a (m,n,np) array c such that
 c                 for i = 1:np
@@ -28,8 +28,8 @@
 c arguments:
 c m,n,k (in)    the dimensions
 c np (in)       number of multiplications
-c a (in)        a complex input array, size (m,k,np) 
-c b (in)        a complex input array, size (k,n,np) 
+c a (in)        a complex input array, size (m,k,np)
+c b (in)        a complex input array, size (k,n,np)
 c c (out)       a complex output array, size (m,n,np)
       integer m,n,k,np
       complex a(m*k,np),b(k*n,np)
--- a/libcruft/blas-xtra/ddot3.f	Tue Sep 20 15:33:10 2011 -0400
+++ b/libcruft/blas-xtra/ddot3.f	Tue Sep 20 15:38:24 2011 -0400
@@ -19,7 +19,7 @@
 c <http://www.gnu.org/licenses/>.
 c
       subroutine ddot3(m,n,k,a,b,c)
-c purpose:      a 3-dimensional dot product. 
+c purpose:      a 3-dimensional dot product.
 c               c = sum (a .* b, 2), where a and b are 3d arrays.
 c arguments:
 c m,n,k (in)    the dimensions of a and b
--- a/libcruft/blas-xtra/dmatm3.f	Tue Sep 20 15:33:10 2011 -0400
+++ b/libcruft/blas-xtra/dmatm3.f	Tue Sep 20 15:38:24 2011 -0400
@@ -19,7 +19,7 @@
 c <http://www.gnu.org/licenses/>.
 c
       subroutine dmatm3(m,n,k,np,a,b,c)
-c purpose:      a 3-dimensional matrix product. 
+c purpose:      a 3-dimensional matrix product.
 c               given a (m,k,np) array a and (k,n,np) array b,
 c               calculates a (m,n,np) array c such that
 c                 for i = 1:np
@@ -28,8 +28,8 @@
 c arguments:
 c m,n,k (in)    the dimensions
 c np (in)       number of multiplications
-c a (in)        a double prec. input array, size (m,k,np) 
-c b (in)        a double prec. input array, size (k,n,np) 
+c a (in)        a double prec. input array, size (m,k,np)
+c b (in)        a double prec. input array, size (k,n,np)
 c c (out)       a double prec. output array, size (m,n,np)
       integer m,n,k,np
       double precision a(m*k,np),b(k*n,np)
--- a/libcruft/blas-xtra/sdot3.f	Tue Sep 20 15:33:10 2011 -0400
+++ b/libcruft/blas-xtra/sdot3.f	Tue Sep 20 15:38:24 2011 -0400
@@ -19,7 +19,7 @@
 c <http://www.gnu.org/licenses/>.
 c
       subroutine sdot3(m,n,k,a,b,c)
-c purpose:      a 3-dimensional dot product. 
+c purpose:      a 3-dimensional dot product.
 c               c = sum (a .* b, 2), where a and b are 3d arrays.
 c arguments:
 c m,n,k (in)    the dimensions of a and b
--- a/libcruft/blas-xtra/smatm3.f	Tue Sep 20 15:33:10 2011 -0400
+++ b/libcruft/blas-xtra/smatm3.f	Tue Sep 20 15:38:24 2011 -0400
@@ -19,7 +19,7 @@
 c <http://www.gnu.org/licenses/>.
 c
       subroutine smatm3(m,n,k,np,a,b,c)
-c purpose:      a 3-dimensional matrix product. 
+c purpose:      a 3-dimensional matrix product.
 c               given a (m,k,np) array a and (k,n,np) array b,
 c               calculates a (m,n,np) array c such that
 c                 for i = 1:np
@@ -28,8 +28,8 @@
 c arguments:
 c m,n,k (in)    the dimensions
 c np (in)       number of multiplications
-c a (in)        a real input array, size (m,k,np) 
-c b (in)        a real input array, size (k,n,np) 
+c a (in)        a real input array, size (m,k,np)
+c b (in)        a real input array, size (k,n,np)
 c c (out)       a real output array, size (m,n,np)
       integer m,n,k,np
       real a(m*k,np),b(k*n,np)
--- a/libcruft/blas-xtra/zdotc3.f	Tue Sep 20 15:33:10 2011 -0400
+++ b/libcruft/blas-xtra/zdotc3.f	Tue Sep 20 15:38:24 2011 -0400
@@ -19,7 +19,7 @@
 c <http://www.gnu.org/licenses/>.
 c
       subroutine zdotc3(m,n,k,a,b,c)
-c purpose:      a 3-dimensional dot product. 
+c purpose:      a 3-dimensional dot product.
 c               c = sum (conj (a) .* b, 2), where a and b are 3d arrays.
 c arguments:
 c m,n,k (in)    the dimensions of a and b
--- a/libcruft/blas-xtra/zmatm3.f	Tue Sep 20 15:33:10 2011 -0400
+++ b/libcruft/blas-xtra/zmatm3.f	Tue Sep 20 15:38:24 2011 -0400
@@ -19,7 +19,7 @@
 c <http://www.gnu.org/licenses/>.
 c
       subroutine zmatm3(m,n,k,np,a,b,c)
-c purpose:      a 3-dimensional matrix product. 
+c purpose:      a 3-dimensional matrix product.
 c               given a (m,k,np) array a and (k,n,np) array b,
 c               calculates a (m,n,np) array c such that
 c                 for i = 1:np
@@ -28,8 +28,8 @@
 c arguments:
 c m,n,k (in)    the dimensions
 c np (in)       number of multiplications
-c a (in)        a double complex input array, size (m,k,np) 
-c b (in)        a double complex input array, size (k,n,np) 
+c a (in)        a double complex input array, size (m,k,np)
+c b (in)        a double complex input array, size (k,n,np)
 c c (out)       a double complex output array, size (m,n,np)
       integer m,n,k,np
       double complex a(m*k,np),b(k*n,np)
--- a/libcruft/lapack-xtra/crsf2csf.f	Tue Sep 20 15:33:10 2011 -0400
+++ b/libcruft/lapack-xtra/crsf2csf.f	Tue Sep 20 15:38:24 2011 -0400
@@ -32,7 +32,7 @@
 
          y = t(j+1,j)
          if (y /= 0) then
-c 2x2 block, form Givens rotation [c, i*s; i*s, c] 
+c 2x2 block, form Givens rotation [c, i*s; i*s, c]
            x = t(j,j)
            z = t(j,j+1)
            c(j) = sqrt(z/(z-y))
@@ -42,7 +42,7 @@
 c apply all rotations to t(1:j+1,j+1)
            call crcrot1(j+1,t(1,j+1),c,s)
 c apply new rotation to columns j,j+1
-           call crcrot2(j+1,t(1,j),t(1,j+1),c(j),s(j))           
+           call crcrot2(j+1,t(1,j),t(1,j+1),c(j),s(j))
 c zero subdiagonal entry, skip next row
            t(j+1,j) = 0
            c(j+1) = 1
--- a/libcruft/lapack-xtra/zrsf2csf.f	Tue Sep 20 15:33:10 2011 -0400
+++ b/libcruft/lapack-xtra/zrsf2csf.f	Tue Sep 20 15:38:24 2011 -0400
@@ -32,7 +32,7 @@
 
          y = t(j+1,j)
          if (y /= 0) then
-c 2x2 block, form Givens rotation [c, i*s; i*s, c] 
+c 2x2 block, form Givens rotation [c, i*s; i*s, c]
            x = t(j,j)
            z = t(j,j+1)
            c(j) = sqrt(z/(z-y))
@@ -42,7 +42,7 @@
 c apply all rotations to t(1:j+1,j+1)
            call zrcrot1(j+1,t(1,j+1),c,s)
 c apply new rotation to columns j,j+1
-           call zrcrot2(j+1,t(1,j),t(1,j+1),c(j),s(j))           
+           call zrcrot2(j+1,t(1,j),t(1,j+1),c(j),s(j))
 c zero subdiagonal entry, skip next row
            t(j+1,j) = 0
            c(j+1) = 1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libcruft/link-deps.mk	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,30 @@
+## The following libraries may be needed to satisfy gnulib dependencies:
+##
+##   $(COPYSIGN_LIBM)
+##   $(FLOOR_LIBM)
+##   $(GETHOSTNAME_LIB)
+##   $(LIBSOCKET)
+##   $(LIB_NANOSLEEP)
+##   $(LTLIBINTL)
+##   $(ROUNDF_LIBM)
+##   $(ROUND_LIBM)
+##   $(TRUNCF_LIBM)
+##   $(TRUNC_LIBM)
+
+LIBCRUFT_LINK_DEPS = \
+  $(COPYSIGN_LIBM) \
+  $(FLOOR_LIBM) \
+  $(GETHOSTNAME_LIB) \
+  $(LIBSOCKET) \
+  $(LIB_NANOSLEEP) \
+  $(LTLIBINTL) \
+  $(ROUNDF_LIBM) \
+  $(ROUND_LIBM) \
+  $(TRUNCF_LIBM) \
+  $(TRUNC_LIBM) \
+  $(LAPACK_LIBS) \
+  $(BLAS_LIBS) \
+  $(FLIBS) \
+  $(LIBS)
+
+LIBCRUFT_LINK_OPTS =
--- a/liboctave/Array.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/Array.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -2485,7 +2485,7 @@
         }
       else
         {
-          // Create diag matrix from vector  
+          // Create diag matrix from vector
           octave_idx_type roff = 0;
           octave_idx_type coff = 0;
           if (k > 0)
--- a/liboctave/CColVector.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/CColVector.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -242,7 +242,7 @@
 ComplexColumnVector
 conj (const ComplexColumnVector& a)
 {
-  return do_mx_unary_map<Complex, Complex, std::conj> (a);
+  return do_mx_unary_map<Complex, Complex, std::conj<double> > (a);
 }
 
 // resize is the destructive equivalent for this one
--- a/liboctave/CMatrix.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/CMatrix.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -921,7 +921,7 @@
 ComplexMatrix
 conj (const ComplexMatrix& a)
 {
-  return do_mx_unary_map<Complex, Complex, std::conj> (a);
+  return do_mx_unary_map<Complex, Complex, std::conj<double> > (a);
 }
 
 // resize is the destructive equivalent for this one
--- a/liboctave/CNDArray.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/CNDArray.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -760,7 +760,7 @@
 ComplexNDArray
 conj (const ComplexNDArray& a)
 {
-  return do_mx_unary_map<Complex, Complex, std::conj> (a);
+  return do_mx_unary_map<Complex, Complex, std::conj<double> > (a);
 }
 
 ComplexNDArray&
--- a/liboctave/CRowVector.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/CRowVector.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -234,7 +234,7 @@
 ComplexRowVector
 conj (const ComplexRowVector& a)
 {
-  return do_mx_unary_map<Complex, Complex, std::conj> (a);
+  return do_mx_unary_map<Complex, Complex, std::conj<double> > (a);
 }
 
 // resize is the destructive equivalent for this one
--- a/liboctave/DASPK-opts.in	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/DASPK-opts.in	Tue Sep 20 15:38:24 2011 -0400
@@ -1,17 +1,17 @@
 # Copyright (C) 2002-2011 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 3 of the License, 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, see
 # <http://www.gnu.org/licenses/>.
@@ -262,7 +262,7 @@
 A vector of the same length as the state specifying the type of
 inequality constraint.  Each element of the vector corresponds to an
 element of the state and should be assigned one of the following
-codes 
+codes
 
 @table @asis
 @item -2
--- a/liboctave/DASRT-opts.in	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/DASRT-opts.in	Tue Sep 20 15:38:24 2011 -0400
@@ -1,17 +1,17 @@
 # Copyright (C) 2002-2011 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 3 of the License, 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, see
 # <http://www.gnu.org/licenses/>.
--- a/liboctave/DASSL-opts.in	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/DASSL-opts.in	Tue Sep 20 15:38:24 2011 -0400
@@ -1,17 +1,17 @@
 # Copyright (C) 2002-2011 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 3 of the License, 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, see
 # <http://www.gnu.org/licenses/>.
--- a/liboctave/LSODE-opts.in	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/LSODE-opts.in	Tue Sep 20 15:38:24 2011 -0400
@@ -1,17 +1,17 @@
 # Copyright (C) 2002-2011 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 3 of the License, 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, see
 # <http://www.gnu.org/licenses/>.
--- a/liboctave/LSODE.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/LSODE.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -292,7 +292,7 @@
     case -2:  // excess accuracy requested (tolerances too small).
     case -3:  // invalid input detected (see printed message).
     case -4:  // repeated error test failures (check all inputs).
-    case -5:  // repeated convergence failures (perhaps bad jacobian
+    case -5:  // repeated convergence failures (perhaps bad Jacobian
               // supplied or wrong choice of mf or tolerances).
     case -6:  // error weight became zero during problem. (solution
               // component i vanished, and atol or atol(i) = 0.)
@@ -349,13 +349,13 @@
 
     case -4:
       retval = std::string ("repeated error test failures (t = ")
-        + t_curr + "check all inputs)";
+        + t_curr + "; check all inputs)";
       break;
 
     case -5:
       retval = std::string ("repeated convergence failures (t = ")
         + t_curr
-        + "perhaps bad jacobian supplied or wrong choice of integration method or tolerances)";
+        + "; perhaps bad Jacobian supplied or wrong choice of integration method or tolerances)";
       break;
 
     case -6:
--- a/liboctave/MArray.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/MArray.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -264,7 +264,7 @@
   if (a.is_shared ())
     a = a + b;
   else
-    do_mm_inplace_op<T, T> (a, b, mx_inline_add2, "+=");
+    do_mm_inplace_op<T, T> (a, b, mx_inline_add2, mx_inline_add2, "+=");
   return a;
 }
 
@@ -275,7 +275,7 @@
   if (a.is_shared ())
     a = a - b;
   else
-    do_mm_inplace_op<T, T> (a, b, mx_inline_sub2, "-=");
+    do_mm_inplace_op<T, T> (a, b, mx_inline_sub2, mx_inline_sub2, "-=");
   return a;
 }
 
@@ -287,7 +287,7 @@
   if (a.is_shared ())
     return a = product (a, b);
   else
-    do_mm_inplace_op<T, T> (a, b, mx_inline_mul2, ".*=");
+    do_mm_inplace_op<T, T> (a, b, mx_inline_mul2, mx_inline_mul2, ".*=");
   return a;
 }
 
@@ -298,7 +298,7 @@
   if (a.is_shared ())
     return a = quotient (a, b);
   else
-    do_mm_inplace_op<T, T> (a, b, mx_inline_div2, "./=");
+    do_mm_inplace_op<T, T> (a, b, mx_inline_div2, mx_inline_div2, "./=");
   return a;
 }
 
@@ -339,7 +339,7 @@
   MArray<T> \
   FCN (const MArray<T>& a, const MArray<T>& b) \
   { \
-    return do_mm_binary_op<T, T, T> (a, b, FN, #FCN); \
+    return do_mm_binary_op<T, T, T> (a, b, FN, FN, FN, #FCN); \
   }
 
 MARRAY_NDND_OP (operator +, +, mx_inline_add)
--- a/liboctave/MDiagArray2.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/MDiagArray2.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -82,7 +82,7 @@
   { \
     if (a.d1 != b.d1 || a.d2 != b.d2) \
       gripe_nonconformant (#FCN, a.d1, a.d2, b.d1, b.d2); \
-    return MDiagArray2<T> (do_mm_binary_op<T, T, T> (a, b, FN, #FCN), a.d1, a.d2); \
+    return MDiagArray2<T> (do_mm_binary_op<T, T, T> (a, b, FN, FN, FN, #FCN), a.d1, a.d2); \
   }
 
 MARRAY_DADA_OP (operator +, +, mx_inline_add)
--- a/liboctave/MSparse.h	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/MSparse.h	Tue Sep 20 15:38:24 2011 -0400
@@ -65,6 +65,8 @@
 
   explicit MSparse (octave_idx_type r, octave_idx_type c, T val) : Sparse<T> (r, c, val) { }
 
+  explicit MSparse (const PermMatrix& a) : Sparse<T>(a) { }
+
   MSparse (octave_idx_type r, octave_idx_type c, octave_idx_type num_nz) : Sparse<T> (r, c, num_nz) { }
 
   ~MSparse (void) { }
--- a/liboctave/Makefile.am	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/Makefile.am	Tue Sep 20 15:38:24 2011 -0400
@@ -3,17 +3,17 @@
 # Copyright (C) 1993-2011 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 3 of the License, 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, see
 # <http://www.gnu.org/licenses/>.
@@ -188,6 +188,7 @@
   base-dae.h \
   base-de.h \
   base-min.h \
+  bsxfun.h \
   byte-swap.h \
   caseless-str.h \
   cmd-edit.h \
@@ -491,21 +492,6 @@
 
 LIBOCT_READLINE_SOURCES = $(LIBOCT_READLINE_CXX_SOURCES) $(LIBOCT_READLINE_C_SOURCES)
 
-LINK_DEPS = \
-  $(RLD_FLAG) \
-  ../libcruft/libcruft.la \
-  ../libcruft/libranlib.la \
-  ../libgnu/libgnu.la \
-  $(SPARSE_XLIBS) \
-  $(ARPACK_LIBS) \
-  $(QRUPDATE_LIBS) \
-  $(FFTW_XLIBS) \
-  $(LAPACK_LIBS) $(BLAS_LIBS) \
-  $(READLINE_LIBS) $(TERM_LIBS) \
-  $(LIBGLOB) $(REGEX_LIBS) $(DL_LIBS) \
-  $(FLIBS) \
-  $(PTHREAD_LIBS) $(LIBS)
-
 liboctave_la_SOURCES = \
   $(LIBOCTAVE_CXX_SOURCES) \
   $(LIBOCTAVE_C_SOURCES) \
@@ -516,7 +502,11 @@
 nodist_liboctave_la_SOURCES = \
   $(BUILT_LIBOCTAVE_CXX_SOURCES)
 
-liboctave_la_LIBADD = $(LINK_DEPS)
+include link-deps.mk
+
+liboctave_la_LIBADD = \
+  ../libcruft/libcruft.la \
+  $(LIBOCTAVE_LINK_DEPS)
 
 liboctave_la_CPPFLAGS = \
   @OCTAVE_DLL_DEFS@ \
@@ -537,10 +527,7 @@
   -version-info $(liboctave_version_info) \
   $(NO_UNDEFINED_LDFLAG) \
   -bindir $(bindir) \
-  $(SPARSE_XLDFLAGS) \
-  $(ARPACK_LDFLAGS) \
-  $(QRUPDATE_LDFLAGS) \
-  $(FFTW_XLDFLAGS)
+  $(LIBOCTAVE_LINK_OPTS)
 
 octinclude_HEADERS = \
   $(INCS) \
--- a/liboctave/Quad-opts.in	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/Quad-opts.in	Tue Sep 20 15:38:24 2011 -0400
@@ -1,17 +1,17 @@
 # Copyright (C) 2002-2011 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 3 of the License, 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, see
 # <http://www.gnu.org/licenses/>.
@@ -33,7 +33,7 @@
   NAME = "relative tolerance"
   DOC_ITEM
 Non-negative relative tolerance.  If the absolute tolerance is zero,
-the relative tolerance must be greater than or equal to 
+the relative tolerance must be greater than or equal to
 @w{@code{max (50*eps, 0.5e-28)}}.
 
   END_DOC_ITEM
@@ -45,7 +45,7 @@
 OPTION
   NAME = "single precision absolute tolerance"
   DOC_ITEM
-Absolute tolerance for single precision; may be zero for pure relative 
+Absolute tolerance for single precision; may be zero for pure relative
 error test.
 
   END_DOC_ITEM
@@ -58,7 +58,7 @@
   NAME = "single precision relative tolerance"
   DOC_ITEM
 Non-negative relative tolerance for single precision.  If the absolute
-tolerance is zero, the relative tolerance must be greater than or equal to 
+tolerance is zero, the relative tolerance must be greater than or equal to
 @w{@code{max (50*eps, 0.5e-28)}}.
   END_DOC_ITEM
   TYPE = "float"
--- a/liboctave/Sparse-perm-op-defs.h	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/Sparse-perm-op-defs.h	Tue Sep 20 15:38:24 2011 -0400
@@ -42,14 +42,14 @@
   for (octave_idx_type j = 0; j < nc; j++)
     {
       octave_quit ();
-      
+
       OCTAVE_LOCAL_BUFFER (octave_idx_type, sidx, r.xcidx(j+1) - r.xcidx(j));
       for (octave_idx_type i = r.xcidx(j), ii = 0; i < r.xcidx(j+1); i++)
         {
           sidx[ii++]=i;
           r.xridx (i) = pcol[a.ridx (i)];
         }
-      sort.sort (r.xridx() + r.xcidx(j), sidx, r.xcidx(j+1) - r.xcidx(j)); 
+      sort.sort (r.xridx() + r.xcidx(j), sidx, r.xcidx(j+1) - r.xcidx(j));
       for (octave_idx_type i = r.xcidx(j), ii = 0; i < r.xcidx(j+1); i++)
         r.xdata(i) = a.data (sidx[ii++]);
     }
--- a/liboctave/Sparse.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/Sparse.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -50,6 +50,34 @@
 #include "oct-spparms.h"
 #include "mx-inlines.cc"
 
+#include "PermMatrix.h"
+
+template <class T>
+Sparse<T>::Sparse (const PermMatrix& a)
+  : rep (new typename Sparse<T>::SparseRep (a.rows (), a.cols (), a.rows ())),
+         dimensions (dim_vector (a.rows (), a.cols()))
+{
+  octave_idx_type n = a.rows ();
+  for (octave_idx_type i = 0; i <= n; i++)
+    cidx (i) = i;
+
+  const Array<octave_idx_type> pv = a.pvec ();
+
+  if (a.is_row_perm ())
+    {
+      for (octave_idx_type i = 0; i < n; i++)
+        ridx (pv (i)) = i;
+    }
+  else
+    {
+      for (octave_idx_type i = 0; i < n; i++)
+        ridx (i) = pv (i);
+    }
+
+  for (octave_idx_type i = 0; i < n; i++)
+    data (i) = 1.0;
+}
+
 template <class T>
 T&
 Sparse<T>::SparseRep::elem (octave_idx_type _r, octave_idx_type _c)
--- a/liboctave/Sparse.h	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/Sparse.h	Tue Sep 20 15:38:24 2011 -0400
@@ -41,6 +41,7 @@
 #include "oct-mem.h"
 
 class idx_vector;
+class PermMatrix;
 
 // Two dimensional sparse class.  Handles the reference counting for
 // all the derived classes.
@@ -195,6 +196,10 @@
     : rep (new typename Sparse<T>::SparseRep (nr, nc, nz)),
       dimensions (dim_vector (nr, nc)) { }
 
+  // Both SparseMatrix and SparseBoolMatrix need this ctor, and this
+  // is their only common ancestor.
+  explicit Sparse (const PermMatrix& a);
+
   // Type conversion case. Preserves capacity ().
   template <class U>
   Sparse (const Sparse<U>& a)
--- a/liboctave/boolNDArray.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/boolNDArray.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -149,7 +149,8 @@
   if (a.is_shared ())
     a = mx_el_and (a, b);
   else
-    do_mm_inplace_op<bool, bool> (a, b, mx_inline_and2, "operator &=");
+    do_mm_inplace_op<bool, bool> (a, b, mx_inline_and2, mx_inline_and2,
+                                  "operator &=");
 
   return a;
 }
@@ -160,7 +161,8 @@
   if (a.is_shared ())
     a = mx_el_or (a, b);
   else
-    do_mm_inplace_op<bool, bool> (a, b, mx_inline_or2, "operator |=");
+    do_mm_inplace_op<bool, bool> (a, b, mx_inline_or2, mx_inline_or2,
+                                  "operator |=");
 
   return a;
 }
--- a/liboctave/boolSparse.h	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/boolSparse.h	Tue Sep 20 15:38:24 2011 -0400
@@ -57,6 +57,8 @@
 
   explicit SparseBoolMatrix (const boolNDArray& a) : Sparse<bool> (a) { }
 
+  explicit SparseBoolMatrix (const PermMatrix& a) : Sparse<bool> (a) { };
+
   SparseBoolMatrix (const Array<bool>& a, const idx_vector& r,
                     const idx_vector& c, octave_idx_type nr = -1,
                     octave_idx_type nc = -1, bool sum_terms = true,
--- a/liboctave/bsxfun-decl.h	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/bsxfun-decl.h	Tue Sep 20 15:38:24 2011 -0400
@@ -42,6 +42,12 @@
   BSXFUN_OP_DECL (min, ARRAY, API) \
   BSXFUN_OP_DECL (max, ARRAY, API)
 
+#define BSXFUN_MIXED_INT_DECLS(INT_TYPE, API)         \
+  BSXFUN_OP2_DECL (pow, INT_TYPE, INT_TYPE, NDArray, API)       \
+  BSXFUN_OP2_DECL (pow, INT_TYPE, INT_TYPE, FloatNDArray, API)  \
+  BSXFUN_OP2_DECL (pow, INT_TYPE, NDArray, INT_TYPE, API)       \
+  BSXFUN_OP2_DECL (pow, INT_TYPE, FloatNDArray, INT_TYPE, API)
+
 #define BSXFUN_STDREL_DECLS(ARRAY, API) \
   BSXFUN_REL_DECL (eq, ARRAY, API) \
   BSXFUN_REL_DECL (ne, ARRAY, API) \
--- a/liboctave/bsxfun-defs.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/bsxfun-defs.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -134,6 +134,77 @@
   return retval;
 }
 
+template <class R, class X>
+void
+do_inplace_bsxfun_op (Array<R>& r, const Array<X>& x,
+                      void (*op_vv) (size_t, R *, const X *),
+                      void (*op_vs) (size_t, R *, X))
+{
+  dim_vector dvr = r.dims (), dvx = x.dims ();
+  octave_idx_type nd = r.ndims ();
+  dvx.redim (nd);
+
+  const X* xvec = x.fortran_vec ();
+  R* rvec = r.fortran_vec ();
+
+  // Fold the common leading dimensions.
+  octave_idx_type start, ldr = 1;
+  for (start = 0; start < nd; start++)
+    {
+      if (dvr(start) != dvx(start))
+        break;
+      ldr *= dvr(start);
+    }
+
+  if (r.is_empty ())
+    ; // do nothing
+  else if (start == nd)
+    op_vv (r.numel (), rvec, xvec);
+  else
+    {
+      // Determine the type of the low-level loop.
+      bool xsing = false;
+      if (ldr == 1)
+        {
+          xsing = dvx(start) == 1;
+          if (xsing)
+            {
+              ldr *= dvr(start) * dvx(start);
+              start++;
+            }
+        }
+
+      dim_vector cdvx = dvx.cumulative ();
+      // Nullify singleton dims to achieve a spread effect.
+      for (int i = std::max (start, 1); i < nd; i++)
+        {
+          if (dvx(i) == 1)
+            cdvx(i-1) = 0;
+        }
+
+      octave_idx_type niter = dvr.numel (start);
+      // The index array.
+      OCTAVE_LOCAL_BUFFER_INIT (octave_idx_type, idx, nd, 0);
+      for (octave_idx_type iter = 0; iter < niter; iter++)
+        {
+          octave_quit ();
+
+          // Compute indices.
+          // FIXME: performance impact noticeable?
+          octave_idx_type xidx = cdvx.cum_compute_index (idx);
+          octave_idx_type ridx = dvr.compute_index (idx);
+
+          // Apply the low-level loop.
+          if (xsing)
+            op_vs (ldr, rvec + ridx, xvec[xidx]);
+          else
+            op_vv (ldr, rvec + ridx, xvec + xidx);
+
+          dvr.increment_index (idx + start, start);
+        }
+    }
+}
+
 #define BSXFUN_OP_DEF(OP, ARRAY) \
 ARRAY bsxfun_ ## OP (const ARRAY& x, const ARRAY& y)
 
@@ -174,4 +245,11 @@
   BSXFUN_REL_DEF_MXLOOP (gt, ARRAY, mx_inline_gt) \
   BSXFUN_REL_DEF_MXLOOP (ge, ARRAY, mx_inline_ge)
 
+//For bsxfun power with mixed integer/float types
+#define BSXFUN_POW_MIXED_MXLOOP(INT_TYPE)                              \
+  BSXFUN_OP2_DEF_MXLOOP (pow, INT_TYPE, INT_TYPE, NDArray, mx_inline_pow) \
+  BSXFUN_OP2_DEF_MXLOOP (pow, INT_TYPE, INT_TYPE, FloatNDArray, mx_inline_pow)\
+  BSXFUN_OP2_DEF_MXLOOP (pow, INT_TYPE, NDArray, INT_TYPE,  mx_inline_pow) \
+  BSXFUN_OP2_DEF_MXLOOP (pow, INT_TYPE, FloatNDArray, INT_TYPE, mx_inline_pow)
+
 #endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/liboctave/bsxfun.h	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,68 @@
+/*
+
+Copyright (C) 2011 Jordi Gutiérrez Hermoso <jordigh@octave.org>
+
+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 3 of the License, 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, see
+<http://www.gnu.org/licenses/>.
+
+*/
+#if !defined (bsxfun_h)
+#define bsxfun_h 1
+
+#include <algorithm>
+
+#include "Array.h"
+#include "dim-vector.h"
+
+inline
+bool
+is_valid_bsxfun (const dim_vector& dx, const dim_vector& dy)
+{
+  for (int i = 0; i < std::min (dx.length (), dy.length ()); i++)
+    {
+      octave_idx_type xk = dx(i), yk = dy(i);
+      // Check the three conditions for valid bsxfun dims
+      if (! ( (xk == yk) || (xk == 1 && yk > 1) || (xk > 1 && yk == 1)))
+        return false;
+    }
+  return true;
+}
+
+// since we can't change the size of the assigned-to matrix, we cannot
+// apply singleton expansion to it, so the conditions to check are
+// different here.
+inline
+bool
+is_valid_inplace_bsxfun (const dim_vector& dr, const dim_vector& dx)
+{
+  octave_idx_type drl = dr.length (), dxl = dx.length ();
+  if (drl < dxl)
+    return false;
+
+  for (int i = 0; i < drl; i++)
+    {
+      octave_idx_type rk = dr(i), xk = dx(i);
+
+      // Only two valid canditions to check; can't stretch rk
+      if (! ( (rk == xk) || (rk > 1 && xk == 1)))
+        return false;
+    }
+  return true;
+}
+
+#include "bsxfun-defs.cc"
+
+#endif
--- a/liboctave/chMatrix.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/chMatrix.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -74,8 +74,8 @@
     elem (0, i) = s[i];
 }
 
-charMatrix::charMatrix (const string_vector& s)
-  : Array<char> (dim_vector (s.length (), s.max_length ()), 0)
+charMatrix::charMatrix (const string_vector& s, char fill_value)
+  : Array<char> (dim_vector (s.length (), s.max_length ()), fill_value)
 {
   octave_idx_type nr = rows ();
 
--- a/liboctave/chMatrix.h	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/chMatrix.h	Tue Sep 20 15:38:24 2011 -0400
@@ -62,7 +62,7 @@
 
   charMatrix (const std::string& s);
 
-  charMatrix (const string_vector& s);
+  charMatrix (const string_vector& s, char fill_value = '\0');
 
   charMatrix& operator = (const charMatrix& a)
     {
--- a/liboctave/dNDArray.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/dNDArray.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -925,3 +925,5 @@
 BSXFUN_OP_DEF_MXLOOP (pow, NDArray, mx_inline_pow)
 BSXFUN_OP2_DEF_MXLOOP (pow, ComplexNDArray, ComplexNDArray,
                        NDArray, mx_inline_pow)
+BSXFUN_OP2_DEF_MXLOOP (pow, ComplexNDArray, NDArray,
+                       ComplexNDArray, mx_inline_pow)
--- a/liboctave/dNDArray.h	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/dNDArray.h	Tue Sep 20 15:38:24 2011 -0400
@@ -185,5 +185,7 @@
 BSXFUN_OP_DECL (pow, NDArray, OCTAVE_API)
 BSXFUN_OP2_DECL (pow, ComplexNDArray, ComplexNDArray,
                  NDArray, OCTAVE_API)
+BSXFUN_OP2_DECL (pow, ComplexNDArray, NDArray,
+                 ComplexNDArray, OCTAVE_API)
 
 #endif
--- a/liboctave/dSparse.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/dSparse.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -180,29 +180,6 @@
     cidx(i) = j;
 }
 
-SparseMatrix::SparseMatrix (const PermMatrix& a)
-  : MSparse<double> (a.rows (), a.cols (), a.rows ())
-{
-  octave_idx_type n = a.rows ();
-  for (octave_idx_type i = 0; i <= n; i++)
-    cidx (i) = i;
-  const Array<octave_idx_type> pv = a.pvec ();
-
-  if (a.is_row_perm ())
-    {
-      for (octave_idx_type i = 0; i < n; i++)
-        ridx (pv (i)) = i;
-    }
-  else
-    {
-      for (octave_idx_type i = 0; i < n; i++)
-        ridx (i) = pv (i);
-    }
-
-  for (octave_idx_type i = 0; i < n; i++)
-    data (i) = 1.0;
-}
-
 bool
 SparseMatrix::operator == (const SparseMatrix& a) const
 {
--- a/liboctave/dSparse.h	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/dSparse.h	Tue Sep 20 15:38:24 2011 -0400
@@ -82,7 +82,7 @@
 
   explicit SparseMatrix (const DiagMatrix& a);
 
-  explicit SparseMatrix (const PermMatrix& a);
+  explicit SparseMatrix (const PermMatrix& a) : MSparse<double>(a) { }
 
   SparseMatrix (octave_idx_type r, octave_idx_type c, octave_idx_type num_nz) : MSparse<double> (r, c, num_nz) { }
 
--- a/liboctave/fCColVector.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/fCColVector.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -242,7 +242,7 @@
 FloatComplexColumnVector
 conj (const FloatComplexColumnVector& a)
 {
-  return do_mx_unary_map<FloatComplex, FloatComplex, std::conj> (a);
+  return do_mx_unary_map<FloatComplex, FloatComplex, std::conj<float> > (a);
 }
 
 // resize is the destructive equivalent for this one
--- a/liboctave/fCMatrix.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/fCMatrix.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -923,7 +923,7 @@
 FloatComplexMatrix
 conj (const FloatComplexMatrix& a)
 {
-  return do_mx_unary_map<FloatComplex, FloatComplex, std::conj> (a);
+  return do_mx_unary_map<FloatComplex, FloatComplex, std::conj<float> > (a);
 }
 
 // resize is the destructive equivalent for this one
--- a/liboctave/fCNDArray.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/fCNDArray.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -757,7 +757,7 @@
 FloatComplexNDArray
 conj (const FloatComplexNDArray& a)
 {
-  return do_mx_unary_map<FloatComplex, FloatComplex, std::conj> (a);
+  return do_mx_unary_map<FloatComplex, FloatComplex, std::conj<float> > (a);
 }
 
 FloatComplexNDArray&
--- a/liboctave/fCRowVector.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/fCRowVector.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -234,7 +234,7 @@
 FloatComplexRowVector
 conj (const FloatComplexRowVector& a)
 {
-  return do_mx_unary_map<FloatComplex, FloatComplex, std::conj> (a);
+  return do_mx_unary_map<FloatComplex, FloatComplex, std::conj<float> > (a);
 }
 
 // resize is the destructive equivalent for this one
--- a/liboctave/fNDArray.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/fNDArray.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -885,3 +885,5 @@
 BSXFUN_OP_DEF_MXLOOP (pow, FloatNDArray, mx_inline_pow)
 BSXFUN_OP2_DEF_MXLOOP (pow, FloatComplexNDArray, FloatComplexNDArray,
                        FloatNDArray, mx_inline_pow)
+BSXFUN_OP2_DEF_MXLOOP (pow, FloatComplexNDArray, FloatNDArray,
+                       FloatComplexNDArray, mx_inline_pow)
--- a/liboctave/fNDArray.h	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/fNDArray.h	Tue Sep 20 15:38:24 2011 -0400
@@ -182,5 +182,7 @@
 BSXFUN_OP_DECL (pow, FloatNDArray, OCTAVE_API)
 BSXFUN_OP2_DECL (pow, FloatComplexNDArray, FloatComplexNDArray,
                  FloatNDArray, OCTAVE_API)
+BSXFUN_OP2_DECL (pow, FloatComplexNDArray, FloatNDArray,
+                 FloatComplexNDArray, OCTAVE_API)
 
 #endif
--- a/liboctave/int16NDArray.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/int16NDArray.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -54,3 +54,7 @@
 
 BSXFUN_STDOP_DEFS_MXLOOP (int16NDArray)
 BSXFUN_STDREL_DEFS_MXLOOP (int16NDArray)
+
+BSXFUN_OP_DEF_MXLOOP (pow, int16NDArray, mx_inline_pow)
+
+BSXFUN_POW_MIXED_MXLOOP (int16NDArray)
--- a/liboctave/int16NDArray.h	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/int16NDArray.h	Tue Sep 20 15:38:24 2011 -0400
@@ -44,6 +44,7 @@
 MINMAX_DECLS (int16NDArray, octave_int16, OCTAVE_API)
 
 BSXFUN_STDOP_DECLS (int16NDArray, OCTAVE_API)
+BSXFUN_MIXED_INT_DECLS(int16NDArray, OCTAVE_API)
 BSXFUN_STDREL_DECLS (int16NDArray, OCTAVE_API)
 
 #endif
--- a/liboctave/int32NDArray.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/int32NDArray.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -54,3 +54,6 @@
 
 BSXFUN_STDOP_DEFS_MXLOOP (int32NDArray)
 BSXFUN_STDREL_DEFS_MXLOOP (int32NDArray)
+
+BSXFUN_OP_DEF_MXLOOP (pow, int32NDArray, mx_inline_pow)
+BSXFUN_POW_MIXED_MXLOOP (int32NDArray)
--- a/liboctave/int32NDArray.h	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/int32NDArray.h	Tue Sep 20 15:38:24 2011 -0400
@@ -44,6 +44,7 @@
 MINMAX_DECLS (int32NDArray, octave_int32, OCTAVE_API)
 
 BSXFUN_STDOP_DECLS (int32NDArray, OCTAVE_API)
+BSXFUN_MIXED_INT_DECLS(int32NDArray, OCTAVE_API)
 BSXFUN_STDREL_DECLS (int32NDArray, OCTAVE_API)
 
 #endif
--- a/liboctave/int64NDArray.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/int64NDArray.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -54,3 +54,7 @@
 
 BSXFUN_STDOP_DEFS_MXLOOP (int64NDArray)
 BSXFUN_STDREL_DEFS_MXLOOP (int64NDArray)
+
+BSXFUN_OP_DEF_MXLOOP (pow, int64NDArray, mx_inline_pow)
+
+BSXFUN_POW_MIXED_MXLOOP (int64NDArray)
--- a/liboctave/int64NDArray.h	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/int64NDArray.h	Tue Sep 20 15:38:24 2011 -0400
@@ -44,6 +44,7 @@
 MINMAX_DECLS (int64NDArray, octave_int64, OCTAVE_API)
 
 BSXFUN_STDOP_DECLS (int64NDArray, OCTAVE_API)
+BSXFUN_MIXED_INT_DECLS(int64NDArray, OCTAVE_API)
 BSXFUN_STDREL_DECLS (int64NDArray, OCTAVE_API)
 
 #endif
--- a/liboctave/int8NDArray.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/int8NDArray.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -54,3 +54,6 @@
 
 BSXFUN_STDOP_DEFS_MXLOOP (int8NDArray)
 BSXFUN_STDREL_DEFS_MXLOOP (int8NDArray)
+
+BSXFUN_OP_DEF_MXLOOP (pow, int8NDArray, mx_inline_pow)
+BSXFUN_POW_MIXED_MXLOOP (int8NDArray)
--- a/liboctave/int8NDArray.h	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/int8NDArray.h	Tue Sep 20 15:38:24 2011 -0400
@@ -44,6 +44,7 @@
 MINMAX_DECLS (int8NDArray, octave_int8, OCTAVE_API)
 
 BSXFUN_STDOP_DECLS (int8NDArray, OCTAVE_API)
+BSXFUN_MIXED_INT_DECLS(int8NDArray, OCTAVE_API)
 BSXFUN_STDREL_DECLS (int8NDArray, OCTAVE_API)
 
 #endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/liboctave/link-deps.mk	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,27 @@
+include ../libcruft/link-deps.mk
+
+LIBOCTAVE_LINK_DEPS = \
+  $(SPARSE_XLIBS) \
+  $(ARPACK_LIBS) \
+  $(QRUPDATE_LIBS) \
+  $(FFTW_XLIBS) \
+  $(LAPACK_LIBS) \
+  $(BLAS_LIBS) \
+  $(READLINE_LIBS) \
+  $(TERM_LIBS) \
+  $(LIBGLOB) \
+  $(REGEX_LIBS) \
+  $(DL_LIBS) \
+  $(PTHREAD_LIBS) \
+  $(LIBS)
+
+LIBOCTAVE_LINK_OPTS = \
+  $(SPARSE_XLDFLAGS) \
+  $(ARPACK_LDFLAGS) \
+  $(QRUPDATE_LDFLAGS) \
+  $(FFTW_XLDFLAGS)
+
+if AMCOND_LINK_ALL_DEPS
+  LIBOCTAVE_LINK_DEPS += $(LIBCRUFT_LINK_DEPS)
+  LIBOCTAVE_LINK_OPTS += $(LIBCRUFT_LINK_OPTS)
+endif
--- a/liboctave/lo-utils.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/lo-utils.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -196,44 +196,57 @@
 }
 
 static inline double
-read_inf_nan_na (std::istream& is, char c, char sign = '+')
+read_inf_nan_na (std::istream& is, char c0, char sign = '+')
 {
   double d = 0.0;
 
-  switch (c)
+  switch (c0)
     {
     case 'i': case 'I':
       {
-        c = is.get ();
-        if (c == 'n' || c == 'N')
+        char c1 = is.get ();
+        if (c1 == 'n' || c1 == 'N')
           {
-            c = is.get ();
-            if (c == 'f' || c == 'F')
+            char c2 = is.get ();
+            if (c2 == 'f' || c2 == 'F')
               d = sign == '-' ? -octave_Inf : octave_Inf;
             else
-              is.putback (c);
+              {
+                is.putback (c2);
+                is.putback (c1);
+                is.putback (c0);
+                is.setstate (std::ios::failbit);
+              }
           }
         else
-          is.putback (c);
+          {
+            is.putback (c1);
+            is.putback (c0);
+            is.setstate (std::ios::failbit);
+          }
       }
       break;
 
     case 'n': case 'N':
       {
-        c = is.get ();
-        if (c == 'a' || c == 'A')
+        char c1 = is.get ();
+        if (c1 == 'a' || c1 == 'A')
           {
-            c = is.get ();
-            if (c == 'n' || c == 'N')
+            char c2 = is.get ();
+            if (c2 == 'n' || c2 == 'N')
               d = octave_NaN;
             else
               {
-                is.putback (c);
+                is.putback (c2);
                 d = octave_NA;
               }
           }
         else
-          is.putback (c);
+          {
+            is.putback (c1);
+            is.putback (c0);
+            is.setstate (std::ios::failbit);
+          }
       }
       break;
 
@@ -244,6 +257,8 @@
   return d;
 }
 
+// Read a double value.  Discard any sign on NaN and NA.
+
 template <>
 double
 octave_read_value (std::istream& is)
@@ -261,7 +276,7 @@
       {
         char c2 = 0;
         c2 = is.get ();
-        if (c2 == 'i' || c2 == 'I')
+        if (c2 == 'i' || c2 == 'I' || c2 == 'n' || c2 == 'N')
           d = read_inf_nan_na (is, c2, c1);
         else
           {
@@ -276,7 +291,7 @@
       {
         char c2 = 0;
         c2 = is.get ();
-        if (c2 == 'i' || c2 == 'I')
+        if (c2 == 'i' || c2 == 'I' || c2 == 'n' || c2 == 'N')
           d = read_inf_nan_na (is, c2, c1);
         else
           {
@@ -344,44 +359,57 @@
 }
 
 static inline float
-read_float_inf_nan_na (std::istream& is, char c, char sign = '+')
+read_float_inf_nan_na (std::istream& is, char c0, char sign = '+')
 {
   float d = 0.0;
 
-  switch (c)
+  switch (c0)
     {
     case 'i': case 'I':
       {
-        c = is.get ();
-        if (c == 'n' || c == 'N')
+        char c1 = is.get ();
+        if (c1 == 'n' || c1 == 'N')
           {
-            c = is.get ();
-            if (c == 'f' || c == 'F')
-              d = sign == '-' ? -octave_Inf : octave_Inf;
+            char c2 = is.get ();
+            if (c2 == 'f' || c2 == 'F')
+              d = sign == '-' ? -octave_Float_Inf : octave_Float_Inf;
             else
-              is.putback (c);
+              {
+                is.putback (c2);
+                is.putback (c1);
+                is.putback (c0);
+                is.setstate (std::ios::failbit);
+              }
           }
         else
-          is.putback (c);
+          {
+            is.putback (c1);
+            is.putback (c0);
+            is.setstate (std::ios::failbit);
+          }
       }
       break;
 
     case 'n': case 'N':
       {
-        c = is.get ();
-        if (c == 'a' || c == 'A')
+        char c1 = is.get ();
+        if (c1 == 'a' || c1 == 'A')
           {
-            c = is.get ();
-            if (c == 'n' || c == 'N')
-              d = octave_NaN;
+            char c2 = is.get ();
+            if (c2 == 'n' || c2 == 'N')
+              d = octave_Float_NaN;
             else
               {
-                is.putback (c);
-                d = octave_NA;
+                is.putback (c2);
+                d = octave_Float_NA;
               }
           }
         else
-          is.putback (c);
+          {
+            is.putback (c1);
+            is.putback (c0);
+            is.setstate (std::ios::failbit);
+          }
       }
       break;
 
@@ -392,6 +420,8 @@
   return d;
 }
 
+// Read a float value.  Discard any sign on NaN and NA.
+
 template <>
 float
 octave_read_value (std::istream& is)
@@ -409,7 +439,7 @@
       {
         char c2 = 0;
         c2 = is.get ();
-        if (c2 == 'i' || c2 == 'I')
+        if (c2 == 'i' || c2 == 'I' || c2 == 'n' || c2 == 'N')
           d = read_float_inf_nan_na (is, c2, c1);
         else
           {
@@ -424,7 +454,7 @@
       {
         char c2 = 0;
         c2 = is.get ();
-        if (c2 == 'i' || c2 == 'I')
+        if (c2 == 'i' || c2 == 'I' || c2 == 'n' || c2 == 'N')
           d = read_float_inf_nan_na (is, c2, c1);
         else
           {
--- a/liboctave/mx-inlines.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/mx-inlines.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -37,6 +37,8 @@
 #include "Array.h"
 #include "Array-util.h"
 
+#include "bsxfun.h"
+
 // Provides some commonly repeated, basic loop templates.
 
 template <class R, class S>
@@ -167,6 +169,9 @@
   for (size_t i = 0; i < n; i++) \
     r[i] OP logical_value (x[i]); \
 } \
+template <class X> \
+inline void F (size_t n, bool *r, X x) throw () \
+{ for (size_t i = 0; i < n; i++) r[i] OP x; }
 
 DEFMXBOOLOPEQ (mx_inline_and2, &=)
 DEFMXBOOLOPEQ (mx_inline_or2, |=)
@@ -286,7 +291,10 @@
 inline void F (size_t n, R *r, X x, const Y *y) throw () \
 { for (size_t i = 0; i < n; i++) r[i] = FUN (x, y[i]); }
 
-DEFMXMAPPER2X (mx_inline_pow, std::pow)
+// Let the compiler decide which pow to use, whichever best matches the
+// arguments provided.
+using std::pow;
+DEFMXMAPPER2X (mx_inline_pow, pow)
 
 // Arbitrary function appliers. The function is a template parameter to enable
 // inlining.
@@ -336,11 +344,12 @@
   return r;
 }
 
-
 template <class R, class X, class Y>
 inline Array<R>
 do_mm_binary_op (const Array<X>& x, const Array<Y>& y,
                  void (*op) (size_t, R *, const X *, const Y *) throw (),
+                 void (*op1) (size_t, R *, X, const Y *) throw (),
+                 void (*op2) (size_t, R *, const X *, Y) throw (),
                  const char *opname)
 {
   dim_vector dx = x.dims (), dy = y.dims ();
@@ -350,6 +359,10 @@
       op (r.length (), r.fortran_vec (), x.data (), y.data ());
       return r;
     }
+  else if (is_valid_bsxfun (dx, dy))
+    {
+      return do_bsxfun_op (x, y, op, op1, op2);
+    }
   else
     {
       gripe_nonconformant (opname, dx, dy);
@@ -381,11 +394,18 @@
 inline Array<R>&
 do_mm_inplace_op (Array<R>& r, const Array<X>& x,
                   void (*op) (size_t, R *, const X *) throw (),
+                  void (*op1) (size_t, R *, X) throw (),
                   const char *opname)
 {
   dim_vector dr = r.dims (), dx = x.dims ();
   if (dr == dx)
-    op (r.length (), r.fortran_vec (), x.data ());
+    {
+      op (r.length (), r.fortran_vec (), x.data ());
+    }
+  else if (is_valid_inplace_bsxfun (dr, dx))
+    {
+      do_inplace_bsxfun_op (r, x, op, op1);
+    }
   else
     gripe_nonconformant (opname, dr, dx);
   return r;
--- a/liboctave/mx-op-defs.h	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/mx-op-defs.h	Tue Sep 20 15:38:24 2011 -0400
@@ -72,7 +72,7 @@
   R \
   F (const V1& v1, const V2& v2) \
   { \
-    return do_mm_binary_op<R::element_type, V1::element_type, V2::element_type> (v1, v2, OP, #F); \
+    return do_mm_binary_op<R::element_type, V1::element_type, V2::element_type> (v1, v2, OP, OP, OP, #F); \
   }
 
 #define VV_BIN_OPS(R, V1, V2) \
@@ -173,7 +173,7 @@
   R \
   OP (const M1& m1, const M2& m2) \
   { \
-    return do_mm_binary_op<R::element_type, M1::element_type, M2::element_type> (m1, m2, F, #OP); \
+    return do_mm_binary_op<R::element_type, M1::element_type, M2::element_type> (m1, m2, F, F, F, #OP); \
   }
 
 #define MM_BIN_OPS(R, M1, M2) \
@@ -186,7 +186,7 @@
   boolMatrix \
   F (const M1& m1, const M2& m2) \
   { \
-    return do_mm_binary_op<bool, M1::element_type, M2::element_type> (m1, m2, OP, #F); \
+    return do_mm_binary_op<bool, M1::element_type, M2::element_type> (m1, m2, OP, OP, OP, #F); \
   }
 
 #define MM_CMP_OPS(M1, M2) \
@@ -203,7 +203,7 @@
   { \
     MNANCHK (m1, M1::element_type); \
     MNANCHK (m2, M2::element_type); \
-    return do_mm_binary_op<bool, M1::element_type, M2::element_type> (m1, m2, OP, #F); \
+    return do_mm_binary_op<bool, M1::element_type, M2::element_type> (m1, m2, OP, OP, OP, #F); \
   }
 
 #define MM_BOOL_OPS(M1, M2) \
@@ -310,7 +310,7 @@
   R \
   OP (const ND1& m1, const ND2& m2) \
   { \
-    return do_mm_binary_op<R::element_type, ND1::element_type, ND2::element_type> (m1, m2, F, #OP); \
+    return do_mm_binary_op<R::element_type, ND1::element_type, ND2::element_type> (m1, m2, F, F, F, #OP); \
   }
 
 #define NDND_BIN_OPS(R, ND1, ND2) \
@@ -323,7 +323,7 @@
   boolNDArray \
   F (const ND1& m1, const ND2& m2) \
   { \
-    return do_mm_binary_op<bool, ND1::element_type, ND2::element_type> (m1, m2, OP, #F); \
+    return do_mm_binary_op<bool, ND1::element_type, ND2::element_type> (m1, m2, OP, OP, OP, #F); \
   }
 
 #define NDND_CMP_OPS(ND1, ND2) \
@@ -340,7 +340,7 @@
   { \
     MNANCHK (m1, ND1::element_type); \
     MNANCHK (m2, ND2::element_type); \
-    return do_mm_binary_op<bool, ND1::element_type, ND2::element_type> (m1, m2, OP, #F); \
+    return do_mm_binary_op<bool, ND1::element_type, ND2::element_type> (m1, m2, OP, OP, OP, #F); \
   }
 
 #define NDND_BOOL_OPS(ND1, ND2) \
@@ -583,7 +583,7 @@
 T \
 FCN (const T& a, const T& b) \
 { \
-  return do_mm_binary_op<T::element_type, T::element_type, T::element_type> (a, b, mx_inline_x##FCN, #FCN); \
+  return do_mm_binary_op<T::element_type, T::element_type, T::element_type> (a, b, mx_inline_x##FCN, mx_inline_x##FCN, mx_inline_x##FCN, #FCN); \
 }
 
 #define MINMAX_FCNS(T, S) \
--- a/liboctave/oct-binmap.h	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/oct-binmap.h	Tue Sep 20 15:38:24 2011 -0400
@@ -27,9 +27,13 @@
 #include "Sparse.h"
 #include "Array-util.h"
 
-// This source implements a general binary maping function for arrays.
-// The syntax is binmap<type> (a, b, f, [name]). type denotes the expected
-// return type of the operation. a, b, should be one of the 6 combinations:
+#include "bsxfun.h"
+
+// This source file implements a general binary maping function for
+// arrays. The syntax is binmap<type> (a, b, f, [name]). type denotes
+// the expected return type of the operation. a, b, should be one of
+// the 6 combinations:
+//
 // Array-Array
 // Array-scalar
 // scalar-Array
@@ -37,11 +41,12 @@
 // Sparse-scalar
 // scalar-Sparse
 //
-// If both operands are nonscalar, name must be supplied. It is used as the base for error message
-// when operands are nonconforming.
+// If both operands are nonscalar, name must be supplied. It is used
+// as the base for error message when operands are nonconforming.
 //
-// The operation needs not be homogeneous, i.e. a, b and the result may be of distinct types.
-// f can have any of the four signatures:
+// The operation needs not be homogeneous, i.e. a, b and the result
+// may be of distinct types. f can have any of the four signatures:
+//
 // U f (T, R)
 // U f (const T&, R)
 // U f (T, const R&)
@@ -49,7 +54,51 @@
 //
 // Additionally, f can be an arbitrary functor object.
 //
-// octave_quit() is called at appropriate places, hence the operation is breakable.
+// octave_quit() is called at appropriate places, hence the operation
+// is breakable.
+
+// The following template wrappers are provided for automatic bsxfun
+// calls (see the function signature for do_bsxfun_op).
+
+template<typename R, typename X, typename Y, typename F>
+class bsxfun_wrapper
+{
+private:
+  static F f;
+
+public:
+  static void
+  set_f (const F& f_in)
+  {
+    f = f_in;
+  }
+
+  static void
+  op_mm (size_t n, R* r, const X* x , const Y* y)
+  {
+    for (size_t i = 0; i < n; i++)
+      r[i] = f (x[i], y[i]);
+  }
+
+  static void
+  op_sm (size_t n, R* r, X x, const Y* y)
+  {
+    for (size_t i = 0; i < n; i++)
+      r[i] = f (x, y[i]);
+  }
+
+  static void
+  op_ms (size_t n , R* r, const X* x, Y y)
+  {
+    for (size_t i = 0; i < n; i++)
+      r[i] = f (x[i], y);
+  }
+};
+
+// Static init
+template<typename R, typename X, typename Y, typename F>
+F bsxfun_wrapper<R, X, Y, F>::f;
+
 
 // scalar-Array
 template <class U, class T, class R, class F>
@@ -118,12 +167,24 @@
 Array<U>
 binmap (const Array<T>& xa, const Array<R>& ya, F fcn, const char *name)
 {
+  dim_vector xad = xa.dims (), yad = ya.dims ();
   if (xa.numel () == 1)
     return binmap<U, T, R, F> (xa(0), ya, fcn);
   else if (ya.numel () == 1)
     return binmap<U, T, R, F> (xa, ya(0), fcn);
-  else if (xa.dims () != ya.dims ())
-    gripe_nonconformant (name, xa.dims (), ya.dims ());
+  else if (xad != yad)
+    {
+      if (is_valid_bsxfun (xad, yad))
+        {
+          bsxfun_wrapper<U, T, R, F>::set_f(fcn);
+          return do_bsxfun_op (xa, ya,
+                               bsxfun_wrapper<U, T, R, F>::op_mm,
+                               bsxfun_wrapper<U, T, R, F>::op_sm,
+                               bsxfun_wrapper<U, T, R, F>::op_ms);
+        }
+      else
+        gripe_nonconformant (name, xad, yad);
+    }
 
   octave_idx_type len = xa.numel ();
 
@@ -273,134 +334,134 @@
                                           fcn, name));
 }
 
-// Overloads for function references.
+// Overloads for function pointers.
 
 // Signature (T, R)
 
 template <class U, class T, class R>
 inline Array<U>
-binmap (const Array<T>& xa, const Array<R>& ya, U (&fcn) (T, R), const char *name)
-{ return binmap<U, T, R, U (&) (T, R)> (xa, ya, fcn, name); }
+binmap (const Array<T>& xa, const Array<R>& ya, U (*fcn) (T, R), const char *name)
+{ return binmap<U, T, R, U (*) (T, R)> (xa, ya, fcn, name); }
 
 template <class U, class T, class R>
 inline Array<U>
-binmap (const T& x, const Array<R>& ya, U (&fcn) (T, R))
-{ return binmap<U, T, R, U (&) (T, R)> (x, ya, fcn); }
+binmap (const T& x, const Array<R>& ya, U (*fcn) (T, R))
+{ return binmap<U, T, R, U (*) (T, R)> (x, ya, fcn); }
 
 template <class U, class T, class R>
 inline Array<U>
-binmap (const Array<T>& xa, const R& y, U (&fcn) (T, R))
-{ return binmap<U, T, R, U (&) (T, R)> (xa, y, fcn); }
+binmap (const Array<T>& xa, const R& y, U (*fcn) (T, R))
+{ return binmap<U, T, R, U (*) (T, R)> (xa, y, fcn); }
 
 template <class U, class T, class R>
 inline Sparse<U>
-binmap (const Sparse<T>& xa, const Sparse<R>& ya, U (&fcn) (T, R), const char *name)
-{ return binmap<U, T, R, U (&) (T, R)> (xa, ya, fcn, name); }
+binmap (const Sparse<T>& xa, const Sparse<R>& ya, U (*fcn) (T, R), const char *name)
+{ return binmap<U, T, R, U (*) (T, R)> (xa, ya, fcn, name); }
 
 template <class U, class T, class R>
 inline Sparse<U>
-binmap (const T& x, const Sparse<R>& ya, U (&fcn) (T, R))
-{ return binmap<U, T, R, U (&) (T, R)> (x, ya, fcn); }
+binmap (const T& x, const Sparse<R>& ya, U (*fcn) (T, R))
+{ return binmap<U, T, R, U (*) (T, R)> (x, ya, fcn); }
 
 template <class U, class T, class R>
 inline Sparse<U>
-binmap (const Sparse<T>& xa, const R& y, U (&fcn) (T, R))
-{ return binmap<U, T, R, U (&) (T, R)> (xa, y, fcn); }
+binmap (const Sparse<T>& xa, const R& y, U (*fcn) (T, R))
+{ return binmap<U, T, R, U (*) (T, R)> (xa, y, fcn); }
 
 // Signature (const T&, const R&)
 
 template <class U, class T, class R>
 inline Array<U>
-binmap (const Array<T>& xa, const Array<R>& ya, U (&fcn) (const T&, const R&), const char *name)
-{ return binmap<U, T, R, U (&) (const T&, const R&)> (xa, ya, fcn, name); }
+binmap (const Array<T>& xa, const Array<R>& ya, U (*fcn) (const T&, const R&), const char *name)
+{ return binmap<U, T, R, U (*) (const T&, const R&)> (xa, ya, fcn, name); }
 
 template <class U, class T, class R>
 inline Array<U>
-binmap (const T& x, const Array<R>& ya, U (&fcn) (const T&, const R&))
-{ return binmap<U, T, R, U (&) (const T&, const R&)> (x, ya, fcn); }
+binmap (const T& x, const Array<R>& ya, U (*fcn) (const T&, const R&))
+{ return binmap<U, T, R, U (*) (const T&, const R&)> (x, ya, fcn); }
 
 template <class U, class T, class R>
 inline Array<U>
-binmap (const Array<T>& xa, const R& y, U (&fcn) (const T&, const R&))
-{ return binmap<U, T, R, U (&) (const T&, const R&)> (xa, y, fcn); }
+binmap (const Array<T>& xa, const R& y, U (*fcn) (const T&, const R&))
+{ return binmap<U, T, R, U (*) (const T&, const R&)> (xa, y, fcn); }
 
 template <class U, class T, class R>
 inline Sparse<U>
-binmap (const Sparse<T>& xa, const Sparse<R>& ya, U (&fcn) (const T&, const R&), const char *name)
-{ return binmap<U, T, R, U (&) (const T&, const R&)> (xa, ya, fcn, name); }
+binmap (const Sparse<T>& xa, const Sparse<R>& ya, U (*fcn) (const T&, const R&), const char *name)
+{ return binmap<U, T, R, U (*) (const T&, const R&)> (xa, ya, fcn, name); }
 
 template <class U, class T, class R>
 inline Sparse<U>
-binmap (const T& x, const Sparse<R>& ya, U (&fcn) (const T&, const R&))
-{ return binmap<U, T, R, U (&) (const T&, const R&)> (x, ya, fcn); }
+binmap (const T& x, const Sparse<R>& ya, U (*fcn) (const T&, const R&))
+{ return binmap<U, T, R, U (*) (const T&, const R&)> (x, ya, fcn); }
 
 template <class U, class T, class R>
 inline Sparse<U>
-binmap (const Sparse<T>& xa, const R& y, U (&fcn) (const T&, const R&))
-{ return binmap<U, T, R, U (&) (const T&, const R&)> (xa, y, fcn); }
+binmap (const Sparse<T>& xa, const R& y, U (*fcn) (const T&, const R&))
+{ return binmap<U, T, R, U (*) (const T&, const R&)> (xa, y, fcn); }
 
 // Signature (const T&, R)
 
 template <class U, class T, class R>
 inline Array<U>
-binmap (const Array<T>& xa, const Array<R>& ya, U (&fcn) (const T&, R), const char *name)
-{ return binmap<U, T, R, U (&) (const T&, R)> (xa, ya, fcn, name); }
+binmap (const Array<T>& xa, const Array<R>& ya, U (*fcn) (const T&, R), const char *name)
+{ return binmap<U, T, R, U (*) (const T&, R)> (xa, ya, fcn, name); }
 
 template <class U, class T, class R>
 inline Array<U>
-binmap (const T& x, const Array<R>& ya, U (&fcn) (const T&, R))
-{ return binmap<U, T, R, U (&) (const T&, R)> (x, ya, fcn); }
+binmap (const T& x, const Array<R>& ya, U (*fcn) (const T&, R))
+{ return binmap<U, T, R, U (*) (const T&, R)> (x, ya, fcn); }
 
 template <class U, class T, class R>
 inline Array<U>
-binmap (const Array<T>& xa, const R& y, U (&fcn) (const T&, R))
-{ return binmap<U, T, R, U (&) (const T&, R)> (xa, y, fcn); }
+binmap (const Array<T>& xa, const R& y, U (*fcn) (const T&, R))
+{ return binmap<U, T, R, U (*) (const T&, R)> (xa, y, fcn); }
 
 template <class U, class T, class R>
 inline Sparse<U>
-binmap (const Sparse<T>& xa, const Sparse<R>& ya, U (&fcn) (const T&, R), const char *name)
-{ return binmap<U, T, R, U (&) (const T&, R)> (xa, ya, fcn, name); }
+binmap (const Sparse<T>& xa, const Sparse<R>& ya, U (*fcn) (const T&, R), const char *name)
+{ return binmap<U, T, R, U (*) (const T&, R)> (xa, ya, fcn, name); }
 
 template <class U, class T, class R>
 inline Sparse<U>
-binmap (const T& x, const Sparse<R>& ya, U (&fcn) (const T&, R))
-{ return binmap<U, T, R, U (&) (const T&, R)> (x, ya, fcn); }
+binmap (const T& x, const Sparse<R>& ya, U (*fcn) (const T&, R))
+{ return binmap<U, T, R, U (*) (const T&, R)> (x, ya, fcn); }
 
 template <class U, class T, class R>
 inline Sparse<U>
-binmap (const Sparse<T>& xa, const R& y, U (&fcn) (const T&, R))
-{ return binmap<U, T, R, U (&) (const T&, R)> (xa, y, fcn); }
+binmap (const Sparse<T>& xa, const R& y, U (*fcn) (const T&, R))
+{ return binmap<U, T, R, U (*) (const T&, R)> (xa, y, fcn); }
 
 // Signature (T, const R&)
 
 template <class U, class T, class R>
 inline Array<U>
-binmap (const Array<T>& xa, const Array<R>& ya, U (&fcn) (T, const R&), const char *name)
-{ return binmap<U, T, R, U (&) (T, const R&)> (xa, ya, fcn, name); }
+binmap (const Array<T>& xa, const Array<R>& ya, U (*fcn) (T, const R&), const char *name)
+{ return binmap<U, T, R, U (*) (T, const R&)> (xa, ya, fcn, name); }
 
 template <class U, class T, class R>
 inline Array<U>
-binmap (const T& x, const Array<R>& ya, U (&fcn) (T, const R&))
-{ return binmap<U, T, R, U (&) (T, const R&)> (x, ya, fcn); }
+binmap (const T& x, const Array<R>& ya, U (*fcn) (T, const R&))
+{ return binmap<U, T, R, U (*) (T, const R&)> (x, ya, fcn); }
 
 template <class U, class T, class R>
 inline Array<U>
-binmap (const Array<T>& xa, const R& y, U (&fcn) (T, const R&))
-{ return binmap<U, T, R, U (&) (T, const R&)> (xa, y, fcn); }
+binmap (const Array<T>& xa, const R& y, U (*fcn) (T, const R&))
+{ return binmap<U, T, R, U (*) (T, const R&)> (xa, y, fcn); }
 
 template <class U, class T, class R>
 inline Sparse<U>
-binmap (const Sparse<T>& xa, const Sparse<R>& ya, U (&fcn) (T, const R&), const char *name)
-{ return binmap<U, T, R, U (&) (T, const R&)> (xa, ya, fcn, name); }
+binmap (const Sparse<T>& xa, const Sparse<R>& ya, U (*fcn) (T, const R&), const char *name)
+{ return binmap<U, T, R, U (*) (T, const R&)> (xa, ya, fcn, name); }
 
 template <class U, class T, class R>
 inline Sparse<U>
-binmap (const T& x, const Sparse<R>& ya, U (&fcn) (T, const R&))
-{ return binmap<U, T, R, U (&) (T, const R&)> (x, ya, fcn); }
+binmap (const T& x, const Sparse<R>& ya, U (*fcn) (T, const R&))
+{ return binmap<U, T, R, U (*) (T, const R&)> (x, ya, fcn); }
 
 template <class U, class T, class R>
 inline Sparse<U>
-binmap (const Sparse<T>& xa, const R& y, U (&fcn) (T, const R&))
-{ return binmap<U, T, R, U (&) (T, const R&)> (xa, y, fcn); }
+binmap (const Sparse<T>& xa, const R& y, U (*fcn) (T, const R&))
+{ return binmap<U, T, R, U (*) (T, const R&)> (xa, y, fcn); }
 
 #endif
--- a/liboctave/oct-inttypes.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/oct-inttypes.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -578,6 +578,23 @@
 
 template <class T>
 octave_int<T>
+pow (const float& a, const octave_int<T>& b)
+{ return octave_int<T> (pow (a, b.float_value ())); }
+
+template <class T>
+octave_int<T>
+pow (const octave_int<T>& a, const float& b)
+{
+  return ((b >= 0 && b < std::numeric_limits<T>::digits && b == xround (b))
+          ? pow (a, octave_int<T> (static_cast<T> (b)))
+          : octave_int<T> (pow (a.double_value (), static_cast<double> (b))));
+}
+
+// FIXME: Do we really need a differently named single-precision
+//        function integer power function here instead of an overloaded
+//        one?
+template <class T>
+octave_int<T>
 powf (const float& a, const octave_int<T>& b)
 { return octave_int<T> (pow (a, b.float_value ())); }
 
@@ -595,6 +612,8 @@
   template OCTAVE_API octave_int<T> pow (const octave_int<T>&, const octave_int<T>&); \
   template OCTAVE_API octave_int<T> pow (const double&, const octave_int<T>&); \
   template OCTAVE_API octave_int<T> pow (const octave_int<T>&, const double&); \
+  template OCTAVE_API octave_int<T> pow (const float&, const octave_int<T>&);  \
+  template OCTAVE_API octave_int<T> pow (const octave_int<T>&, const float&);  \
   template OCTAVE_API octave_int<T> powf (const float&, const octave_int<T>&); \
   template OCTAVE_API octave_int<T> powf (const octave_int<T>&, const float&); \
   template OCTAVE_API octave_int<T> \
--- a/liboctave/oct-inttypes.h	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/oct-inttypes.h	Tue Sep 20 15:38:24 2011 -0400
@@ -874,6 +874,17 @@
 
 template <class T>
 extern OCTAVE_API octave_int<T>
+pow (const float& a, const octave_int<T>& b);
+
+template <class T>
+extern OCTAVE_API octave_int<T>
+pow (const octave_int<T>& a, const float& b);
+
+// FIXME: Do we really need a differently named single-precision
+//        function integer power function here instead of an overloaded
+//        one?
+template <class T>
+extern OCTAVE_API octave_int<T>
 powf (const float& a, const octave_int<T>& b);
 
 template <class T>
--- a/liboctave/str-vec.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/str-vec.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -163,6 +163,26 @@
   return *this;
 }
 
+std::string
+string_vector::join (const std::string& sep) const
+{
+  std::string retval;
+
+  octave_idx_type len = length ();
+
+  if (len > 0)
+    {
+      octave_idx_type i;
+
+      for (i = 0; i < len - 1; i++)
+        retval += elem(i) + sep;
+
+      retval += elem(i);
+    }
+
+  return retval;
+}
+
 char **
 string_vector::c_str_vec (void) const
 {
--- a/liboctave/str-vec.h	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/str-vec.h	Tue Sep 20 15:38:24 2011 -0400
@@ -105,6 +105,8 @@
 
   string_vector& append (const string_vector& sv);
 
+  std::string join (const std::string& sep = std::string ()) const;
+
   char **c_str_vec (void) const;
 
   static void delete_c_str_vec (const char * const*);
--- a/liboctave/uint16NDArray.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/uint16NDArray.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -54,3 +54,6 @@
 
 BSXFUN_STDOP_DEFS_MXLOOP (uint16NDArray)
 BSXFUN_STDREL_DEFS_MXLOOP (uint16NDArray)
+
+BSXFUN_OP_DEF_MXLOOP (pow, uint16NDArray, mx_inline_pow)
+BSXFUN_POW_MIXED_MXLOOP (uint16NDArray)
--- a/liboctave/uint16NDArray.h	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/uint16NDArray.h	Tue Sep 20 15:38:24 2011 -0400
@@ -44,6 +44,7 @@
 MINMAX_DECLS (uint16NDArray, octave_uint16, OCTAVE_API)
 
 BSXFUN_STDOP_DECLS (uint16NDArray, OCTAVE_API)
+BSXFUN_MIXED_INT_DECLS(uint16NDArray, OCTAVE_API)
 BSXFUN_STDREL_DECLS (uint16NDArray, OCTAVE_API)
 
 #endif
--- a/liboctave/uint32NDArray.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/uint32NDArray.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -54,3 +54,6 @@
 
 BSXFUN_STDOP_DEFS_MXLOOP (uint32NDArray)
 BSXFUN_STDREL_DEFS_MXLOOP (uint32NDArray)
+
+BSXFUN_OP_DEF_MXLOOP (pow, uint32NDArray, mx_inline_pow)
+BSXFUN_POW_MIXED_MXLOOP (uint32NDArray)
--- a/liboctave/uint32NDArray.h	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/uint32NDArray.h	Tue Sep 20 15:38:24 2011 -0400
@@ -44,6 +44,7 @@
 MINMAX_DECLS (uint32NDArray, octave_uint32, OCTAVE_API)
 
 BSXFUN_STDOP_DECLS (uint32NDArray, OCTAVE_API)
+BSXFUN_MIXED_INT_DECLS(uint32NDArray, OCTAVE_API)
 BSXFUN_STDREL_DECLS (uint32NDArray, OCTAVE_API)
 
 #endif
--- a/liboctave/uint64NDArray.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/uint64NDArray.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -54,3 +54,7 @@
 
 BSXFUN_STDOP_DEFS_MXLOOP (uint64NDArray)
 BSXFUN_STDREL_DEFS_MXLOOP (uint64NDArray)
+
+BSXFUN_OP_DEF_MXLOOP (pow, uint64NDArray, mx_inline_pow)
+BSXFUN_POW_MIXED_MXLOOP (uint64NDArray)
+
--- a/liboctave/uint64NDArray.h	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/uint64NDArray.h	Tue Sep 20 15:38:24 2011 -0400
@@ -44,6 +44,7 @@
 MINMAX_DECLS (uint64NDArray, octave_uint64, OCTAVE_API)
 
 BSXFUN_STDOP_DECLS (uint64NDArray, OCTAVE_API)
+BSXFUN_MIXED_INT_DECLS(uint64NDArray, OCTAVE_API)
 BSXFUN_STDREL_DECLS (uint64NDArray, OCTAVE_API)
 
 #endif
--- a/liboctave/uint8NDArray.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/uint8NDArray.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -54,3 +54,7 @@
 
 BSXFUN_STDOP_DEFS_MXLOOP (uint8NDArray)
 BSXFUN_STDREL_DEFS_MXLOOP (uint8NDArray)
+
+BSXFUN_POW_MIXED_MXLOOP (uint8NDArray)
+BSXFUN_OP_DEF_MXLOOP (pow, uint8NDArray, mx_inline_pow)
+
--- a/liboctave/uint8NDArray.h	Tue Sep 20 15:33:10 2011 -0400
+++ b/liboctave/uint8NDArray.h	Tue Sep 20 15:38:24 2011 -0400
@@ -44,6 +44,7 @@
 MINMAX_DECLS (uint8NDArray, octave_uint8, OCTAVE_API)
 
 BSXFUN_STDOP_DECLS (uint8NDArray, OCTAVE_API)
+BSXFUN_MIXED_INT_DECLS(uint8NDArray, OCTAVE_API)
 BSXFUN_STDREL_DECLS (uint8NDArray, OCTAVE_API)
 
 #endif
--- a/scripts/Makefile.am	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/Makefile.am	Tue Sep 20 15:38:24 2011 -0400
@@ -3,17 +3,17 @@
 # Copyright (C) 1993-2011 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 3 of the License, 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, see
 # <http://www.gnu.org/licenses/>.
--- a/scripts/audio/playaudio.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/audio/playaudio.m	Tue Sep 20 15:38:24 2011 -0400
@@ -47,7 +47,10 @@
       num = fopen (file, "wb");
       c = fwrite (num, X, "uchar");
       fclose (num);
-      system (sprintf ("cat \"%s\" > /dev/dsp", file));
+      [status, out] = system (sprintf ("cat \"%s\" > /dev/dsp", file));
+      if (status != 0)
+        system (sprintf ("paplay --raw \"%s\"", file))
+      endif
     unwind_protect_cleanup
       unlink (file);
     end_unwind_protect
@@ -61,10 +64,16 @@
       print_usage ();
     endif
     if (strcmp (ext, "lin") || strcmp (ext, "raw"))
-      system (sprintf ("cat \"%s\" > /dev/dsp", name));
+      [status, out] = system (sprintf ("cat \"%s\" > /dev/dsp", name));
+      if (status != 0)
+        system (sprintf ("paplay --raw \"%s\"", name))
+      endif
     elseif (strcmp (ext, "mu") || strcmp (ext, "au")
             || strcmp (ext, "snd") || strcmp (ext, "ul"))
-      system (sprintf ("cat \"%s\" > /dev/audio", name));
+      [status, out] = system (sprintf ("cat \"%s\" > /dev/audio", name));
+      if (status != 0)
+        system (sprintf ("paplay \"%s\"", name))
+      endif
     else
       error ("playaudio: unsupported extension");
     endif
--- a/scripts/audio/wavread.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/audio/wavread.m	Tue Sep 20 15:38:24 2011 -0400
@@ -55,135 +55,139 @@
     error ("wavread: FILENAME must be a character string");
   endif
 
-  # Open file for binary reading.
-  [fid, msg] = fopen (filename, "rb");
-  if (fid < 0)
-    error ("wavread: %s", msg);
-  endif
+  fid = -1;
+
+  unwind_protect
 
-  ## Get file size.
-  fseek (fid, 0, "eof");
-  file_size = ftell (fid);
-  fseek (fid, 0, "bof");
+    [fid, msg] = fopen (filename, "rb");
+
+    if (fid < 0)
+      error ("wavread: %s", msg);
+    endif
 
-  ## Find RIFF chunk.
-  riff_size = find_chunk (fid, "RIFF", file_size);
-  riff_pos = ftell (fid);
-  if (riff_size == -1)
-    fclose (fid);
-    error ("wavread: file contains no RIFF chunk");
-  endif
+    ## Get file size.
+    fseek (fid, 0, "eof");
+    file_size = ftell (fid);
+    fseek (fid, 0, "bof");
 
-  riff_type = char (fread (fid, 4))';
-  if (! strcmp (riff_type, "WAVE"))
-    fclose (fid);
-    error ("wavread: file contains no WAVE signature");
-  endif
-  riff_pos = riff_pos + 4;
-  riff_size = riff_size - 4;
+    ## Find RIFF chunk.
+    riff_size = find_chunk (fid, "RIFF", file_size);
+    riff_pos = ftell (fid);
+    if (riff_size == -1)
+      error ("wavread: file contains no RIFF chunk");
+    endif
+
+    riff_type = char (fread (fid, 4))';
+    if (! strcmp (riff_type, "WAVE"))
+      error ("wavread: file contains no WAVE signature");
+    endif
+    riff_pos = riff_pos + 4;
+    riff_size = riff_size - 4;
 
-  ## Find format chunk inside the RIFF chunk.
-  fseek (fid, riff_pos, "bof");
-  fmt_size = find_chunk (fid, "fmt ", riff_size);
-  fmt_pos = ftell(fid);
-  if (fmt_size == -1)
-    fclose (fid);
-    error ("wavread: file contains no format chunk");
-  endif
+    ## Find format chunk inside the RIFF chunk.
+    fseek (fid, riff_pos, "bof");
+    fmt_size = find_chunk (fid, "fmt ", riff_size);
+    fmt_pos = ftell(fid);
+    if (fmt_size == -1)
+      error ("wavread: file contains no format chunk");
+    endif
+
+    ## Find data chunk inside the RIFF chunk.
+    ## We don't assume that it comes after the format chunk.
+    fseek (fid, riff_pos, "bof");
+    data_size = find_chunk (fid, "data", riff_size);
+    data_pos = ftell (fid);
+    if (data_size == -1)
+      error ("wavread: file contains no data chunk");
+    endif
 
-  ## Find data chunk inside the RIFF chunk.
-  ## We don't assume that it comes after the format chunk.
-  fseek (fid, riff_pos, "bof");
-  data_size = find_chunk (fid, "data", riff_size);
-  data_pos = ftell (fid);
-  if (data_size == -1)
-    fclose (fid);
-    error ("wavread: file contains no data chunk");
-  endif
+    ### Read format chunk.
+    fseek (fid, fmt_pos, "bof");
 
-  ### Read format chunk.
-  fseek (fid, fmt_pos, "bof");
+    ## Sample format code.
+    format_tag = fread (fid, 1, "uint16", 0, BYTEORDER);
+    if (format_tag != FORMAT_PCM && format_tag != FORMAT_IEEE_FLOAT)
+      error ("wavread: sample format %#x is not supported", format_tag);
+    endif
 
-  ## Sample format code.
-  format_tag = fread (fid, 1, "uint16", 0, BYTEORDER);
-  if (format_tag != FORMAT_PCM && format_tag != FORMAT_IEEE_FLOAT)
-    fclose (fid);
-    error ("wavread: sample format %#x is not supported", format_tag);
-  endif
+    ## Number of interleaved channels.
+    channels = fread (fid, 1, "uint16", 0, BYTEORDER);
 
-  ## Number of interleaved channels.
-  channels = fread (fid, 1, "uint16", 0, BYTEORDER);
+    ## Sample rate.
+    samples_per_sec = fread (fid, 1, "uint32", 0, BYTEORDER);
 
-  ## Sample rate.
-  samples_per_sec = fread (fid, 1, "uint32", 0, BYTEORDER);
+    ## Bits per sample.
+    fseek (fid, 6, "cof");
+    bits_per_sample = fread (fid, 1, "uint16", 0, BYTEORDER);
 
-  ## Bits per sample.
-  fseek (fid, 6, "cof");
-  bits_per_sample = fread (fid, 1, "uint16", 0, BYTEORDER);
+    ### Read data chunk.
+    fseek (fid, data_pos, "bof");
 
-  ### Read data chunk.
-  fseek (fid, data_pos, "bof");
+    ## Determine sample data type.
+    if (format_tag == FORMAT_PCM)
+      switch (bits_per_sample)
+        case 8
+          format = "uint8";
+        case 16
+          format = "int16";
+        case 24
+          format = "uint8";
+        case 32
+          format = "int32";
+        otherwise
+          error ("wavread: %d bits sample resolution is not supported with PCM",
+                 bits_per_sample);
+      endswitch
+    else
+      switch (bits_per_sample)
+        case 32
+          format = "float32";
+        case 64
+          format = "float64";
+        otherwise
+          error ("wavread: %d bits sample resolution is not supported with IEEE float",
+                 bits_per_sample);
+      endswitch
+    endif
 
-  ## Determine sample data type.
-  if (format_tag == FORMAT_PCM)
-    switch (bits_per_sample)
-      case 8
-        format = "uint8";
-      case 16
-        format = "int16";
-      case 24
-        format = "uint8";
-      case 32
-        format = "int32";
-      otherwise
-        fclose (fid);
-        error ("wavread: %d bits sample resolution is not supported with PCM",
-               bits_per_sample);
-    endswitch
-  else
-    switch (bits_per_sample)
-      case 32
-        format = "float32";
-      case 64
-        format = "float64";
-      otherwise
-        fclose (fid);
-        error ("wavread: %d bits sample resolution is not supported with IEEE float",
-               bits_per_sample);
-    endswitch
-  endif
+    ## Parse arguments.
+    if (nargin == 1)
+      length = idivide (8 * data_size, bits_per_sample);
+    else
+      nparams = numel (param);
+      if (nparams == 1)
+        ## Number of samples is given.
+        length = param * channels;
+      elseif (nparams == 2)
+        ## Sample range is given.
+        if (fseek (fid, (param(1)-1) * channels * (bits_per_sample/8), "cof") < 0)
+          warning ("wavread: seeking failed");
+        endif
+        length = (param(2)-param(1)+1) * channels;
+      elseif (nparams == 4 && char (param) == "size")
+        ## Size of the file is requested.
+        tmp = idivide (8 * data_size, channels * bits_per_sample);
+        y = [tmp, channels];
+        return;
+      else
+        error ("wavread: invalid PARAM argument");
+      endif
+    endif
 
-  ## Parse arguments.
-  if (nargin == 1)
-    length = 8 * data_size / bits_per_sample;
-  else
-    nparams = numel (param);
-    if (nparams == 1)
-      ## Number of samples is given.
-      length = param * channels;
-    elseif (nparams == 2)
-      ## Sample range is given.
-      if (fseek (fid, (param(1)-1) * channels * (bits_per_sample/8), "cof") < 0)
-        warning ("wavread: seeking failed");
-      endif
-      length = (param(2)-param(1)+1) * channels;
-    elseif (nparams == 4 && char (param) == "size")
-      ## Size of the file is requested.
+    ## Read samples and close file.
+    if (bits_per_sample == 24)
+      length *= 3;
+    endif
+
+    [yi, n] = fread (fid, length, format, 0, BYTEORDER);
+
+  unwind_protect_cleanup
+
+    if (fid >= 0)
       fclose (fid);
-      y = [data_size/channels/(bits_per_sample/8), channels];
-      return;
-    else
-      fclose (fid);
-      error ("wavread: invalid PARAM argument");
     endif
-  endif
 
-  ## Read samples and close file.
-  if (bits_per_sample == 24)
-    length *= 3;
-  endif
-  [yi, n] = fread (fid, length, format, 0, BYTEORDER);
-  fclose (fid);
+  end_unwind_protect
 
   ## Check data.
   if (mod (numel (yi), channels) != 0)
@@ -240,7 +244,6 @@
   endif
 endfunction
 
-
-%% Tests for wavread/wavwrite pair are in wavrite.m
-%!assert(1)  # stop fntests.m from reporting no tests for wavread
-
+## Mark file as being tested.  Tests for wavread/wavwrite pair are in
+## wavwrite.m
+%!assert(1)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/deprecated/__error_text__.m	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,36 @@
+## Copyright (C) 2011 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 3 of the License, 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, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Built-in Function} {[@var{msg}, @var{msgid}] =} __error_text__ (@var{msg}, @var{msgid})
+## This function has been deprecated.  Use @code{lasterr} instead.
+## @seealso{lasterr}
+## @end deftypefn
+
+function [msg, msgid] = __error_text__ (varargin)
+
+  persistent warned = false;
+  if (! warned)
+    warned = true;
+    warning ("Octave:deprecated-function",
+             "__error_text__ is obsolete and will be removed from a future version of Octave, please use lasterr instead");
+  endif
+
+  [msg, msgid] = lasterr (varargin{:});
+
+endfunction
--- a/scripts/deprecated/complement.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,78 +0,0 @@
-## Copyright (C) 1994-2011 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} {} complement (@var{x}, @var{y})
-## Return the elements of set @var{y} that are not in set @var{x}.  For
-## example:
-##
-## @example
-## @group
-## complement ([ 1, 2, 3 ], [ 2, 3, 5 ])
-##      @result{} 5
-## @end group
-## @end example
-## @seealso{union, intersect, unique}
-## @end deftypefn
-
-## Author: jwe
-
-## Deprecated in version 3.2
-
-function y = complement (a, b)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "complement is obsolete and will be removed from a future version of Octave, please use setdiff instead");
-  endif
-
-  if (nargin != 2)
-    print_usage ();
-  endif
-
-  if (isempty (a))
-    y = unique (b);
-  elseif (isempty (b))
-    y = [];
-  else
-    a = unique (a);
-    b = unique (b);
-    yindex = 1;
-    y = zeros (1, length (b));
-    for index = 1:length (b)
-      if (all (a != b (index)))
-        y(yindex++) = b(index);
-      endif
-    endfor
-    y = y(1:(yindex-1));
-  endif
-
-endfunction
-
-%!assert(all (all (complement ([1, 2, 3], [3; 4; 5; 6]) == [4, 5, 6])));
-
-%!assert(all (all (complement ([1, 2, 3], [3, 4, 5, 6]) == [4, 5, 6])));
-
-%!assert(isempty (complement ([1, 2, 3], [3, 2, 1])));
-
-%!error complement (1);
-
-%!error complement (1, 2, 3);
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/deprecated/cor.m	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,54 @@
+## Copyright (C) 1995-2011 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 3 of the License, 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, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {Function File} {} cor (@var{x})
+## @deftypefnx {Function File} {} cor (@var{x}, @var{y})
+## Compute matrix of correlation coefficients.
+##
+## This is an alias for @code{corrcoef}.
+## @seealso{corrcoef}
+## @end deftypefn
+
+function retval = cor (x, y = x)
+
+  persistent warned = false;
+  if (! warned)
+    warned = true;
+    warning ("Octave:deprecated-function",
+             "cor is obsolete and will be removed from a future version of Octave; please use corr instead");
+  endif
+
+  if (nargin < 1 || nargin > 2)
+    print_usage ();
+  endif
+
+  retval = corrcoef (x, y);
+
+endfunction
+
+
+%!test
+%! x = rand (10, 2);
+%! assert (cor (x), corrcoef (x), 5*eps);
+%! assert (cor (x(:,1), x(:,2)) == corrcoef (x(:,1), x(:,2)));
+
+%% Test input validation
+%!error corrcoef ();
+%!error corrcoef (1, 2, 3);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/deprecated/corrcoef.m	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,119 @@
+## Copyright (C) 1996-2011 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 3 of the License, 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, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {Function File} {} corrcoef (@var{x})
+## @deftypefnx {Function File} {} corrcoef (@var{x}, @var{y})
+## Compute matrix of correlation coefficients.
+##
+## If each row of @var{x} and @var{y} is an observation and each column is
+## a variable, then the @w{(@var{i}, @var{j})-th} entry of
+## @code{corrcoef (@var{x}, @var{y})} is the correlation between the
+## @var{i}-th variable in @var{x} and the @var{j}-th variable in @var{y}.
+## @tex
+## $$
+## {\rm corrcoef}(x,y) = {{\rm cov}(x,y) \over {\rm std}(x) {\rm std}(y)}
+## $$
+## @end tex
+## @ifnottex
+##
+## @example
+## corrcoef(x,y) = cov(x,y)/(std(x)*std(y))
+## @end example
+##
+## @end ifnottex
+## If called with one argument, compute @code{corrcoef (@var{x}, @var{x})},
+## the correlation between the columns of @var{x}.
+## @seealso{cov}
+## @end deftypefn
+
+## Author: Kurt Hornik <hornik@wu-wien.ac.at>
+## Created: March 1993
+## Adapted-By: jwe
+
+function retval = corrcoef (x, y = [])
+
+  persistent warned = false;
+  if (! warned)
+    warned = true;
+    warning ("Octave:deprecated-function",
+             "corrcoef is not equivalent to Matlab and will be removed from a future version of Octave; for similar functionality see corr");
+  endif
+
+  if (nargin < 1 || nargin > 2)
+    print_usage ();
+  endif
+
+  ## Input validation is done by cov.m.  Don't repeat tests here
+
+  ## Special case, scalar is always 100% correlated with itself
+  if (isscalar (x))
+    if (isa (x, 'single'))
+      retval = single (1);
+    else
+      retval = 1;
+    endif
+    return;
+  endif
+
+  ## No check for division by zero error, which happens only when
+  ## there is a constant vector and should be rare.
+  if (nargin == 2)
+    c = cov (x, y);
+    s = std (x)' * std (y);
+    retval = c ./ s;
+  else
+    c = cov (x);
+    s = sqrt (diag (c));
+    retval = c ./ (s * s');
+  endif
+
+endfunction
+
+
+%!test
+%! x = rand (10);
+%! cc1 = corrcoef (x);
+%! cc2 = corrcoef (x, x);
+%! assert (size (cc1) == [10, 10] && size (cc2) == [10, 10]);
+%! assert (cc1, cc2, sqrt (eps));
+
+%!test
+%! x = [1:3]';
+%! y = [3:-1:1]';
+%! assert (corrcoef (x,y), -1, 5*eps)
+%! assert (corrcoef (x,flipud (y)), 1, 5*eps)
+%! assert (corrcoef ([x, y]), [1 -1; -1 1], 5*eps)
+
+%!test
+%! x = single ([1:3]');
+%! y = single ([3:-1:1]');
+%! assert (corrcoef (x,y), single (-1), 5*eps)
+%! assert (corrcoef (x,flipud (y)), single (1), 5*eps)
+%! assert (corrcoef ([x, y]), single ([1 -1; -1 1]), 5*eps)
+
+%!assert (corrcoef (5), 1);
+%!assert (corrcoef (single(5)), single(1));
+
+%% Test input validation
+%!error corrcoef ();
+%!error corrcoef (1, 2, 3);
+%!error corrcoef ([1; 2], ["A", "B"]);
+%!error corrcoef (ones (2,2,2));
+%!error corrcoef (ones (2,2), ones (2,2,2));
+
--- a/scripts/deprecated/create_set.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-## Copyright (C) 1994-2011 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn  {Function File} {} create_set (@var{x})
-## @deftypefnx {Function File} {} create_set (@var{x}, "rows")
-## This function has been deprecated.  Use unique instead.
-## @end deftypefn
-
-## Return a row vector containing the unique values in @var{x}, sorted in
-## ascending order.  For example,
-##
-## @example
-## @group
-## create_set ([ 1, 2; 3, 4; 4, 2; 1, 2 ])
-##      @result{} [ 1, 2, 3, 4 ]
-## @end group
-## @end example
-##
-## If the optional second input argument is the string "rows" each row of
-## the matrix @var{x} will be considered an element of set.  For example,
-## @example
-## @group
-## create_set ([ 1, 2; 3, 4; 4, 2; 1, 2 ], "rows")
-##      @result{}  1   2
-##     3   4
-##     4   2
-## @end group
-## @end example
-## @seealso{union, intersect, complement, unique}
-
-## Author: jwe
-
-## Deprecated in version 3.2
-
-function y = create_set (x, rows_opt)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "create_set is obsolete and will be removed from a future version of Octave, please use unique instead");
-  endif
-
-  if (nargin < 1 || nargin > 2)
-    print_usage ();
-  endif
-
-  if (nargin == 1)
-    y = unique (x)(:)';
-  elseif (strcmpi (rows_opt, "rows"))
-    y = unique (x, "rows");
-  else
-    error ("create_set: expecting \"rows\" as second argument");
-  endif
-
-endfunction
-
-%!assert(all (all (create_set ([1, 2, 3, 4, 2, 4]) == [1, 2, 3, 4])));
-%!assert(all (all (create_set ([1, 2; 3, 4; 2, 4]) == [1, 2, 3, 4])));
-%!assert(all (all (create_set ([1; 2; 3; 4; 2; 4]) == [1, 2, 3, 4])));
-%!assert(isempty (create_set ([])));
-%!error create_set (1, 2);
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/deprecated/cut.m	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,71 @@
+## Copyright (C) 1996-2011 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 3 of the License, 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, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {} cut (@var{x}, @var{breaks})
+## Create categorical data from numerical or continuous data by
+## cutting into intervals.
+##
+## If @var{breaks} is a scalar, the data is cut into that many
+## equal-width intervals.  If @var{breaks} is a vector of break points,
+## the category has @code{length (@var{breaks}) - 1} groups.
+##
+## The returned value is a vector of the same size as @var{x} telling
+## which group each point in @var{x} belongs to.  Groups are labelled
+## from 1 to the number of groups; points outside the range of
+## @var{breaks} are labelled by @code{NaN}.
+## @seealso{histc}
+## @end deftypefn
+
+## Author: KH <Kurt.Hornik@wu-wien.ac.at>
+## Description: Cut data into intervals
+
+function group = cut (x, breaks)
+
+  persistent warned = false;
+  if (! warned)
+    warned = true;
+    warning ("Octave:deprecated-function",
+             "cut is obsolete and will be removed from a future version of Octave; please use histc instead");
+  endif
+
+  if (nargin != 2)
+    print_usage ();
+  endif
+
+  if (!isvector (x))
+    error ("cut: X must be a vector");
+  endif
+  if isscalar (breaks)
+    breaks = linspace (min (x), max (x), breaks + 1);
+    breaks(1) = breaks(1) - 1;
+  elseif isvector (breaks)
+    breaks = sort (breaks);
+  else
+    error ("cut: BREAKS must be a scalar or vector");
+  endif
+
+  group = NaN (size (x));
+  m = length (breaks);
+  if any (k = find ((x >= min (breaks)) & (x < max (breaks))))
+    n = length (k);
+    group(k) = sum ((ones (m, 1) * reshape (x(k), 1, n))
+                    >= (reshape (breaks, m, 1) * ones (1, n)));
+  endif
+
+endfunction
--- a/scripts/deprecated/dmult.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-## Copyright (C) 1995-2011 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} {} dmult (@var{a}, @var{b})
-## This function has been deprecated.  Use the direct syntax @code{diag(A)*B}
-## which is more readable and now also more efficient.
-## @end deftypefn
-
-## Author: KH <Kurt.Hornik@wu-wien.ac.at>
-## Description: Rescale the rows of a matrix
-
-## Deprecated in version 3.2
-
-function M = dmult (a, B)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "dmult is obsolete and will be removed from a future version of Octave; please use the straightforward (and now efficient) syntax \"diag(A)*B\"");
-  endif
-
-  if (nargin != 2)
-    print_usage ();
-  endif
- if (! isvector (a))
-    error ("dmult: a must be a vector of length rows (B)");
-  endif
-  a = a(:);
-  sb = size (B);
-  sb(1) = 1;
-  M = repmat (a(:), sb) .* B;
-endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/deprecated/error_text.m	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,36 @@
+## Copyright (C) 2011 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 3 of the License, 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, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Built-in Function} {[@var{msg}, @var{msgid}] =} error_text (@var{msg}, @var{msgid})
+## This function has been deprecated.  Use @code{lasterr} instead.
+## @seealso{lasterr}
+## @end deftypefn
+
+function [msg, msgid] = error_text (varargin)
+
+  persistent warned = false;
+  if (! warned)
+    warned = true;
+    warning ("Octave:deprecated-function",
+             "error_text is obsolete and will be removed from a future version of Octave, please use lasterr instead");
+  endif
+
+  [msg, msgid] = lasterr (varargin{:});
+
+endfunction
--- a/scripts/deprecated/glpkmex.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/deprecated/glpkmex.m	Tue Sep 20 15:38:24 2011 -0400
@@ -32,7 +32,7 @@
     warning ("Octave:deprecated-function",
              "glpkmex is obsolete and will be removed from a future version of Octave; please use glpk instead");
   endif
-  
+
   ## If there is no input output the version and syntax
   if (nargin < 4 || nargin > 11)
     print_usage ();
--- a/scripts/deprecated/iscommand.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-## Copyright (C) 2009-2011 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Built-in Function} {} iscommand (@var{name})
-## This function is obsolete and will be removed from a future
-## version of Octave.
-## @end deftypefn
-
-## Author: jwe
-
-## Deprecated in version 3.2
-
-function retval = iscommand ()
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "iscommand is obsolete and will be removed from a future version of Octave");
-  endif
-
-  if (nargin == 0)
-    retval = {};
-  else
-    retval = true;
-  endif
-
-endfunction
--- a/scripts/deprecated/israwcommand.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-## Copyright (C) 2009-2011 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Built-in Function} {} israwcommand (@var{name})
-## This function is obsolete and will be removed from a future
-## version of Octave.
-## @end deftypefn
-
-## Author: jwe
-
-## Deprecated in version 3.2
-
-function retval = israwcommand ()
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "israwcommand is obsolete and will be removed from a future version of Octave");
-  endif
-
-  if (nargin == 0)
-    retval = {};
-  else
-    retval = true;
-  endif
-
-endfunction
--- a/scripts/deprecated/lchol.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-## Copyright (C) 2008-2011 David Bateman
-##
-## 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn  {Loadable Function} {@var{l} =} lchol (@var{a})
-## @deftypefnx {Loadable Function} {[@var{l}, @var{p}] =} lchol (@var{a})
-## This function has been deprecated.  Use @code{chol (@dots{},'lower')}
-## instead.
-## @end deftypefn
-
-## Deprecated in version 3.2
-
-function varargout = lchol (varargin)
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "spfind is obsolete and will be removed from a future version of Octave; please use find instead");
-  endif
-
-  varargout = cell (nargout, 1);
-  [ varargout{:} ] = chol (varargin{:}, "lower");
-
-endfunction
--- a/scripts/deprecated/loadimage.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-## Copyright (C) 1994-2011 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} {[@var{x}, @var{map}] =} loadimage (@var{file})
-## Load an image file and its associated color map from the specified
-## @var{file}.  The image must be stored in Octave's image format.
-## @seealso{saveimage, load, save}
-## @end deftypefn
-
-## Author: Tony Richardson <arichard@stark.cc.oh.us>
-## Created: July 1994
-## Adapted-By: jwe
-
-## Deprecated in version 3.2
-
-function [img_retval, map_retval] = loadimage (varargin)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "loadimage is obsolete and will be removed from a future version of Octave; please use imread instead");
-  endif
-
-  [img_retval, map_retval] = imread (varargin{:});
-
-endfunction
--- a/scripts/deprecated/mark_as_command.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-## Copyright (C) 2009-2011 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Built-in Function} {} mark_as_command (@var{name})
-## This function is obsolete and will be removed from a future
-## version of Octave.
-## @end deftypefn
-
-## Author: jwe
-
-## Deprecated in version 3.2
-
-function mark_as_command ()
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "mark_as_command is obsolete and will be removed from a future version of Octave");
-  endif
-
-endfunction
--- a/scripts/deprecated/mark_as_rawcommand.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-## Copyright (C) 2009-2011 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Built-in Function} {} mark_as_rawcommand (@var{name})
-## This function is obsolete and will be removed from a future
-## version of Octave.
-## @end deftypefn
-
-## Author: jwe
-
-## Deprecated in version 3.2
-
-function mark_as_rawcommand ()
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "mark_as_rawcommand is obsolete and will be removed from a future version of Octave");
-  endif
-
-endfunction
--- a/scripts/deprecated/module.mk	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/deprecated/module.mk	Tue Sep 20 15:38:24 2011 -0400
@@ -6,55 +6,29 @@
   deprecated/betai.m \
   deprecated/cellidx.m \
   deprecated/clg.m \
-  deprecated/complement.m \
-  deprecated/create_set.m \
+  deprecated/cor.m \
+  deprecated/corrcoef.m \
   deprecated/cquad.m \
+  deprecated/cut.m \
   deprecated/dispatch.m \
-  deprecated/dmult.m \
   deprecated/fstat.m \
   deprecated/gammai.m \
   deprecated/glpkmex.m \
   deprecated/intwarning.m \
-  deprecated/iscommand.m \
   deprecated/is_duplicate_entry.m \
   deprecated/is_global.m \
-  deprecated/israwcommand.m \
   deprecated/isstr.m \
-  deprecated/lchol.m \
-  deprecated/loadimage.m \
   deprecated/krylovb.m \
-  deprecated/mark_as_command.m \
-  deprecated/mark_as_rawcommand.m \
   deprecated/perror.m \
+  deprecated/polyderiv.m \
   deprecated/replot.m \
   deprecated/saveimage.m \
   deprecated/setstr.m \
-  deprecated/spatan2.m \
-  deprecated/spchol2inv.m \
-  deprecated/spcholinv.m \
-  deprecated/spchol.m \
-  deprecated/spcumprod.m \
-  deprecated/spcumsum.m \
-  deprecated/spdet.m \
-  deprecated/spdiag.m \
-  deprecated/spfind.m \
   deprecated/sphcat.m \
-  deprecated/spinv.m \
-  deprecated/spkron.m \
-  deprecated/splchol.m \
-  deprecated/split.m \
-  deprecated/splu.m \
-  deprecated/spmax.m \
-  deprecated/spmin.m \
-  deprecated/spprod.m \
-  deprecated/spqr.m \
-  deprecated/spsum.m \
-  deprecated/spsumsq.m \
   deprecated/spvcat.m \
-  deprecated/str2mat.m \
   deprecated/strerror.m \
-  deprecated/unmark_command.m \
-  deprecated/unmark_rawcommand.m \
+  deprecated/studentize.m \
+  deprecated/sylvester_matrix.m \
   deprecated/values.m \
   deprecated/weibcdf.m \
   deprecated/weibinv.m \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/deprecated/polyderiv.m	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,108 @@
+## Copyright (C) 1994-2011 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 3 of the License, 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, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {Function File} {} polyderiv (@var{p})
+## @deftypefnx {Function File} {[@var{k}] =} polyderiv (@var{a}, @var{b})
+## @deftypefnx {Function File} {[@var{q}, @var{d}] =} polyderiv (@var{b}, @var{a})
+## Return the coefficients of the derivative of the polynomial whose
+## coefficients are given by the vector @var{p}.  If a pair of polynomials
+## is given, return the derivative of the product @math{@var{a}*@var{b}}.
+## If two inputs and two outputs are given, return the derivative of the
+## polynomial quotient @math{@var{b}/@var{a}}.  The quotient numerator is
+## in @var{q} and the denominator in @var{d}.
+## @seealso{poly, polyint, polyreduce, roots, conv, deconv, residue,
+## filter, polygcd, polyval, polyvalm}
+## @end deftypefn
+
+## Author: Tony Richardson <arichard@stark.cc.oh.us>
+## Created: June 1994
+## Adapted-By: jwe
+
+function [q, d] = polyderiv (p, a)
+
+  persistent warned = false;
+  if (! warned)
+    warned = true;
+    warning ("Octave:deprecated-function",
+             "polyderiv is obsolete and will be removed from a future version of Octave; please use polyder instead");
+  endif
+
+  if (nargin == 1 || nargin == 2)
+    if (! isvector (p))
+      error ("polyderiv: argument must be a vector");
+    endif
+    if (nargin == 2)
+      if (! isvector (a))
+        error ("polyderiv: argument must be a vector");
+      endif
+      if (nargout == 1)
+        ## derivative of p*a returns a single polynomial
+        q = polyderiv (conv (p, a));
+      else
+        ## derivative of p/a returns numerator and denominator
+        d = conv (a, a);
+        if (numel (p) == 1)
+          q = -p * polyderiv (a);
+        elseif (numel (a) == 1)
+          q = a * polyderiv (p);
+        else
+          q = conv (polyderiv (p), a) - conv (p, polyderiv (a));
+          q = polyreduce (q);
+        endif
+
+        ## remove common factors from numerator and denominator
+        x = polygcd (q, d);
+        if (length(x) != 1)
+          q = deconv (q, x);
+          d = deconv (d, x);
+        endif
+
+        ## move all the gain into the numerator
+        q = q/d(1);
+        d = d/d(1);
+      endif
+    else
+      lp = numel (p);
+      if (lp == 1)
+        q = 0;
+        return;
+      elseif (lp == 0)
+        q = [];
+        return;
+      endif
+
+      ## Force P to be a row vector.
+      p = p(:).';
+
+      q = p(1:(lp-1)) .* [(lp-1):-1:1];
+    endif
+  else
+    print_usage ();
+  endif
+
+endfunction
+
+%!assert(all (all (polyderiv ([1, 2, 3]) == [2, 2])));
+
+%!assert(polyderiv (13) == 0);
+
+%!error polyderiv ([]);
+
+%!error polyderiv ([1, 2; 3, 4]);
+
--- a/scripts/deprecated/saveimage.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/deprecated/saveimage.m	Tue Sep 20 15:38:24 2011 -0400
@@ -30,8 +30,7 @@
 ## Portable pixmap format.
 ##
 ## @item "ps"
-## PostScript format.  Note that images saved in PostScript format cannot
-## be read back into Octave with loadimage.
+## PostScript format.
 ## @end table
 ##
 ## If the fourth argument is supplied, the specified colormap will also be
@@ -42,7 +41,7 @@
 ## image is a gray scale image (the entries within each row of the colormap
 ## are equal) the gray scale ppm and PostScript image formats are used,
 ## otherwise the full color formats are used.
-## @seealso{loadimage, save, load, colormap}
+## @seealso{imread, save, load, colormap}
 ## @end deftypefn
 
 ## The conversion to PostScript is based on pbmtolps.c, which was
--- a/scripts/deprecated/spatan2.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-## Copyright (C) 2008-2011 David Bateman
-##
-## 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} {} spatan2 (@var{y}, @var{x})
-## This function has been deprecated.  Use @code{atan2} instead.
-## @end deftypefn
-
-## Deprecated in version 3.2
-
-function retval = spatan2 (varargin)
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "spatan2 is obsolete and will be removed from a future version of Octave; please use atan2 instead");
-  endif
-
-  retval = atan2 (varargin{:});
-
-endfunction
--- a/scripts/deprecated/spchol.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-## Copyright (C) 2008-2011 David Bateman
-##
-## 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn  {Loadable Function} {@var{r} =} spchol (@var{a})
-## @deftypefnx {Loadable Function} {[@var{r}, @var{p}] =} spchol (@var{a})
-## @deftypefnx {Loadable Function} {[@var{r}, @var{p}, @var{q}] =} spchol (@var{a})
-## This function has been deprecated.  Use @code{chol} instead.
-## @end deftypefn
-
-## Deprecated in version 3.2
-
-function varargout = spchol (varargin)
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "spchol is obsolete and will be removed from a future version of Octave; please use chol instead");
-  endif
-
-  varargout = cell (nargout, 1);
-  [ varargout{:} ] = chol (varargin{:});
-
-endfunction
--- a/scripts/deprecated/spchol2inv.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-## Copyright (C) 2008-2011 David Bateman
-##
-## 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} {} spchol2inv (@var{u})
-## This function has been deprecated.  Use @code{chol2inv} instead.
-## @end deftypefn
-
-## Deprecated in version 3.2
-
-function retval = spchol2inv (varargin)
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "spchol2inv is obsolete and will be removed from a future version of Octave; please use chol2inv instead");
-  endif
-
-  retval = chol2inv (varargin{:});
-
-endfunction
--- a/scripts/deprecated/spcholinv.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-## Copyright (C) 2008-2011 David Bateman
-##
-## 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} {} spcholinv (@var{u})
-## This function has been deprecated.  Use @code{cholinv} instead.
-## @end deftypefn
-
-## Deprecated in version 3.2
-
-function retval = spcholinv (varargin)
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "spcholinv is obsolete and will be removed from a future version of Octave; please use cholinv instead");
-  endif
-  retval = cholinv (varargin{:});
-
-endfunction
--- a/scripts/deprecated/spcumprod.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-## Copyright (C) 2008-2011 David Bateman
-##
-## 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} {} spcumprod (@var{x}, @var{dim})
-## This function has been deprecated.  Use @code{cumprod} instead.
-## @end deftypefn
-
-## Deprecated in version 3.2
-
-function retval = spcumprod (varargin)
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "spcumprod is obsolete and will be removed from a future version of Octave; please use cumprod instead");
-  endif
-
-  retval = cumprod (varargin{:});
-
-endfunction
--- a/scripts/deprecated/spcumsum.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-## Copyright (C) 2008-2011 David Bateman
-##
-## 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} {} spcumsum (@var{x}, @var{dim})
-## This function has been deprecated.  Use @code{cumsum} instead.
-## @end deftypefn
-
-## Deprecated in version 3.2
-
-function retval = spcumsum (varargin)
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "spcumsum is obsolete and will be removed from a future version of Octave; please use cumsum instead");
-  endif
-
-  retval = cumsum (varargin{:});
-
-endfunction
--- a/scripts/deprecated/spdet.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-## Copyright (C) 2008-2011 David Bateman
-##
-## 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Loadable Function} {[@var{d}, @var{rcond}] =} spdet (@var{a})
-## This function has been deprecated.  Use @code{det} instead.
-## @end deftypefn
-
-## Deprecated in version 3.2
-
-function varargout = spdet (varargin)
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "spdet is obsolete and will be removed from a future version of Octave; please use det instead");
-  endif
-
-  varargout = cell (nargout, 1);
-  [ varargout{:} ] = det (varargin{:});
-
-endfunction
--- a/scripts/deprecated/spdiag.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-## Copyright (C) 2008-2011 David Bateman
-##
-## 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} {} spdiag (@var{v}, @var{k})
-## This function has been deprecated.  Use @code{sparse (diag (@dots{}))}
-## instead.
-## @end deftypefn
-
-## Deprecated in version 3.2
-
-function retval = spdiag (varargin)
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "spdiag is obsolete and will be removed from a future version of Octave; please use sparse (diag (...)) instead");
-  endif
-
-  retval = sparse (diag (varargin{:}));
-
-endfunction
--- a/scripts/deprecated/spfind.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-## Copyright (C) 2008-2011 David Bateman
-##
-## 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn  {Loadable Function} {} spfind (@var{x})
-## @deftypefnx {Loadable Function} {} spfind (@var{x}, @var{n})
-## @deftypefnx {Loadable Function} {} spfind (@var{x}, @var{n}, @var{direction})
-## @deftypefnx {Loadable Function} {[@var{i}, @var{j}, @var{v}} spfind (@dots{})
-## This function has been deprecated.  Use @code{find} instead.
-## @end deftypefn
-
-## Deprecated in version 3.2
-
-function varargout = spfind (varargin)
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "spfind is obsolete and will be removed from a future version of Octave; please use find instead");
-  endif
-
-  varargout = cell (nargout, 1);
-  [ varargout{:} ] = find (varargin{:});
-
-endfunction
--- a/scripts/deprecated/spinv.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-## Copyright (C) 2008-2011 David Bateman
-##
-## 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} {[@var{x}, @var{rcond}] =} spinv (@var{a})
-## This function has been deprecated.  Use @code{inv} instead.
-## @end deftypefn
-
-## Deprecated in version 3.2
-
-function varargout = spinv (varargin)
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "spinv is obsolete and will be removed from a future version of Octave; please use inv instead");
-  endif
-
-  varargout = cell (nargout, 1);
-  [ varargout{:} ] = inv (varargin{:});
-
-endfunction
--- a/scripts/deprecated/spkron.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-## Copyright (C) 2008-2011 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} {} spkron (@var{a}, @var{b})
-## This function has been deprecated.  Use @code{kron} instead.
-## @end deftypefn
-
-## Author: jwe
-
-## Deprecated in version 3.2
-
-function retval = spkron (varargin)
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "spkron is obsolete and will be removed from a future version of Octave; please use kron instead");
-  endif
-
-  retval = kron (varargin{:});
-
-endfunction
--- a/scripts/deprecated/splchol.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-## Copyright (C) 2008-2011 David Bateman
-##
-## 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn  {Loadable Function} {@var{l} =} splchol (@var{a})
-## @deftypefnx {Loadable Function} {[@var{l}, @var{p}] =} splchol (@var{a})
-## @deftypefnx {Loadable Function} {[@var{l}, @var{p}, @var{q}] =} splchol (@var{a})
-## This function has been deprecated.  Use @code{chol (@dots{},'lower')}
-## instead.
-## @end deftypefn
-
-## Deprecated in version 3.2
-
-function varargout = splchol (varargin)
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "splchol is obsolete and will be removed from a future version of Octave; please use chol instead");
-  endif
-
-  varargout = cell (nargout, 1);
-  [ varargout{:} ] = chol (varargin{:}, "lower");
-
-endfunction
--- a/scripts/deprecated/split.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,130 +0,0 @@
-## Copyright (C) 1996-2011 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} {} split (@var{s}, @var{t}, @var{n})
-## This function has been deprecated.  Use @code{char (strsplit (s, t))}
-## instead.
-## @end deftypefn
-
-## Divides the string @var{s} into pieces separated by @var{t}, returning
-## the result in a string array (padded with blanks to form a valid
-## matrix).  If the optional input @var{n} is supplied, split @var{s}
-## into at most @var{n} different pieces.
-##
-## For example,
-##
-## @example
-## split ("Test string", "t")
-##      @result{}
-##         "Tes "
-##         " s  "
-##         "ring"
-## @end example
-##
-## @example
-## split ("Test string", "t s", 2)
-##      @result{}
-##         "Tes  "
-##         "tring"
-## @end example
-## @seealso{strtok, index}
-## @end deftypefn
-
-## Author: Kurt Hornik <Kurt.Hornik@wu-wien.ac.at>
-## Adapted-By: jwe
-
-## Deprecated in version 3.2
-
-function m = split (s, t, n)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "split is obsolete and will be removed from a future version of Octave; please use strsplit instead");
-  endif
-
-  if (nargin == 2 || nargin == 3)
-    if (nargin == 2)
-      n = length (s);
-    endif
-
-    if (ischar (s) && ischar (t))
-
-      l_s = length (s);
-      l_t = length (t);
-
-      if (l_s == 0)
-        m = "";
-        return;
-      elseif (l_t == 0)
-        m = s';
-        return;
-      elseif (l_s < l_t)
-        error ("split: S must not be shorter than T");
-      endif
-
-      if (min (size (s)) != 1 || min (size (t)) != 1)
-        error("split: multi-line strings are not supported");
-      endif
-
-      ind = findstr (s, t, 0);
-      if (length (ind) == 0)
-        m = s;
-        return;
-      elseif (n - 1 < length(ind))
-        ind = ind(1:n-1);
-      endif
-      ind2 = [1, ind+l_t];
-      ind  = [ind, l_s+1];
-
-      ind_diff = ind-ind2;
-
-      ## Create a matrix of the correct size that's filled with spaces.
-      m_rows = length (ind);
-      m_cols = max (ind_diff);
-      m = repmat (" ", m_rows, m_cols);
-
-      ## Copy the strings to the matrix.
-      for i = 1:length (ind)
-        tmp = ind2(i):(ind(i)-1);
-        m(i,1:length(tmp)) = s(tmp);
-      endfor
-    else
-      error ("split: both S and T must be strings");
-    endif
-  else
-    print_usage ();
-  endif
-
-endfunction
-
-%!assert(all (all (split ("Test string", "t") == ["Tes "; " s  "; "ring"])));
-
-%!error split ();
-
-%!assert(all (strcmp (split ("foo bar baz", " ", 2), ["foo"; "bar baz"])));
-
-%!error split ("foo", "bar", 3, 4);
-
-%!assert (all (strcmp (split("road//to/hell","/"), ["road"; "    "; "to  "; "hell"])))
-
-%!assert (all (strcmp (split("/road/to/hell/","/"), ["    "; "road"; "to  "; "hell"; "    "])))
-
-
--- a/scripts/deprecated/splu.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-## Copyright (C) 2008-2011 David Bateman
-##
-## 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn  {Loadable Function} {[@var{l}, @var{u}] =} splu (@var{a})
-## @deftypefnx {Loadable Function} {[@var{l}, @var{u}, @var{P}] =} splu (@var{a})
-## @deftypefnx {Loadable Function} {[@var{l}, @var{u}, @var{P}, @var{Q}] =} splu (@var{a})
-## @deftypefnx {Loadable Function} {[@var{l}, @var{u}, @var{P}, @var{Q}] =} splu (@dots{}, @var{thres})
-## @deftypefnx {Loadable Function} {[@var{l}, @var{u}, @var{P}] =} splu (@dots{}, @var{Q})
-## This function has been deprecated.  Use @code{lu} instead.
-## @end deftypefn
-
-## Deprecated in version 3.2
-
-function varargout = splu (varargin)
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "splu is obsolete and will be removed from a future version of Octave; please use lu instead");
-  endif
-
-  for i = 2 : nargin
-    arg = varargin {i};
-    if (! isscalar (arg))
-      error ("splu: Can no longer treat input column permutations");
-    endif
-  endfor
-
-  varargout = cell (nargout, 1);
-  [ varargout{:} ] = lu (varargin{:});
-
-endfunction
--- a/scripts/deprecated/spmax.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-## Copyright (C) 2008-2011 David Bateman
-##
-## 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn  {Mapping Function} {} spmax (@var{x}, @var{y}, @var{dim})
-## @deftypefnx {Mapping Function} {[@var{w}, @var{iw}] =} spmax (@var{x})
-## This function has been deprecated.  Use @code{max} instead.
-## @end deftypefn
-
-## Deprecated in version 3.2
-
-function varargout = spmax (varargin)
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "spmax is obsolete and will be removed from a future version of Octave; please use max instead");
-  endif
-
-  varargout = cell (nargout, 1);
-  [ varargout{:} ] = max (varargin{:});
-
-endfunction
--- a/scripts/deprecated/spmin.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-## Copyright (C) 2008-2011 David Bateman
-##
-## 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn  {Mapping Function} {} spmin (@var{x}, @var{y}, @var{dim})
-## @deftypefnx {Mapping Function} {[@var{w}, @var{iw}] =} spmin (@var{x})
-## This function has been deprecated.  Use @code{min} instead.
-## @end deftypefn
-
-## Deprecated in version 3.2
-
-function varargout = spmin (varargin)
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "spmin is obsolete and will be removed from a future version of Octave; please use min instead");
-  endif
-
-  varargout = cell (nargout, 1);
-  [ varargout{:} ] = min (varargin{:});
-
-endfunction
--- a/scripts/deprecated/spprod.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-## Copyright (C) 2008-2011 David Bateman
-##
-## 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} {} spprod (@var{x}, @var{dim})
-## This function has been deprecated.  Use @code{prod} instead.
-## @end deftypefn
-
-## Deprecated in version 3.2
-
-function retval = spprod (varargin)
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "spprod is obsolete and will be removed from a future version of Octave; please use prod instead");
-  endif
-
-  retval = prod (varargin{:});
-
-endfunction
--- a/scripts/deprecated/spqr.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-## Copyright (C) 2008-2011 David Bateman
-##
-## 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn  {Loadable Function} {@var{r} =} spqr (@var{a})
-## @deftypefnx {Loadable Function} {@var{r} =} spqr (@var{a}, 0)
-## @deftypefnx {Loadable Function} {[@var{c}, @var{r}] =} spqr (@var{a}, @var{b})
-## @deftypefnx {Loadable Function} {[@var{c}, @var{r}] =} spqr (@var{a}, @var{b}, 0)
-## This function has been deprecated.  Use @code{qr} instead.
-## @end deftypefn
-
-## Deprecated in version 3.2
-
-function varargout = spqr (varargin)
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "spqr is obsolete and will be removed from a future version of Octave; please use qr instead");
-  endif
-
-  varargout = cell (nargout, 1);
-  [ varargout{:} ] = qr (varargin{:});
-
-endfunction
--- a/scripts/deprecated/spsum.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-## Copyright (C) 2008-2011 David Bateman
-##
-## 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} {} spsum (@var{x}, @var{dim})
-## This function has been deprecated.  Use @code{sum} instead.
-## @end deftypefn
-
-## Deprecated in version 3.2
-
-function retval = spsum (varargin)
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "spsum is obsolete and will be removed from a future version of Octave; please use sum instead");
-  endif
-
-  retval = sum (varargin{:});
-
-endfunction
--- a/scripts/deprecated/spsumsq.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-## Copyright (C) 2008-2011 David Bateman
-##
-## 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} {} spsumsq (@var{x}, @var{dim})
-## This function has been deprecated.  Use @code{sumsq} instead.
-## @end deftypefn
-
-## Deprecated in version 3.2
-
-function retval = spsumsq (varargin)
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "spsumsq is obsolete and will be removed from a future version of Octave; please use sumsq instead");
-  endif
-  retval = sumsq (varargin{:});
-
-endfunction
--- a/scripts/deprecated/str2mat.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-## Copyright (C) 1996-2011 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} {} str2mat (@var{s_1}, @dots{}, @var{s_n})
-## Return a matrix containing the strings @var{s_1}, @dots{}, @var{s_n} as
-## its rows.  Each string is padded with blanks in order to form a valid
-## matrix.
-##
-## This function is modelled after @sc{matlab}.  In Octave, you can create
-## a matrix of strings by @code{[@var{s_1}; @dots{}; @var{s_n}]} even if
-## the strings are not all the same length.
-## @end deftypefn
-
-## Author: Kurt Hornik <Kurt.Hornik@wu-wien.ac.at>
-## Adapted-By: jwe
-
-## Deprecated in version 3.2
-
-function retval = str2mat (varargin)
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "str2mat is obsolete and will be removed from a future version of Octave; please use char instead");
-  endif
-
-  retval = char (varargin{:});
-
-endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/deprecated/studentize.m	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,94 @@
+## Copyright (C) 1995-2011 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 3 of the License, 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, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {Function File} {} studentize (@var{x})
+## @deftypefnx {Function File} {} studentize (@var{x}, @var{dim})
+## If @var{x} is a vector, subtract its mean and divide by its standard
+## deviation.
+##
+## If @var{x} is a matrix, do the above along the first non-singleton
+## dimension.
+## If the optional argument @var{dim} is given, operate along this dimension.
+## @seealso{center}
+## @end deftypefn
+
+## Author: KH <Kurt.Hornik@wu-wien.ac.at>
+## Description: Subtract mean and divide by standard deviation
+
+function t = studentize (x, dim)
+  persistent warned = false;
+  if (! warned)
+    warned = true;
+    warning ("Octave:deprecated-function",
+             "studentize is obsolete and will be removed from a future version of Octave; please use zscore instead");
+  endif
+
+  if (nargin != 1 && nargin != 2)
+    print_usage ();
+  endif
+
+  if (! isnumeric(x))
+    error ("studentize: X must be a numeric vector or matrix");
+  endif
+
+  if (isinteger (x))
+    x = double (x);
+  endif
+
+  nd = ndims (x);
+  sz = size (x);
+  if (nargin != 2)
+    ## Find the first non-singleton dimension.
+    dim = find (sz > 1, 1);
+    if (isempty (dim))
+      dim = 1;
+    endif
+  else
+    if (!(isscalar (dim) && dim == fix (dim))
+        || !(1 <= dim && dim <= nd))
+      error ("studentize: DIM must be an integer and a valid dimension");
+    endif
+  endif
+
+  c = sz(dim);
+  if (c == 0)
+    t = x;
+  else
+    idx = ones (1, nd);
+    idx(dim) = c;
+    t = x - repmat (mean (x, dim), idx);
+    t = t ./ repmat (max (cat (dim, std(t, [], dim), ! any (t, dim)), [], dim), idx);
+  endif
+
+endfunction
+
+%!assert(studentize ([1,2,3]), [-1,0,1])
+%!assert(studentize (int8 ([1,2,3])), [-1,0,1])
+#%!assert(studentize (ones (3,2,0,2)), zeros (3,2,0,2))
+%!assert(studentize ([2,0,-2;0,2,0;-2,-2,2]), [1,0,-1;0,1,0;-1,-1,1])
+
+%% Test input validation
+%!error studentize ()
+%!error studentize (1, 2, 3)
+%!error studentize ([true true])
+%!error studentize (1, ones(2,2))
+%!error studentize (1, 1.5)
+%!error studentize (1, 0)
+%!error studentize (1, 3)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/deprecated/sylvester_matrix.m	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,69 @@
+## Copyright (C) 1996-2011 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 3 of the License, 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, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {} sylvester_matrix (@var{k})
+## Return the Sylvester matrix of order
+## @tex
+## $n = 2^k$.
+## @end tex
+## @ifnottex
+## n = 2^@var{k}.
+## @end ifnottex
+##
+## @seealso{toeplitz, hankel}
+## @end deftypefn
+
+## Author: jwe
+
+function retval = sylvester_matrix (k)
+
+  persistent warned = false;
+  if (! warned)
+    warned = true;
+    warning ("Octave:deprecated-function",
+             "sylvester_matrix is obsolete and will be removed from a future version of Octave; please use hadamard(2^k) instead");
+  endif
+
+  if (nargin != 1)
+    print_usage ();
+  endif
+
+  if (isscalar (k))
+    if (k < 1)
+      retval = 1;
+    else
+      tmp = sylvester_matrix (k-1);
+      retval = [tmp, tmp; tmp, -tmp];
+    endif
+  else
+    error ("sylvester_matrix: expecting scalar argument");
+  endif
+
+endfunction
+
+%!assert((sylvester_matrix (1) == [1, 1; 1, -1]
+%! && (sylvester_matrix (2)
+%! == [1, 1, 1, 1; 1, -1, 1, -1; 1, 1, -1, -1; 1, -1, -1, 1])));
+
+%!error sylvester_matrix ([1, 2; 3, 4]);
+
+%!error sylvester_matrix ();
+
+%!error sylvester_matrix (1, 2);
+
--- a/scripts/deprecated/unmark_command.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-## Copyright (C) 2009-2011 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Built-in Function} {} unmark_command (@var{name})
-## This function is obsolete and will be removed from a future
-## version of Octave.
-## @end deftypefn
-
-## Author: jwe
-
-## Deprecated in version 3.2
-
-function unmark_command ()
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "unmark_command is obsolete and will be removed from a future version of Octave");
-  endif
-
-endfunction
--- a/scripts/deprecated/unmark_rawcommand.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-## Copyright (C) 2009-2011 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Built-in Function} {} unmark_rawcommand (@var{name})
-## This function is obsolete and will be removed from a future
-## version of Octave.
-## @end deftypefn
-
-## Author: jwe
-
-## Deprecated in version 3.2
-
-function unmark_rawcommand ()
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "unmark_rawcommand is obsolete and will be removed from a future version of Octave");
-  endif
-
-endfunction
--- a/scripts/elfun/lcm.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-## Copyright (C) 1994-2011 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn  {Mapping Function} {} lcm (@var{x}, @var{y})
-## @deftypefnx {Mapping Function} {} lcm (@var{x}, @var{y}, @dots{})
-## Compute the least common multiple of @var{x} and @var{y},
-## or of the list of all arguments.  All elements must be the same size or
-## scalar.
-## @seealso{factor, gcd}
-## @end deftypefn
-
-## Author: KH <Kurt.Hornik@wu-wien.ac.at>
-## Created: 16 September 1994
-## Adapted-By: jwe
-
-function l = lcm (varargin)
-
-  if (nargin > 1)
-    if (common_size (varargin{:}) != 0)
-      error ("lcm: all args must be of the same size or scalar");
-    elseif (! all (cellfun (@isnumeric, varargin)))
-      error ("lcm: all arguments must be numeric");
-    endif
-
-    l = varargin{1};
-    for i = 2:nargin
-      x = varargin{i};
-      msk = l == 0 & x == 0;
-      l .*= x ./ gcd (l, x);
-      l(msk) = 0;
-    endfor
-  else
-    print_usage ();
-  endif
-
-endfunction
-
-%!assert(lcm (3, 5, 7, 15) == 105);
-
-%!error lcm ();
-
-%!test
-%! s.a = 1;
-%! fail("lcm (s)");
-
--- a/scripts/elfun/module.mk	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/elfun/module.mk	Tue Sep 20 15:38:24 2011 -0400
@@ -20,7 +20,6 @@
   elfun/csc.m \
   elfun/cscd.m \
   elfun/csch.m \
-  elfun/lcm.m \
   elfun/sec.m \
   elfun/secd.m \
   elfun/sech.m \
--- a/scripts/general/accumarray.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/general/accumarray.m	Tue Sep 20 15:38:24 2011 -0400
@@ -100,7 +100,7 @@
   endif
 
   if (iscell (subs))
-    subs = cellfun (@vec, subs, "uniformoutput", false);
+    subs = cellfun ("vec", subs, "uniformoutput", false);
     ndims = numel (subs);
     if (ndims == 1)
       subs = subs{1};
@@ -177,7 +177,7 @@
     if (ndims > 1)
       if (isempty (sz))
         if (iscell (subs))
-          sz = cellfun (@max, subs);
+          sz = cellfun ("max", subs);
         else
           sz = max (subs, [], 1);
         endif
--- a/scripts/general/accumdim.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/general/accumdim.m	Tue Sep 20 15:38:24 2011 -0400
@@ -42,12 +42,12 @@
 ##
 ## An example of the use of @code{accumdim} is:
 ##
-## @example
+## @smallexample
 ## @group
 ## accumdim ([1, 2, 1, 2, 1], [7,-10,4;-5,-12,8;-12,2,8;-10,9,-3;-5,-3,-13])
 ## @result{} ans = [-10,-11,-1;-15,-3,5]
 ## @end group
-## @end example
+## @end smallexample
 ##
 ## @seealso{accumarray}
 ## @end deftypefn
--- a/scripts/general/arrayfun.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/general/arrayfun.m	Tue Sep 20 15:38:24 2011 -0400
@@ -154,7 +154,7 @@
   args = varargin(1:nargs);
   opts = varargin(nargs+1:end);
 
-  args = cellfun (@num2cell, args, "UniformOutput", false,
+  args = cellfun ("num2cell", args, "UniformOutput", false,
   "ErrorHandler",  @arg_class_error);
 
   [varargout{1:max(1, nargout)}] = cellfun (func, args{:}, opts{:});
--- a/scripts/general/bitget.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/general/bitget.m	Tue Sep 20 15:38:24 2011 -0400
@@ -79,3 +79,31 @@
   C = bitand (A, bitshift (_conv (1), uint8 (n) - uint8 (1))) != _conv (0);
 
 endfunction
+
+%!error bitget (1);
+%!error bitget (1, 2, 3);
+
+%!test
+%! assert (bitget ([4, 14], [3, 3]), logical ([1, 1]));
+%! pfx = {"", "u"};
+%! for i = 1:2
+%!   for prec = [8, 16, 32, 64]
+%!     fcn = str2func (sprintf ("%sint%d", pfx{i}, prec));
+%!     assert (bitget (fcn ([4, 14]), [3, 3]), logical ([1, 1]));
+%!   endfor
+%! endfor
+
+%!error bitget (0, 0);
+%!error bitget (0, 55);
+
+%!error bitget (int8 (0), 9);
+%!error bitget (uint8 (0), 9);
+
+%!error bitget (int16 (0), 17);
+%!error bitget (uint16 (0), 17);
+
+%!error bitget (int32 (0), 33);
+%!error bitget (uint32 (0), 33);
+
+%!error bitget (int64 (0), 65);
+%!error bitget (uint64 (0), 65);
--- a/scripts/general/bitset.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/general/bitset.m	Tue Sep 20 15:38:24 2011 -0400
@@ -92,3 +92,31 @@
   endif
 
 endfunction
+
+%!error bitset (1);
+%!error bitset (1, 2, 3, 4);
+
+%!test
+%! assert (bitset ([0, 10], [3, 3]), [4, 14]);
+%! pfx = {"", "u"};
+%! for i = 1:2
+%!   for prec = [8, 16, 32, 64]
+%!     fcn = str2func (sprintf ("%sint%d", pfx{i}, prec));
+%!     assert (bitset (fcn ([0, 10]), [3, 3]), fcn ([4, 14]));
+%!   endfor
+%! endfor
+
+%!error bitset (0, 0);
+%!error bitset (0, 55);
+
+%!error bitset (int8 (0), 9);
+%!error bitset (uint8 (0), 9);
+
+%!error bitset (int16 (0), 17);
+%!error bitset (uint16 (0), 17);
+
+%!error bitset (int32 (0), 33);
+%!error bitset (uint32 (0), 33);
+
+%!error bitset (int64 (0), 65);
+%!error bitset (uint64 (0), 65);
--- a/scripts/general/blkdiag.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/general/blkdiag.m	Tue Sep 20 15:38:24 2011 -0400
@@ -20,8 +20,9 @@
 ## @deftypefn {Function File} {} blkdiag (@var{A}, @var{B}, @var{C}, @dots{})
 ## Build a block diagonal matrix from @var{A}, @var{B}, @var{C}, @dots{}
 ## All the arguments must be numeric and are two-dimensional matrices or
-## scalars.
-## @seealso{diag, horzcat, vertcat}
+## scalars. If any argument is of type sparse, the output will also be
+## sparse.
+## @seealso{diag, horzcat, vertcat, sparse}
 ## @end deftypefn
 
 ## Author: Daniel Calvelo
@@ -33,7 +34,7 @@
     print_usage ();
   endif
 
-  if (! all (cellfun (@isnumeric, varargin)))
+  if (! all (cellfun ("isnumeric", varargin)))
     error ("blkdiag: all arguments must be numeric");
   endif
 
@@ -46,7 +47,12 @@
   ## calling size directly.
   tmp = cell2mat (cellfun (@size, varargin', "uniformoutput", false));
   csz = cumsum ([0 0; tmp], 1);
-  retval = zeros (csz(end,:));
+
+  if (any (cellfun ("issparse", varargin)))
+    retval = sparse (csz(end,1), csz(end,2));
+  else
+    retval = zeros (csz(end,:));
+  endif
 
   for p = 1:nargin
     vp = varargin{p};
@@ -57,15 +63,18 @@
 
 endfunction
 
-# regular tests
+## regular tests
 %!assert(blkdiag(1,ones(2),1),[1,0,0,0;0,1,1,0;0,1,1,0;0,0,0,1])
 %!assert(blkdiag([1,2],[3,4],[5,6]),[1,2,0,0,0,0;0,0,3,4,0,0;0,0,0,0,5,6])
 %!assert(blkdiag([1,2],[3;4],[5,6]),[1,2,0,0,0;0,0,3,0,0;0,0,4,0,0;0,0,0,5,6])
 %!assert(blkdiag([1,2;3,4],[5,6,7]),[1,2,0,0,0;3,4,0,0,0;0,0,5,6,7])
-# tests involving empty matrices
+## tests involving empty matrices
 %!assert(blkdiag([],[],[]),[])
 %!assert(blkdiag([],[1,2;3,4],[],5,[]),[1,2,0;3,4,0;0,0,5])
 %!assert(blkdiag(zeros(1,0,1),[1,2,3],1,0,5,zeros(0,1,1)),[0,0,0,0,0,0,0;1,2,3,0,0,0,0;0,0,0,1,0,0,0;0,0,0,0,0,0,0;0,0,0,0,0,5,0]);
+## tests involving sparse matrices
+%!assert (blkdiag (sparse([1,2;3,4]),[5,6;7,8]), sparse([1,2,0,0;3,4,0,0;0,0,5,6;0,0,7,8]))
+%!assert (blkdiag (sparse([1,2;3,4]),[5,6]), sparse([1,2,0,0;3,4,0,0;0,0,5,6]))
 # sanity checks
 %!test
 %! A = rand (round (rand (1, 2) * 10));
--- a/scripts/general/cell2mat.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/general/cell2mat.m	Tue Sep 20 15:38:24 2011 -0400
@@ -43,11 +43,11 @@
   else
 
     ## We only want numeric, logical, and char matrices.
-    valid = cellfun (@isnumeric, c);
-    valid |= cellfun (@islogical, c);
-    valid |= cellfun (@ischar, c);
-    validc = cellfun (@iscell, c);
-    valids = cellfun (@isstruct, c);
+    valid = cellfun ("isnumeric", c);
+    valid |= cellfun ("islogical", c);
+    valid |= cellfun ("isclass", c, "char");
+    validc = cellfun ("isclass", c, "cell");
+    valids = cellfun ("isclass", c, "struct");
 
     if (! all (valid(:)) && ! all (validc(:)) && ! all (valids(:)))
       error ("cell2mat: wrong type elements or mixed cells, structs and matrices");
@@ -71,7 +71,7 @@
       endif
       xdim = [1:idim-1, idim+1:nd];
       cc = num2cell (c, xdim);
-      c = cellfun (@cat, {idim}, cc{:}, "uniformoutput", false);
+      c = cellfun ("cat", {idim}, cc{:}, "uniformoutput", false);
     endfor
     m = c{1};
   endif
--- a/scripts/general/celldisp.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/general/celldisp.m	Tue Sep 20 15:38:24 2011 -0400
@@ -80,4 +80,8 @@
 
 %!demo
 %! c = {1, 2, {31, 32}};
-%! celldisp(c, "b")
\ No newline at end of file
+%! celldisp(c, "b")
+
+%!error celldisp ();
+%!error celldisp ({}, "name", 1);
+%!error celldisp (1);
--- a/scripts/general/colon.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/general/colon.m	Tue Sep 20 15:38:24 2011 -0400
@@ -38,3 +38,7 @@
     error ("colon: not defined for class \"%s\"", class(varargin{1}));
   endif
 endfunction
+
+%!error colon (1)
+
+## FIXME -- what does colon () mean since it doesn't set a return value?
--- a/scripts/general/common_size.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/general/common_size.m	Tue Sep 20 15:38:24 2011 -0400
@@ -52,7 +52,7 @@
   endif
 
   ## Find scalar args.
-  nscal = cellfun (@numel, varargin) != 1;
+  nscal = cellfun ("numel", varargin) != 1;
 
   i = find (nscal, 1);
 
@@ -60,7 +60,7 @@
     errorcode = 0;
     varargout = varargin;
   else
-    match = cellfun (@size_equal, varargin, varargin(i));
+    match = cellfun ("size_equal", varargin, varargin(i));
     if (any (nscal &! match))
       errorcode = 1;
       varargout = varargin;
@@ -78,3 +78,13 @@
     endif
   endif
 endfunction
+
+%!error common_size ();
+
+%!test
+%! m = [1,2;3,4];
+%! [err, a, b, c] = common_size (m, 3, 5);
+%! assert (err, 0);
+%! assert (a, m);
+%! assert (b, [3,3;3,3]);
+%! assert (c, [5,5;5,5]);
--- a/scripts/general/dblquad.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/general/dblquad.m	Tue Sep 20 15:38:24 2011 -0400
@@ -37,22 +37,23 @@
 ##
 ## The optional argument @var{quadf} specifies which underlying integrator
 ## function to use.  Any choice but @code{quad} is available and the default
-## is @code{quadgk}.
+## is @code{quadcc}.
 ##
 ## Additional arguments, are passed directly to @var{f}.  To use the default
-## value for @var{tol} or @var{quadf} one may pass an empty matrix ([]).
+## value for @var{tol} or @var{quadf} one may pass ':' or an empty matrix ([]).
 ## @seealso{triplequad, quad, quadv, quadl, quadgk, quadcc, trapz}
 ## @end deftypefn
 
-function q = dblquad(f, xa, xb, ya, yb, tol, quadf, varargin)
+function q = dblquad (f, xa, xb, ya, yb, tol = 1e-6, quadf = @quadcc, varargin)
+
   if (nargin < 5)
     print_usage ();
   endif
-  if (nargin < 6 || isempty (tol))
+  if (isempty (tol))
     tol = 1e-6;
   endif
-  if (nargin < 7 || isempty (quadf))
-    quadf = @quadgk;
+  if (isempty (quadf))
+    quadf = @quadcc;
   endif
 
   inner = @__dblquad_inner__;
@@ -72,10 +73,10 @@
   endfor
 endfunction
 
-%% Nasty integrand to show quadgk off
+%% Nasty integrand to show quadcc off
 %!assert (dblquad (@(x,y) 1 ./ (x+y), 0, 1, 0, 1), 2*log(2), 1e-6)
 
-%!assert (dblquad (@(x,y) exp(-x.^2 - y.^2) , -1, 1, -1, 1, [],  @quadgk), pi * erf(1).^2, 1e-6)
-%!assert (dblquad (@(x,y) exp(-x.^2 - y.^2) , -1, 1, -1, 1, [],  @quadl), pi * erf(1).^2, 1e-6)
-%!assert (dblquad (@(x,y) exp(-x.^2 - y.^2) , -1, 1, -1, 1, [],  @quadv), pi * erf(1).^2, 1e-6)
+%!assert (dblquad (@(x,y) exp(-x.^2 - y.^2) , -1, 1, -1, 1, 1e-6, @quadgk), pi * erf(1).^2, 1e-6)
+%!assert (dblquad (@(x,y) exp(-x.^2 - y.^2) , -1, 1, -1, 1, 1e-6, @quadl), pi * erf(1).^2, 1e-6)
+%!assert (dblquad (@(x,y) exp(-x.^2 - y.^2) , -1, 1, -1, 1, 1e-6, @quadv), pi * erf(1).^2, 1e-6)
 
--- a/scripts/general/flipdim.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/general/flipdim.m	Tue Sep 20 15:38:24 2011 -0400
@@ -43,9 +43,10 @@
   endif
 
   nd = ndims (x);
+  sz = size (x);
   if (nargin == 1)
     ## Find the first non-singleton dimension.
-    [~, dim] = min (size (x) != 1);
+    (dim = find (sz > 1, 1)) || (dim = 1);
   elseif (! (isscalar (dim) && isindex (dim)))
     error ("flipdim: DIM must be a positive integer");
   endif
@@ -55,3 +56,12 @@
   y = x(idx{:});
 
 endfunction
+
+%!error flipdim ();
+%!error flipdim (1, 2, 3);
+
+%!assert (flipdim ([1,2;3,4]), flipdim ([1,2 ; 3,4], 1));
+%!assert (flipdim ([1,2;3,4], 2), [2,1;4,3]);
+%!assert (flipdim ([1,2;3,4], 3), [1,2;3,4]);
+
+## FIXME -- we need tests for multidimensional arrays.
--- a/scripts/general/gradient.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/general/gradient.m	Tue Sep 20 15:38:24 2011 -0400
@@ -88,7 +88,7 @@
   if (isvector (m))
     ## make a row vector.
     transposed = (size (m, 2) == 1);
-    m = m(:)';
+    m = m(:).';
   endif
 
   nd = ndims (m);
@@ -259,6 +259,34 @@
 %! assert (all(dU(:)==2));
 
 %!test
+%! [Y,X,Z,U] = ndgrid (2:2:8,1:5,4:4:12,3:5:30);
+%! [dX,dY,dZ,dU] = gradient (X+j*X);
+%! assert (all(dX(:)==1+1j));
+%! assert (all(dY(:)==0));
+%! assert (all(dZ(:)==0));
+%! assert (all(dU(:)==0));
+%! [dX,dY,dZ,dU] = gradient (Y-j*Y);
+%! assert (all(dX(:)==0));
+%! assert (all(dY(:)==2-j*2));
+%! assert (all(dZ(:)==0));
+%! assert (all(dU(:)==0));
+%! [dX,dY,dZ,dU] = gradient (Z+j*1);
+%! assert (all(dX(:)==0));
+%! assert (all(dY(:)==0));
+%! assert (all(dZ(:)==4));
+%! assert (all(dU(:)==0));
+%! [dX,dY,dZ,dU] = gradient (U-j*1);
+%! assert (all(dX(:)==0));
+%! assert (all(dY(:)==0));
+%! assert (all(dZ(:)==0));
+%! assert (all(dU(:)==5));
+%! assert (size_equal(dX, dY, dZ, dU, X, Y, Z, U));
+%! [dX,dY,dZ,dU] = gradient (U, 5.0);
+%! assert (all(dU(:)==1));
+%! [dX,dY,dZ,dU] = gradient (U, 1.0, 2.0, 3.0, 2.5);
+%! assert (all(dU(:)==2));
+
+%!test
 %! x = 0:10;
 %! f = @cos;
 %! df_dx = @(x) -sin (x);
--- a/scripts/general/int2str.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/general/int2str.m	Tue Sep 20 15:38:24 2011 -0400
@@ -49,31 +49,33 @@
 
 function retval = int2str (n)
 
-  if (nargin == 1)
-    n = round (real(n));
-    sz = size(n);
-    nd = ndims (n);
-    nc = columns (n);
-    if (nc > 1)
-      idx = cell ();
-      for i = 1:nd
-        idx{i} = 1:sz(i);
-      endfor
-      idx(2) = 1;
-      ifmt = get_fmt (n(idx{:}), 0);
-      idx(2) = 2:sz(2);
-      rfmt = get_fmt (n(idx{:}), 2);
-      fmt = cstrcat (ifmt, repmat (rfmt, 1, nc-1), "\n");
-    else
-      fmt = cstrcat (get_fmt (n, 0), "\n");
-    endif
-    tmp = sprintf (fmt, permute (n, [2, 1, 3 : nd]));
-    tmp(end) = "";
-    retval = char (strsplit (tmp, "\n"));
-  else
+  if (nargin != 1)
     print_usage ();
   endif
 
+  if (isempty (n))
+    retval = '';
+    return;
+  endif
+
+  n = round (real(n));
+  sz = size(n);
+  nd = ndims (n);
+  nc = columns (n);
+  if (nc > 1)
+    idx = repmat ({':'}, nd, 1);
+    idx(2) = 1;
+    ifmt = get_fmt (n(idx{:}), 0);
+    idx(2) = 2:sz(2);
+    rfmt = get_fmt (n(idx{:}), 2);
+    fmt = cstrcat (ifmt, repmat (rfmt, 1, nc-1), "\n");
+  else
+    fmt = cstrcat (get_fmt (n, 0), "\n");
+  endif
+  tmp = sprintf (fmt, permute (n, [2, 1, 3 : nd]));
+  tmp(end) = "";
+  retval = char (strsplit (tmp, "\n"));
+
 endfunction
 
 function fmt = get_fmt (x, sep)
@@ -112,8 +114,10 @@
 
 endfunction
 
-%!assert(strcmp (int2str (-123), "-123") && strcmp (int2str (1.2), "1"));
+%!assert (strcmp (int2str (-123), "-123") && strcmp (int2str (1.2), "1"));
 %!assert (all (int2str ([1, 2, 3; 4, 5, 6]) == ["1  2  3";"4  5  6"]));
+%!assert (int2str([]), "");
+
 %!error int2str ();
 %!error int2str (1, 2);
 
--- a/scripts/general/interp1.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/general/interp1.m	Tue Sep 20 15:38:24 2011 -0400
@@ -43,7 +43,7 @@
 ## Piecewise cubic Hermite interpolating polynomial
 ##
 ## @item 'cubic'
-## Cubic interpolation from four nearest neighbors
+## Cubic interpolation (same as @code{pchip})
 ##
 ## @item 'spline'
 ## Cubic spline interpolation---smooth first and second derivatives
@@ -112,7 +112,7 @@
   method = "linear";
   extrap = NA;
   xi = [];
-  pp = false;
+  ispp = false;
   firstnumeric = true;
 
   if (nargin > 2)
@@ -123,7 +123,7 @@
         if (strcmp ("extrap", arg))
           extrap = "extrap";
         elseif (strcmp ("pp", arg))
-          pp = true;
+          ispp = true;
         else
           method = arg;
         endif
@@ -138,7 +138,7 @@
     endfor
   endif
 
-  if (isempty (xi) && firstnumeric && ! pp)
+  if (isempty (xi) && firstnumeric && ! ispp)
     xi = y;
     y = x;
     x = 1:numel(y);
@@ -150,9 +150,8 @@
   szx = size (xi);
   if (isvector (y))
     y = y(:);
-  elseif (isvector (xi))
-    szx = length (xi);
   endif
+
   szy = size (y);
   y = y(:,:);
   [ny, nc] = size (y);
@@ -191,147 +190,85 @@
 
   switch (method)
   case "nearest"
-    if (pp)
-      yi = mkpp ([x(1); (x(1:nx-1)+x(2:nx))/2; x(nx)], y, szy(2:end));
+    pp = mkpp ([x(1); (x(1:nx-1)+x(2:nx))/2; x(nx)], shiftdim (y, 1), szy(2:end));
+    pp.orient = "first";
+
+    if (ispp)
+      yi = pp;
     else
-      idx = lookup (0.5*(x(1:nx-1)+x(2:nx)), xi) + 1;
-      yi = y(idx,:);
+      yi = ppval (pp, reshape (xi, szx));
     endif
   case "*nearest"
-    if (pp)
-      yi = mkpp ([x(1); x(1)+[0.5:(nx-1)]'*dx; x(nx)], y, szy(2:end));
+    pp = mkpp ([x(1), x(1)+[0.5:(nx-1)]*dx, x(nx)], shiftdim (y, 1), szy(2:end));
+    pp.orient = "first";
+    if (ispp)
+      yi = pp;
     else
-      idx = max (1, min (ny, floor((xi-x(1))/dx+1.5)));
-      yi = y(idx,:);
+      yi = ppval(pp, reshape (xi, szx));
     endif
   case "linear"
     dy = diff (y);
     dx = diff (x);
-    if (pp)
-      coefs = [dy./dx, y(1:nx-1)];
-      xx = x;
-      if (have_jumps)
-        ## Omit zero-size intervals.
-        coefs(jumps) = [];
-        xx(jumps) = [];
-      endif
-      yi = mkpp (xx, coefs, szy(2:end));
+    dx = repmat (dx, [1 size(dy)(2:end)]);
+    coefs = [(dy./dx).'(:), y(1:nx-1, :).'(:)];
+    xx = x;
+
+    if (have_jumps)
+      ## Omit zero-size intervals.
+      coefs(jumps, :) = [];
+      xx(jumps) = [];
+    endif
+
+    pp = mkpp (xx, coefs, szy(2:end));
+    pp.orient = "first";
+
+    if (ispp)
+      yi = pp;
     else
-      ## find the interval containing the test point
-      idx = lookup (x, xi, "lr");
-      ## use the endpoints of the interval to define a line
-      s = (xi - x(idx))./dx(idx);
-      yi = bsxfun (@times, s, dy(idx,:)) + y(idx,:);
-      if (have_jumps)
-        ## Fix the corner cases of discontinuities at boundaries.
-        ## Internal discontinuities already handled correctly.
-        if (jumps (1))
-          mask = xi < x(1);
-          yi(mask,:) = y(1*ones (1, sum (mask)),:);
-        endif
-        if (jumps(nx-1))
-          mask = xi >= x(nx);
-          yi(mask,:) = y(nx*ones (1, sum (mask)),:);
-        endif
-      endif
+      yi = ppval(pp, reshape (xi, szx));
     endif
+
   case "*linear"
     dy = diff (y);
-    if (pp)
-      yi = mkpp (x(1) + [0:ny-1]*dx, [dy./dx, y(1:end-1)], szy(2:end));
+    coefs = [(dy/dx).'(:), y(1:nx-1, :).'(:)];
+    pp = mkpp (x, coefs, szy(2:end));
+    pp.orient = "first";
+
+    if (ispp)
+      yi = pp;
     else
-      ## find the interval containing the test point
-      t = (xi - x(1))/dx + 1;
-      idx = max (1, min (ny - 1, floor (t)));
+      yi = ppval(pp, reshape (xi, szx));
+    endif
 
-      ## use the endpoints of the interval to define a line
-      s = t - idx;
-      yi = bsxfun (@times, s, dy(idx,:)) + y(idx,:);
-    endif
-  case {"pchip", "*pchip"}
+  case {"pchip", "*pchip", "cubic", "*cubic"}
     if (nx == 2 || starmethod)
       x = linspace (x(1), x(nx), ny);
     endif
-    ## Note that pchip's arguments are transposed relative to interp1
-    if (pp)
-      yi = pchip (x.', y.');
-      yi.d = szy(2:end);
-    else
-      yi = pchip (x.', y.', xi.').';
-    endif
 
-  case {"cubic", "*cubic"}
-    if (nx < 4 || ny < 4)
-      error ("interp1: table too short");
-    endif
-
-    ## FIXME Is there a better way to treat pp return and *cubic
-    if (starmethod && ! pp)
-      ## From: Miloje Makivic
-      ## http://www.npac.syr.edu/projects/nasa/MILOJE/final/node36.html
-      t = (xi - x(1))/dx + 1;
-      idx = max (min (floor (t), ny-2), 2);
-      t = t - idx;
-      t2 = t.*t;
-      tp = 1 - 0.5*t;
-      a = (1 - t2).*tp;
-      b = (t2 + t).*tp;
-      c = (t2 - t).*tp/3;
-      d = (t2 - 1).*t/6;
-      J = ones (1, nc);
-
-      yi = a(:,J) .* y(idx,:) + b(:,J) .* y(idx+1,:) ...
-      + c(:,J) .* y(idx-1,:) + d(:,J) .* y(idx+2,:);
+    if (ispp)
+      y = shiftdim (reshape (y, szy), 1);
+      yi = pchip (x, y);
     else
-      if (starmethod)
-        x = linspace (x(1), x(nx), ny).';
-        nx = ny;
-      endif
-
-      idx = lookup (x(2:nx-1), xi, "lr");
-
-      ## Construct cubic equations for each interval using divided
-      ## differences (computation of c and d don't use divided differences
-      ## but instead solve 2 equations for 2 unknowns). Perhaps
-      ## reformulating this as a lagrange polynomial would be more efficient.
-      i = 1:nx-3;
-      J = ones (1, nc);
-      dx = diff (x);
-      dx2 = x(i+1).^2 - x(i).^2;
-      dx3 = x(i+1).^3 - x(i).^3;
-      a = diff (y, 3)./dx(i,J).^3/6;
-      b = (diff (y(1:nx-1,:), 2)./dx(i,J).^2 - 6*a.*x(i+1,J))/2;
-      c = (diff (y(1:nx-2,:), 1) - a.*dx3(:,J) - b.*dx2(:,J))./dx(i,J);
-      d = y(i,:) - ((a.*x(i,J) + b).*x(i,J) + c).*x(i,J);
-
-      if (pp)
-        xs = [x(1);x(3:nx-2)];
-        yi = mkpp ([x(1);x(3:nx-2);x(nx)],
-                   [a(:), (b(:) + 3.*xs(:,J).*a(:)), ...
-                    (c(:) + 2.*xs(:,J).*b(:) + 3.*xs(:,J)(:).^2.*a(:)), ...
-                    (d(:) + xs(:,J).*c(:) + xs(:,J).^2.*b(:) + ...
-                     xs(:,J).^3.*a(:))], szy(2:end));
-      else
-        yi = ((a(idx,:).*xi(:,J) + b(idx,:)).*xi(:,J) ...
-              + c(idx,:)).*xi(:,J) + d(idx,:);
-      endif
+      y = shiftdim (y, 1);
+      yi = pchip (x, y, reshape (xi, szx));
     endif
   case {"spline", "*spline"}
     if (nx == 2 || starmethod)
       x = linspace(x(1), x(nx), ny);
     endif
-    ## Note that spline's arguments are transposed relative to interp1
-    if (pp)
-      yi = spline (x.', y.');
-      yi.d = szy(2:end);
+
+    if (ispp)
+      y = shiftdim (reshape (y, szy), 1);
+      yi = spline (x, y);
     else
-      yi = spline (x.', y.', xi.').';
+      y = shiftdim (y, 1);
+      yi = spline (x, y, reshape (xi, szx));
     endif
   otherwise
     error ("interp1: invalid method '%s'", method);
   endswitch
 
-  if (! pp)
+  if (! ispp)
     if (! ischar (extrap))
       ## determine which values are out of range and set them to extrap,
       ## unless extrap == "extrap".
@@ -339,10 +276,24 @@
       maxx = max (x(1), x(nx));
 
       outliers = xi < minx | ! (xi <= maxx); # this catches even NaNs
-      yi(outliers, :) = extrap;
+      if (size_equal (outliers, yi))
+        yi(outliers) = extrap;
+        yi = reshape (yi, szx);
+      elseif (!isvector (yi))
+        if (strcmp (method, "pchip") || strcmp (method, "*pchip")
+          ||strcmp (method, "cubic") || strcmp (method, "*cubic")
+          ||strcmp (method, "spline") || strcmp (method, "*spline"))
+          yi(:, outliers) = extrap;
+          yi = shiftdim(yi, 1);
+        else
+          yi(outliers, :) = extrap;
+        endif
+      else
+        yi(outliers.') = extrap;
+      endif
     endif
-
-    yi = reshape (yi, [szx, szy(2:end)]);
+  else
+    yi.orient = "first";
   endif
 
 endfunction
@@ -394,6 +345,7 @@
 %! %--------------------------------------------------------
 %! % confirm that interpolated function matches the original
 
+##FIXME: add test for n-d arguments here
 
 ## For each type of interpolated test, confirm that the interpolated
 ## value at the knots match the values at the knots.  Points away
@@ -595,7 +547,6 @@
 %!assert (interp1(1:2,1:2,1.4,"nearest"),1);
 %!error interp1(1,1,1, "linear");
 %!assert (interp1(1:2,1:2,1.4,"linear"),1.4);
-%!error interp1(1:3,1:3,1, "cubic");
 %!assert (interp1(1:4,1:4,1.4,"cubic"),1.4);
 %!assert (interp1(1:2,1:2,1.1, "spline"), 1.1);
 %!assert (interp1(1:3,1:3,1.4,"spline"),1.4);
@@ -604,7 +555,6 @@
 %!assert (interp1(1:2:4,1:2:4,1.4,"*nearest"),1);
 %!error interp1(1,1,1, "*linear");
 %!assert (interp1(1:2:4,1:2:4,[0,1,1.4,3,4],"*linear"),[NA,1,1.4,3,NA]);
-%!error interp1(1:3,1:3,1, "*cubic");
 %!assert (interp1(1:2:8,1:2:8,1.4,"*cubic"),1.4);
 %!assert (interp1(1:2,1:2,1.3, "*spline"), 1.3);
 %!assert (interp1(1:2:6,1:2:6,1.4,"*spline"),1.4);
@@ -612,5 +562,5 @@
 %!assert (interp1([3,2,1],[3,2,2],2.5),2.5)
 
 %!assert (interp1 ([1,2,2,3,4],[0,1,4,2,1],[-1,1.5,2,2.5,3.5], "linear", "extrap"), [-2,0.5,4,3,1.5])
-%!assert (interp1 ([4,4,3,2,0],[0,1,4,2,1],[1.5,4,4.5], "linear"), [0,1,NA])
+%!assert (interp1 ([4,4,3,2,0],[0,1,4,2,1],[1.5,4,4.5], "linear"), [1.75,1,NA])
 %!assert (interp1 (0:4, 2.5), 1.5)
--- a/scripts/general/interpft.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/general/interpft.m	Tue Sep 20 15:38:24 2011 -0400
@@ -76,10 +76,8 @@
   k = floor (m / 2);
   sz = size (x);
   sz(1) = n * inc - m;
-  idx = cell (nd, 1);
-  for i = 2:nd
-    idx{i} = 1:sz(i);
-  endfor
+
+  idx = repmat ({':'}, nd, 1);
   idx{1} = 1:k;
   z = cat (1, y(idx{:}), zeros (sz));
   idx{1} = k+1:m;
--- a/scripts/general/interpn.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/general/interpn.m	Tue Sep 20 15:38:24 2011 -0400
@@ -129,7 +129,7 @@
     error ("interpn: wrong number or incorrectly formatted input arguments");
   endif
 
-  if (any (! cellfun (@isvector, x)))
+  if (any (! cellfun ("isvector", x)))
     for i = 2 : nd
       if (! size_equal (x{1}, x{i}) || ! size_equal (x{i}, v))
         error ("interpn: dimensional mismatch");
@@ -145,8 +145,8 @@
 
   method = tolower (method);
 
-  all_vectors = all (cellfun (@isvector, y));
-  different_lengths = numel (unique (cellfun (@numel, y))) > 1;
+  all_vectors = all (cellfun ("isvector", y));
+  different_lengths = numel (unique (cellfun ("numel", y))) > 1;
   if (all_vectors && different_lengths)
     [foobar(1:numel(y)).y] = ndgrid (y{:});
     y = {foobar.y};
@@ -174,7 +174,7 @@
     vi(idx) = extrapval;
     vi = reshape (vi, yshape);
   elseif (strcmp (method, "spline"))
-    if (any (! cellfun (@isvector, y)))
+    if (any (! cellfun ("isvector", y)))
       for i = 2 : nd
         if (! size_equal (y{1}, y{i}))
           error ("interpn: dimensional mismatch");
--- a/scripts/general/isa.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/general/isa.m	Tue Sep 20 15:38:24 2011 -0400
@@ -75,3 +75,22 @@
 %!assert (isa (uint16 (13), "numeric"), true)
 %!assert (isa (uint32 (13), "numeric"), true)
 %!assert (isa (uint64 (13), "numeric"), true)
+
+%!assert (isa (double (13), "double"));
+%!assert (isa (single (13), "single"));
+%!assert (isa (int8 (13), "int8"));
+%!assert (isa (int16 (13), "int16"));
+%!assert (isa (int32 (13), "int32"));
+%!assert (isa (int64 (13), "int64"));
+%!assert (isa (uint8 (13), "uint8"));
+%!assert (isa (uint16 (13), "uint16"));
+%!assert (isa (uint32 (13), "uint32"));
+%!assert (isa (uint64 (13), "uint64"));
+%!assert (isa ("string", "char"));
+%!assert (isa (true, "logical"));
+%!assert (isa (false, "logical"));
+%!assert (isa ({1, 2}, "cell"));
+%!test
+%! a.b = 1;
+%! assert (isa (a, "struct"));
+
--- a/scripts/general/iscolumn.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/general/iscolumn.m	Tue Sep 20 15:38:24 2011 -0400
@@ -26,8 +26,6 @@
 
 function retval = iscolumn (x)
 
-  retval = false;
-
   if (nargin != 1)
     print_usage ();
   endif
--- a/scripts/general/isdir.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/general/isdir.m	Tue Sep 20 15:38:24 2011 -0400
@@ -23,10 +23,17 @@
 ## @end deftypefn
 
 function retval = isdir (f)
-  if (nargin == 1)
-    ## Exist returns an integer but isdir should return a logical.
-    retval = (exist (f, "dir") == 7);
-  else
+  if (nargin != 1)
     print_usage ("isdir");
   endif
+
+  ## Exist returns an integer but isdir should return a logical.
+  retval = (exist (f, "dir") == 7);
+
 endfunction
+
+%!error isdir ();
+%!error isdir (1, 2);
+
+%!assert (isdir (pwd ()));
+%!assert (! isdir ("this is highly unlikely to be a directory name"));
--- a/scripts/general/isequal.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/general/isequal.m	Tue Sep 20 15:38:24 2011 -0400
@@ -24,12 +24,12 @@
 
 function retval = isequal (x1, varargin)
 
-  if (nargin > 1)
-    retval = __isequal__ (false, x1, varargin{:});
-  else
+  if (nargin < 2)
     print_usage ();
   endif
 
+  retval = __isequal__ (false, x1, varargin{:});
+
 endfunction
 
 ## test size and shape
--- a/scripts/general/isequalwithequalnans.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/general/isequalwithequalnans.m	Tue Sep 20 15:38:24 2011 -0400
@@ -25,12 +25,12 @@
 
 function retval = isequalwithequalnans (x1, varargin)
 
-  if (nargin > 1)
-    retval = __isequal__ (true, x1, varargin{:});
-  else
+  if (nargin < 2)
     print_usage ();
   endif
 
+  retval = __isequal__ (true, x1, varargin{:});
+
 endfunction
 
 ## test for equality
--- a/scripts/general/isrow.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/general/isrow.m	Tue Sep 20 15:38:24 2011 -0400
@@ -26,8 +26,6 @@
 
 function retval = isrow (x)
 
-  retval = false;
-
   if (nargin != 1)
     print_usage ();
   endif
--- a/scripts/general/isscalar.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/general/isscalar.m	Tue Sep 20 15:38:24 2011 -0400
@@ -26,12 +26,12 @@
 
 function retval = isscalar (x)
 
-  if (nargin == 1)
-    retval = numel (x) == 1;
-  else
+  if (nargin != 1)
     print_usage ();
   endif
 
+  retval = numel (x) == 1;
+
 endfunction
 
 %!assert(isscalar (1));
--- a/scripts/general/issquare.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/general/issquare.m	Tue Sep 20 15:38:24 2011 -0400
@@ -28,42 +28,35 @@
 
 function retval = issquare (x)
 
-  if (nargin == 1)
-    if (ndims (x) == 2)
-      [r, c] = size (x);
-      retval = r == c;
-    else
-      retval = false;
-    endif
+  if (nargin != 1)
+    print_usage ();
+  endif
+
+  if (ndims (x) == 2)
+    [r, c] = size (x);
+    retval = r == c;
   else
-    print_usage ();
+    retval = false;
   endif
 
 endfunction
 
+%!assert(issquare ([]));
 %!assert(issquare (1));
-
 %!assert(!(issquare ([1, 2])));
-
-%!assert(issquare ([]));
-
 %!assert(issquare ([1, 2; 3, 4]));
-
-%!test
-%! assert(issquare ("t"));
-
+%!assert(!(issquare ([1, 2; 3, 4; 5, 6])));
+%!assert(!(issquare (ones (3,3,3))));
+%!assert(issquare ("t"));
 %!assert(!(issquare ("test")));
-
-%!test
-%! assert(issquare (["test"; "ing"; "1"; "2"]));
-
+%!assert(issquare (["test"; "ing"; "1"; "2"]));
 %!test
 %! s.a = 1;
 %! assert(issquare (s));
-
-%!assert(!(issquare ([1, 2; 3, 4; 5, 6])));
+%!assert(issquare ({1, 2; 3, 4}));
+%!assert(sparse (([1, 2; 3, 4])));
 
+%% Test input validation
 %!error issquare ();
-
 %!error issquare ([1, 2; 3, 4], 2);
 
--- a/scripts/general/isvector.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/general/isvector.m	Tue Sep 20 15:38:24 2011 -0400
@@ -28,15 +28,13 @@
 
 function retval = isvector (x)
 
-  retval = 0;
-
-  if (nargin == 1)
-    sz = size (x);
-    retval = (ndims (x) == 2 && (sz(1) == 1 || sz(2) == 1));
-  else
+  if (nargin != 1)
     print_usage ();
   endif
 
+  sz = size (x);
+  retval = (ndims (x) == 2 && (sz(1) == 1 || sz(2) == 1));
+
 endfunction
 
 %!assert(isvector (1));
--- a/scripts/general/module.mk	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/general/module.mk	Tue Sep 20 15:38:24 2011 -0400
@@ -61,6 +61,8 @@
   general/polyarea.m \
   general/postpad.m \
   general/prepad.m \
+  general/profile.m \
+  general/profshow.m \
   general/quadgk.m \
   general/quadl.m \
   general/quadv.m \
--- a/scripts/general/nargchk.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/general/nargchk.m	Tue Sep 20 15:38:24 2011 -0400
@@ -30,16 +30,14 @@
 
 ## Author: Bill Denney <bill@denney.ws>
 
-function msg = nargchk (minargs, maxargs, nargs, outtype)
+function msg = nargchk (minargs, maxargs, nargs, outtype = "string")
 
   if (nargin < 3 || nargin > 4)
     print_usage ();
   elseif (minargs > maxargs)
     error ("nargchk: MINARGS must be <= MAXARGS");
-  elseif (nargin == 3)
-    outtype = "string";
   elseif (! any (strcmpi (outtype, {"string", "struct"})))
-    error ("nargchk: output type must be either string or struct");
+    error ('nargchk: output type must be either "string" or "struct"');
   elseif (! (isscalar (minargs) && isscalar (maxargs) && isscalar (nargs)))
     error ("nargchk: MINARGS, MAXARGS, and NARGS must be scalars");
   endif
@@ -56,13 +54,16 @@
   if (strcmpi (outtype, "string"))
     msg = msg.message;
   elseif (isempty (msg.message))
-    msg = struct ([]);
+    ## Compatability: Matlab returns a 0x1 empty struct when nargchk passes
+    msg = resize (msg, 0, 1);
   endif
 
 endfunction
 
+
 ## Tests
-%!shared stmin, stmax
+%!shared stnul, stmin, stmax
+%!  stnul = resize (struct ("message", "", "identifier", ""), 0, 1);
 %!  stmin = struct ("message", "not enough input arguments",
 %!                  "identifier", "Octave:nargchk:not-enough-inputs");
 %!  stmax = struct ("message", "too many input arguments",
@@ -73,7 +74,7 @@
 %!assert (nargchk (0, 1, 2), "too many input arguments")
 %!assert (nargchk (0, 1, 2, "string"), "too many input arguments")
 ## Struct outputs
-%!assert (nargchk (0, 1, 0, "struct"), struct([]))
-%!assert (nargchk (0, 1, 1, "struct"), struct([]))
+%!assert (isequal (nargchk (0, 1, 0, "struct"), stnul))
+%!assert (isequal (nargchk (0, 1, 1, "struct"), stnul))
 %!assert (nargchk (1, 1, 0, "struct"), stmin)
 %!assert (nargchk (0, 1, 2, "struct"), stmax)
--- a/scripts/general/nargoutchk.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/general/nargoutchk.m	Tue Sep 20 15:38:24 2011 -0400
@@ -55,19 +55,17 @@
 
   if (strcmpi (outtype, "string"))
     msg = msg.message;
-  else
-    if (isempty (msg.message))
-      msg = struct ([]);
-    endif
-    ## FIXME: remove the error below if error is modified to accept
-    ## struct inputs
-    error ("nargoutchk: error does not yet support struct inputs");
+  elseif (isempty (msg.message))
+    ## Compatability: Matlab returns a 0x1 empty struct when nargchk passes
+    msg = resize (msg, 0, 1);
   endif
 
 endfunction
 
+
 ## Tests
-%!shared stmin, stmax
+%!shared stnul, stmin, stmax
+%!  stnul = resize (struct ("message", "", "identifier", ""), 0, 1);
 %!  stmin = struct ("message", "not enough output arguments",
 %!                  "identifier", "Octave:nargoutchk:not-enough-outputs");
 %!  stmax = struct ("message", "too many output arguments",
@@ -78,7 +76,8 @@
 %!assert (nargoutchk (0, 1, 2), "too many output arguments")
 %!assert (nargoutchk (0, 1, 2, "string"), "too many output arguments")
 ## Struct outputs
-#%!assert (nargoutchk (0, 1, 0, "struct"), struct([]))
-#%!assert (nargoutchk (0, 1, 1, "struct"), struct([]))
-#%!assert (nargoutchk (1, 1, 0, "struct"), stmin)
-#%!assert (nargoutchk (0, 1, 2, "struct"), stmax)
+%!assert (isequal (nargoutchk (0, 1, 0, "struct"), stnul))
+%!assert (isequal (nargoutchk (0, 1, 1, "struct"), stnul))
+%!assert (nargoutchk (1, 1, 0, "struct"), stmin)
+%!assert (nargoutchk (0, 1, 2, "struct"), stmax)
+
--- a/scripts/general/nextpow2.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/general/nextpow2.m	Tue Sep 20 15:38:24 2011 -0400
@@ -55,3 +55,14 @@
   endif
 
 endfunction
+
+%!error nexpow2 ();
+%!error nexpow2 (1, 2);
+
+%!assert (nextpow2 (16), 4);
+%!assert (nextpow2 (17), 5);
+%!assert (nextpow2 (31), 5);
+%!assert (nextpow2 (-16), 4);
+%!assert (nextpow2 (-17), 5);
+%!assert (nextpow2 (-31), 5);
+%!assert (nextpow2 (1:17), 5);
--- a/scripts/general/num2str.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/general/num2str.m	Tue Sep 20 15:38:24 2011 -0400
@@ -111,10 +111,7 @@
     nd = ndims (x);
     perm = fix ([1:0.5:nc+0.5]);
     perm(2:2:2*nc) = perm(2:2:2*nc) + nc;
-    idx = cell ();
-    for i = 1:nd
-      idx{i} = 1:sz(i);
-    endfor
+    idx = repmat ({':'}, nd, 1);
     idx{2} = perm;
     x = horzcat (real (x), imag (x));
     x = x(idx{:});
--- a/scripts/general/postpad.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/general/postpad.m	Tue Sep 20 15:38:24 2011 -0400
@@ -53,11 +53,8 @@
   nd = ndims (x);
   sz = size (x);
   if (nargin < 4)
-    ## Find the first non-singleton dimension
-    dim = find (sz > 1, 1);
-    if (isempty (dim))
-      dim = 1;
-    endif
+    ## Find the first non-singleton dimension.
+    (dim = find (sz > 1, 1)) || (dim = 1);
   else
     if (!(isscalar (dim) && dim == fix (dim))
         || !(1 <= dim && dim <= nd))
@@ -76,10 +73,7 @@
   d = sz (dim);
 
   if (d >= l)
-    idx = cell ();
-    for i = 1:nd
-      idx{i} = 1:sz(i);
-    endfor
+    idx = repmat ({':'}, nd, 1);
     idx{dim} = 1:l;
     y = x(idx{:});
   else
@@ -88,3 +82,16 @@
   endif
 
 endfunction
+
+%!error postpad ();
+%!error postpad (1);
+%!error postpad (1,2,3,4,5);
+%!error postpad ([1,2], 2, 2,3);
+
+%!assert (postpad ([1,2], 4), [1,2,0,0]);
+%!assert (postpad ([1;2], 4), [1;2;0;0]);
+
+%!assert (postpad ([1,2], 4, 2), [1,2,2,2]);
+%!assert (postpad ([1;2], 4, 2), [1;2;2;2]);
+
+%!assert (postpad ([1,2], 2, 2, 1), [1,2;2,2]);
--- a/scripts/general/prepad.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/general/prepad.m	Tue Sep 20 15:38:24 2011 -0400
@@ -53,11 +53,8 @@
   nd = ndims (x);
   sz = size (x);
   if (nargin < 4)
-    ## Find the first non-singleton dimension
-    dim = find (sz > 1, 1);
-    if (isempty (dim))
-      dim = 1;
-    endif
+    ## Find the first non-singleton dimension.
+    (dim = find (sz > 1, 1)) || (dim = 1);
   else
     if (!(isscalar (dim) && dim == fix (dim))
         || !(1 <= dim && dim <= nd))
@@ -76,10 +73,7 @@
   d = sz (dim);
 
   if (d >= l)
-    idx = cell ();
-    for i = 1:nd
-      idx{i} = 1:sz(i);
-    endfor
+    idx = repmat ({':'}, nd, 1);
     idx{dim} = d-l+1:d;
     y = x(idx{:});
   else
@@ -88,3 +82,18 @@
   endif
 
 endfunction
+
+%!error prepad ();
+%!error prepad (1);
+%!error prepad (1,2,3,4,5);
+%!error prepad ([1,2], 2, 2,3);
+
+%!assert (prepad ([1,2], 4), [0,0,1,2]);
+%!assert (prepad ([1;2], 4), [0;0;1;2]);
+
+%!assert (prepad ([1,2], 4, 2), [2,2,1,2]);
+%!assert (prepad ([1;2], 4, 2), [2;2;1;2]);
+
+%!assert (prepad ([1,2], 2, 2, 1), [2,2;1,2]);
+
+## FIXME -- we need tests for multidimensional arrays.
--- a/scripts/general/private/__isequal__.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/general/private/__isequal__.m	Tue Sep 20 15:38:24 2011 -0400
@@ -59,16 +59,16 @@
   ## All arguments must either be of the same class or they must be
   ## numeric values.
   t = (all (strcmp (class(x),
-                    cellfun (@class, varargin, "uniformoutput", false)))
+                    cellfun ("class", varargin, "uniformoutput", false)))
        || ((isnumeric (x) || islogical (x))
-           && all (cellfun (@isnumeric, varargin)
-                   | cellfun (@islogical, varargin))));
+           && all (cellfun ("isnumeric", varargin)
+                   | cellfun ("islogical", varargin))));
 
   if (t)
     ## Test that everything has the same number of dimensions.
     s_x = size (x);
     s_v = cellfun (@size, varargin, "uniformoutput", false);
-    t = all (length (s_x) == cellfun (@length, s_v));
+    t = all (length (s_x) == cellfun ("length", s_v));
   endif
 
   if (t)
@@ -96,8 +96,8 @@
       ## Test the number of fields.
       fn_x = fieldnames (x);
       l_fn_x = length (fn_x);
-      fn_v = cellfun (@fieldnames, varargin, "uniformoutput", false);
-      t = all (l_fn_x == cellfun (@length, fn_v));
+      fn_v = cellfun ("fieldnames", varargin, "uniformoutput", false);
+      t = all (l_fn_x == cellfun ("length", fn_v));
 
       ## Test that all the names are equal.
       idx = 0;
@@ -146,7 +146,7 @@
     elseif (isa (x, "function_handle"))
 
       ## The == operator is overloaded for handles.
-      t = all (cellfun (@eq, {x}, varargin));
+      t = all (cellfun ("eq", {x}, varargin));
 
     else
       ## Check the numeric types.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/general/profile.m	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,150 @@
+## Copyright (C) 2011 Daniel Kraft
+##
+## 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 3 of the License, 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, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {Function File} {} profile on
+## @deftypefnx {Function File} {} profile off
+## @deftypefnx {Function File} {} profile resume
+## @deftypefnx {Function File} {} profile clear
+## @deftypefnx {Function File} {@var{S} =} profile ('status')
+## @deftypefnx {Function File} {@var{T} =} profile ('info')
+## Control the built-in profiler.
+##
+## @table @code
+## @item profile on
+## Start the profiler, clearing all previously collected data if there
+## is any.
+##
+## @item profile off
+## Stop profiling.  The collected data can later be retrieved and examined
+## with calls like @code{S = profile ('info')}.
+##
+## @item profile clear
+## Clear all collected profiler data.
+##
+## @item profile resume
+## Restart profiling without cleaning up the old data and instead
+## all newly collected statistics are added to the already existing ones.
+##
+## @item @var{S} = profile ('status')
+## Return a structure filled with certain information about the current status
+## of the profiler.  At the moment, the only field is @code{ProfilerStatus}
+## which is either 'on' or 'off'.
+##
+## @item @var{T} = profile ('info')
+## Return the collected profiling statistics in the structure @var{T}.
+## The flat profile is returned in the field @code{FunctionTable} which is an
+## array of structures, each entry corresponding to a function which was called
+## and for which profiling statistics are present.  Furthermore, the field
+## @code{Hierarchical} contains the hierarchical call-tree.  Each node
+## has an index into the @code{FunctionTable} identifying the function it
+## corresponds to as well as data fields for number of calls and time spent
+## at this level in the call-tree.
+## @end table
+## @end deftypefn
+
+## Built-in profiler.
+## Author: Daniel Kraft <d@domob.eu>
+
+function retval = profile (option)
+
+  if (nargin != 1)
+    print_usage ();
+  endif
+
+  switch (option)
+    case 'on'
+      __profiler_reset__ ();
+      __profiler_enable__ (true);
+
+    case 'off'
+      __profiler_enable__ (false);
+
+    case 'clear'
+      __profiler_reset__ ();
+
+    case 'resume'
+      __profiler_enable__ (true);
+
+    case 'status'
+      enabled = __profiler_enable__ ();
+      if (enabled)
+        enabled = 'on';
+      else
+        enabled = 'off';
+      endif
+      retval = struct ('ProfilerStatus', enabled);
+
+    case 'info'
+      [flat, tree] = __profiler_data__ ();
+      retval = struct ('FunctionTable', flat, 'Hierarchical', tree);
+
+    otherwise
+      warning ("profile: Unrecognized option '%s'", option);
+      print_usage ();
+
+  endswitch
+
+endfunction
+
+
+%!demo
+%! profile ('on');
+%! A = rand (100);
+%! B = expm (A);
+%! profile ('off');
+%! profile ('resume');
+%! C = sqrtm (A);
+%! profile ('off');
+%! T = profile ('info');
+%! profshow (T);
+
+%!error profile ();
+%!error profile ('on', 2);
+
+%!test
+%! on_struct.ProfilerStatus = "on";
+%! off_struct.ProfilerStatus = "off";
+%! profile ('on');
+%! result = logm (rand (200) + 10 * eye (200));
+%! assert (profile ('status'), on_struct);
+%! profile ('off');
+%! assert (profile ('status'), off_struct);
+%! profile ('resume');
+%! result = logm (rand (200) + 10 * eye (200));
+%! profile ('off');
+%! assert (profile ('status'), off_struct);
+%! info = profile ('info');
+%! assert (isstruct (info));
+%! assert (size (info), [1, 1]);
+%! assert (fieldnames (info), {'FunctionTable'; 'Hierarchical'});
+%! ftbl = info.FunctionTable;
+%! assert (fieldnames (ftbl), {'FunctionName'; 'TotalTime'; 'NumCalls'; 'IsRecursive'; 'Parents'; 'Children'});
+%! hier = info.Hierarchical;
+%! assert (fieldnames (hier), {'Index'; 'SelfTime'; 'NumCalls'; 'Children'});
+%! profile ('clear');
+%! info = profile ('info');
+%! assert (isstruct (info));
+%! assert (size (info), [1, 1]);
+%! assert (fieldnames (info), {'FunctionTable'; 'Hierarchical'});
+%! ftbl = info.FunctionTable;
+%! assert (size (ftbl), [0, 1]);
+%! assert (fieldnames (ftbl), {'FunctionName'; 'TotalTime'; 'NumCalls'; 'IsRecursive'; 'Parents'; 'Children'});
+%! hier = info.Hierarchical;
+%! assert (size (hier), [0, 1]);
+%! assert (fieldnames (hier), {'Index'; 'SelfTime'; 'NumCalls'; 'Children'});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/general/profshow.m	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,106 @@
+## Copyright (C) 2011 Daniel Kraft
+##
+## 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 3 of the License, 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, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {Function File} {} profshow (@var{data})
+## @deftypefnx {Function File} {} profshow (@var{data}, @var{n})
+## Show flat profiler results.
+##
+## This command prints out profiler data as a flat profile.  @var{data} is the
+## structure returned by @code{profile ('info')}.  If @var{n} is given, it
+## specifies the number of functions to show in the profile; functions are
+## sorted in descending order by total time spent in them.  If there are more
+## than @var{n} included in the profile, those will not be shown.  @var{n}
+## defaults to 20.
+##
+## The attribute column shows @samp{R} for recursive functions and nothing
+## otherwise.
+## @end deftypefn
+
+## Built-in profiler.
+## Author: Daniel Kraft <d@domob.eu>
+
+function profshow (data, n = 20)
+
+  if (nargin < 1 || nargin > 2)
+    print_usage ();
+  endif
+
+  n = fix (n);
+  if (! isscalar (n) || ! isreal (n) || ! (n > 0))
+    error ("profile: N must be a positive integer");
+  endif
+
+  m = length (data.FunctionTable);
+  n = min (n, m);
+
+  ## We want to sort by times in descending order.  For this, extract the
+  ## times to an array, then sort this, and use the resulting index permutation
+  ## to print out our table.
+  times = -[ data.FunctionTable.TotalTime ];
+
+  [~, p] = sort (times);
+
+  ## For printing the table, find out the maximum length of a function name
+  ## so that we can proportion the table accordingly.  Based on this,
+  ## we can build the format used for printing table rows.
+  nameLen = length ("Function");
+  for i = 1 : n
+    nameLen = max (nameLen, length (data.FunctionTable(p(i)).FunctionName));
+  endfor
+  headerFormat = sprintf ("%%4s %%%ds %%4s %%12s %%12s\n", nameLen);
+  rowFormat = sprintf ("%%4d %%%ds %%4s %%12.3f %%12d\n", nameLen);
+
+  printf (headerFormat, "#", "Function", "Attr", "Time (s)", "Calls");
+  printf ("%s\n", repmat ("-", 1, nameLen + 2 * 5 + 2 * 13));
+  for i = 1 : n
+    row = data.FunctionTable(p(i));
+    attr = "";
+    if (row.IsRecursive)
+      attr = "R";
+    endif
+    printf (rowFormat, p(i), row.FunctionName, attr, ...
+            row.TotalTime, row.NumCalls);
+  endfor
+
+endfunction
+
+%!demo
+%! profile ("on");
+%! A = rand (100);
+%! B = expm (A);
+%! profile ("off");
+%! T = profile ("info");
+%! profshow (T, 10);
+
+%!demo
+%! function f = myfib (n)
+%!   if (n <= 2)
+%!     f = 1;
+%!   else
+%!     f = myfib (n - 1) + myfib (n - 2);
+%!   endif
+%! endfunction
+%! profile ("on");
+%! myfib (20);
+%! profile ("off");
+%! profshow (profile ("info"), 5);
+
+%!error profshow ();
+%!error profshow (1, 2, 3);
+%!error profshow (struct (), 1.2);
--- a/scripts/general/quadl.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/general/quadl.m	Tue Sep 20 15:38:24 2011 -0400
@@ -62,14 +62,12 @@
 ##   * replace global variable terminate2 with local function need_warning
 ##   * add paper ref to docs
 
-function q = quadl (f, a, b, tol, trace, varargin)
-  need_warning (1);
-  if (nargin < 4)
-    tol = [];
+function q = quadl (f, a, b, tol = [], trace = false, varargin)
+
+  if (nargin < 3)
+    print_usage ();
   endif
-  if (nargin < 5)
-    trace = [];
-  endif
+
   if (isa (a, "single") || isa (b, "single"))
     myeps = eps ("single");
   else
@@ -79,16 +77,23 @@
     tol = myeps;
   endif
   if (isempty (trace))
-    trace = 0;
+    trace = false;
   endif
   if (tol < myeps)
     tol = myeps;
   endif
 
+  ## Track whether recursion has occurred
+  global __quadl_recurse_done__;
+  __quadl_recurse_done__ = false;
+  ## Track whether warning about machine precision has been issued
+  global __quadl_need_warning__;
+  __quadl_need_warning__ = true;
+
   m = (a+b)/2;
   h = (b-a)/2;
-  alpha = sqrt(2/3);
-  beta = 1/sqrt(5);
+  alpha = sqrt (2/3);
+  beta = 1/sqrt (5);
 
   x1 = .942882415695480;
   x2 = .641853342345781;
@@ -104,12 +109,12 @@
 
   i2 = (h/6)*(y(1) + y(13) + 5*(y(5)+y(9)));
 
-  i1 = (h/1470)*(77*(y(1)+y(13))
+  i1 = (h/1470)*(   77*(y(1)+y(13))
                  + 432*(y(3)+y(11))
                  + 625*(y(5)+y(9))
                  + 672*y(7));
 
-  is = h*(.0158271919734802*(y(1)+y(13))
+  is = h*( .0158271919734802*(y(1)+y(13))
           +.0942738402188500*(y(2)+y(12))
           + .155071987336585*(y(3)+y(11))
           + .188821573960182*(y(4)+y(10))
@@ -117,80 +122,96 @@
           + .224926465333340*(y(6)+y(8))
           + .242611071901408*y(7));
 
-  s = sign(is);
-
+  s = sign (is);
   if (s == 0)
     s = 1;
   endif
-  erri1 = abs(i1-is);
-  erri2 = abs(i2-is);
-  R = 1;
+  erri1 = abs (i1-is);
+  erri2 = abs (i2-is);
   if (erri2 != 0)
     R = erri1/erri2;
+  else
+    R = 1;
   endif
   if (R > 0 && R < 1)
     tol = tol/R;
   endif
-  is = s*abs(is)*tol/myeps;
+  is = s * abs(is) * tol/myeps;
   if (is == 0)
     is = b-a;
   endif
+
   q = adaptlobstp (f, a, b, fa, fb, is, trace, varargin{:});
+
 endfunction
 
 ## ADAPTLOBSTP  Recursive function used by QUADL.
 ##
 ##   Q = ADAPTLOBSTP('F', A, B, FA, FB, IS, TRACE) tries to
 ##   approximate the integral of F(X) from A to B to
-##   an appropriate relative error. The argument 'F' is
+##   an appropriate relative error.  The argument 'F' is
 ##   a string containing the name of f.  The remaining
 ##   arguments are generated by ADAPTLOB or by recursion.
 ##
 ##   Walter Gautschi, 08/03/98
 
 function q = adaptlobstp (f, a, b, fa, fb, is, trace, varargin)
+  global __quadl_recurse_done__;
+  global __quadl_need_warning__;
+
   h = (b-a)/2;
   m = (a+b)/2;
-  alpha = sqrt(2/3);
-  beta = 1/sqrt(5);
+  alpha = sqrt (2/3);
+  beta = 1 / sqrt(5);
   mll = m-alpha*h;
-  ml = m-beta*h;
-  mr = m+beta*h;
+  ml  = m-beta*h;
+  mr  = m+beta*h;
   mrr = m+alpha*h;
   x = [mll, ml, m, mr, mrr];
-  y = feval(f, x, varargin{:});
+  y = feval (f, x, varargin{:});
   fmll = y(1);
-  fml = y(2);
-  fm = y(3);
-  fmr = y(4);
+  fml  = y(2);
+  fm   = y(3);
+  fmr  = y(4);
   fmrr = y(5);
   i2 = (h/6)*(fa + fb + 5*(fml+fmr));
   i1 = (h/1470)*(77*(fa+fb) + 432*(fmll+fmrr) + 625*(fml+fmr) + 672*fm);
-  if (is+(i1-i2) == is || mll <= a || b <= mrr)
-    if ((m <= a || b <= m) && need_warning ())
+  if ((is+(i1-i2) == is || mll <= a || b <= mrr) && __quadl_recurse_done__)
+    if ((m <= a || b <= m) && __quadl_need_warning__)
       warning ("quadl: interval contains no more machine number");
       warning ("quadl: required tolerance may not be met");
-      need_warning (0);
+      __quadl_need_warning__ = false;
     endif
     q = i1;
     if (trace)
       disp ([a, b-a, q]);
     endif
   else
-    q = (adaptlobstp (f, a, mll, fa, fmll, is, trace, varargin{:})
-         + adaptlobstp (f, mll, ml, fmll, fml, is, trace, varargin{:})
-         + adaptlobstp (f, ml, m, fml, fm, is, trace, varargin{:})
-         + adaptlobstp (f, m, mr, fm, fmr, is, trace, varargin{:})
-         + adaptlobstp (f, mr, mrr, fmr, fmrr, is, trace, varargin{:})
-         + adaptlobstp (f, mrr, b, fmrr, fb, is, trace, varargin{:}));
+    __quadl_recurse_done__ = true;
+    q = (  adaptlobstp (f, a  , mll, fa  , fmll, is, trace, varargin{:})
+         + adaptlobstp (f, mll, ml , fmll, fml , is, trace, varargin{:})
+         + adaptlobstp (f, ml , m  , fml , fm  , is, trace, varargin{:})
+         + adaptlobstp (f, m  , mr , fm  , fmr , is, trace, varargin{:})
+         + adaptlobstp (f, mr , mrr, fmr , fmrr, is, trace, varargin{:})
+         + adaptlobstp (f, mrr, b  , fmrr, fb  , is, trace, varargin{:}));
   endif
 endfunction
 
-function r = need_warning (v)
-  persistent w = [];
-  if (nargin == 0)
-    r = w;
-  else
-    w = v;
-  endif
-endfunction
+
+## basic functionality
+%!assert (quadl (@(x) sin (x), 0, pi, [], []), 2, -3e-16)
+
+## the values here are very high so it may be unavoidable that this fails
+%!assert (quadl (@(x) sin (3*x).*cosh (x).*sinh (x),10,15),
+%!         2.588424538641647e+10, -9e-15)
+
+## extra parameters
+%!assert (quadl (@(x,a,b) sin (a + b*x), 0, 1, [], [], 2, 3),
+%!        cos(2)/3 - cos(5)/3, - 3e-16)
+
+## test different tolerances.
+%!assert (quadl (@(x) sin (2 + 3*x).^2, 0, 10, 0.3, []),
+%!        (60 + sin(4) - sin(64))/12, -0.3)
+%!assert (quadl (@(x) sin (2 + 3*x).^2, 0, 10, 0.1, []),
+%!        (60 + sin(4) - sin(64))/12, -0.1)
+
--- a/scripts/general/rat.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/general/rat.m	Tue Sep 20 15:38:24 2011 -0400
@@ -150,3 +150,11 @@
   endif
 
 endfunction
+
+%!error rat ();
+%!error rat (1, 2, 3);
+
+%!test
+%! [n, d] = rat ([0.5, 0.3, 1/3]);
+%! assert (n, [1, 3, 1]);
+%! assert (d, [2, 10, 3]);
--- a/scripts/general/rot90.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/general/rot90.m	Tue Sep 20 15:38:24 2011 -0400
@@ -52,44 +52,41 @@
 
 ## Author: jwe
 
-function B = rot90 (A, k)
-
-  if (nargin == 1 || nargin == 2)
-    if (nargin < 2)
-      k = 1;
-    endif
-
-    if (ndims (A) > 2)
-      error ("rot90: Only works with 2-D arrays");
-    endif
-
-    if (imag (k) != 0 || fix (k) != k)
-      error ("rot90: K must be an integer");
-    endif
-
-    k = rem (k, 4);
+function B = rot90 (A, k = 1)
 
-    if (k < 0)
-      k = k + 4;
-    endif
-
-    if (k == 0)
-      B = A;
-    elseif (k == 1)
-      B = flipud (A.');
-    elseif (k == 2)
-      B = flipud (fliplr (A));
-    elseif (k == 3)
-      B = (flipud (A)).';
-    else
-      error ("rot90: internal error!");
-    endif
-  else
+  if (nargin < 1 || nargin > 2)
     print_usage ();
   endif
 
+  if (ndims (A) > 2)
+    error ("rot90: A must be a 2-D array");
+  endif
+
+  if (! (isscalar (k) && isreal (k) && fix (k) == k))
+    error ("rot90: K must be a single real integer");
+  endif
+
+  k = rem (k, 4);
+
+  if (k < 0)
+    k = k + 4;
+  endif
+
+  if (k == 0)
+    B = A;
+  elseif (k == 1)
+    B = flipud (A.');
+  elseif (k == 2)
+    B = flipud (fliplr (A));
+  elseif (k == 3)
+    B = (flipud (A)).';
+  else
+    error ("rot90: internal error!");
+  endif
+
 endfunction
 
+
 %!test
 %! x1 = [1, 2; 3, 4];
 %! x2 = [2, 4; 1, 3];
@@ -106,4 +103,6 @@
 %% Test input validation
 %!error rot90 ();
 %!error rot90 (1, 2, 3);
-
+%!error rot90 (1, ones(2));
+%!error rot90 (1, 1.5);
+%!error rot90 (1, 1+i);
--- a/scripts/general/rotdim.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/general/rotdim.m	Tue Sep 20 15:38:24 2011 -0400
@@ -71,22 +71,26 @@
   nd = ndims (x);
   sz = size (x);
   if (nargin < 3)
-    ## Find the first two non-singleton dimension.
-    plane = [];
-    dim = 0;
-    while (dim < nd)
-      dim = dim + 1;
-      if (sz (dim) != 1)
-        plane = [plane, dim];
-        if (length (plane) == 2)
-          break;
+    if (nd > 2)
+      ## Find the first two non-singleton dimension.
+      plane = [];
+      dim = 0;
+      while (dim < nd)
+        dim = dim + 1;
+        if (sz (dim) != 1)
+          plane = [plane, dim];
+          if (length (plane) == 2)
+            break;
+          endif
         endif
+      endwhile
+      if (length (plane) < 1)
+        plane = [1, 2];
+      elseif (length (plane) < 2)
+        plane = [1, plane];
       endif
-    endwhile
-    if (length (plane) < 1)
+    else
       plane = [1, 2];
-    elseif (length (plane) < 2)
-      plane = [1, plane];
     endif
   else
     if (! (isvector (plane) && length (plane) == 2
@@ -119,3 +123,36 @@
   endif
 
 endfunction
+
+%!error rotdim ();
+%!error rotdim (1, 2, 3, 4);
+
+%!shared r, rr
+%! r = [1,2,3]; rr = [3,2,1];
+%!assert (rotdim (r, 0), r);
+%!assert (rotdim (r, 1), rr');
+%!assert (rotdim (r, 2), rr);
+%!assert (rotdim (r, 3), r');
+%!assert (rotdim (r, 3), rotdim (r, -1));
+%!assert (rotdim (r, 1), rotdim (r));
+
+%!shared c, cr
+%! c = [1;2;3]; cr = [3;2;1];
+%!assert (rotdim (c, 0), c);
+%!assert (rotdim (c, 1), c');
+%!assert (rotdim (c, 2), cr);
+%!assert (rotdim (c, 3), cr');
+%!assert (rotdim (c, 3), rotdim (c, -1));
+%!assert (rotdim (c, 1), rotdim (c));
+
+%!shared m
+%! m = [1,2;3,4];
+%!assert (rotdim (m, 0), m);
+%!assert (rotdim (m, 1), [2,4;1,3]);
+%!assert (rotdim (m, 2), [4,3;2,1]);
+%!assert (rotdim (m, 3), [3,1;4,2]);
+%!assert (rotdim (m, 3), rotdim (m, -1));
+%!assert (rotdim (m, 1), rotdim (m));
+
+## FIXME -- we need tests for multidimensional arrays and different
+## values of PLANE.
--- a/scripts/general/shift.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/general/shift.m	Tue Sep 20 15:38:24 2011 -0400
@@ -51,10 +51,7 @@
     endif
   else
     ## Find the first non-singleton dimension.
-    dim = find (sz > 1, 1);
-    if (isempty (dim))
-      dim = 1;
-    endif
+    (dim = find (sz > 1, 1)) || (dim = 1);
   endif
 
   if (numel (x) < 1)
@@ -63,10 +60,7 @@
 
   d = sz (dim);
 
-  idx = cell ();
-  for i = 1:nd
-    idx{i} = 1:sz(i);
-  endfor
+  idx = repmat ({':'}, nd, 1);
   if (b >= 0)
     b = rem (b, d);
     idx{dim} = [d-b+1:d, 1:d-b];
--- a/scripts/general/shiftdim.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/general/shiftdim.m	Tue Sep 20 15:38:24 2011 -0400
@@ -57,14 +57,9 @@
   orig_dims = size (x);
 
   if (nargin == 1)
-    ## Find the first singleton dimension.
-    n = 0;
-    while (n < nd && orig_dims(n+1) == 1)
-      n++;
-    endwhile
-  endif
-
-  if (! isscalar (n) || floor (n) != n)
+    ## Find the first non-singleton dimension.
+    (n = find (orig_dims != 1, 1) - 1) || (n = nd);
+  elseif (! (isscalar (n) && n == fix (n)))
     error ("shiftdim: N must be a scalar integer");
   endif
 
@@ -78,7 +73,7 @@
   elseif (n > 0)
     ## We need permute here instead of reshape to shift values in a
     ## compatible way.
-    y = permute (x, [n+1:ndims(x) 1:n]);
+    y = permute (x, [n+1:nd 1:n]);
   else
     y = x;
   endif
@@ -86,3 +81,20 @@
   ns = n;
 
 endfunction
+
+
+%!test
+%! x = rand (1, 1, 4, 2);
+%! [y, ns] = shiftdim (x);
+%! assert (size (y), [4 2]);
+%! assert (ns, 2);
+%! assert (shiftdim (y, -2), x);
+%! assert (size (shiftdim (x, 2)), [4 2]);
+%!assert (size (shiftdim (rand (0, 1, 2))), [0 1 2]);
+
+%% Test input validation
+%!error(shiftdim ());
+%!error(shiftdim (1,2,3));
+%!error(shiftdim (1, ones (2)));
+%!error(shiftdim (1, 1.5));
+
--- a/scripts/general/structfun.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/general/structfun.m	Tue Sep 20 15:38:24 2011 -0400
@@ -106,7 +106,7 @@
   [varargout{:}] = cellfun (func, struct2cell (S), varargin{:});
 
   if (! uniform_output)
-    varargout = cellfun (@cell2struct, varargout, {fieldnames(S)}, {1}, uo_str, false);
+    varargout = cellfun ("cell2struct", varargout, {fieldnames(S)}, {1}, uo_str, false);
   endif
 endfunction
 
--- a/scripts/general/triplequad.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/general/triplequad.m	Tue Sep 20 15:38:24 2011 -0400
@@ -37,22 +37,25 @@
 ##
 ## The optional argument @var{quadf} specifies which underlying integrator
 ## function to use.  Any choice but @code{quad} is available and the default
-## is @code{quadgk}.
+## is @code{quadcc}.
 ##
 ## Additional arguments, are passed directly to @var{f}.  To use the default
-## value for @var{tol} or @var{quadf} one may pass an empty matrix ([]).
+## value for @var{tol} or @var{quadf} one may pass ':' or an empty matrix ([]).
 ## @seealso{dblquad, quad, quadv, quadl, quadgk, quadcc, trapz}
 ## @end deftypefn
 
-function q = triplequad(f, xa, xb, ya, yb, za, zb, tol, quadf, varargin)
+function q = triplequad (f, xa, xb, ya, yb, za, zb, tol = 1e-6, quadf = @quadcc, varargin)
+
   if (nargin < 7)
     print_usage ();
   endif
-  if (nargin < 8 || isempty (tol))
+
+  ## Allow use of empty matrix ([]) to indicate default
+  if (isempty (tol))
     tol = 1e-6;
   endif
-  if (nargin < 9 || isempty (quadf))
-    quadf = @quadgk;
+  if (isempty (quadf))
+    quadf = @quadcc;
   endif
 
   inner = @__triplequad_inner__;
@@ -61,7 +64,8 @@
     varargin = {};
   endif
 
-  q = dblquad(@(y, z) inner (y, z, f, xa, xb, tol, quadf, varargin{:}),ya, yb, za, zb, tol);
+  q = dblquad (@(y, z) inner (y, z, f, xa, xb, tol, quadf, varargin{:}), ya, yb, za, zb, tol);
+
 endfunction
 
 function q = __triplequad_inner__ (y, z, f, xa, xb, tol, quadf, varargin)
@@ -71,8 +75,11 @@
   endfor
 endfunction
 
-%% These tests are too expensive to run normally. Disable them
-% !#assert (triplequad (@(x,y,z) exp(-x.^2 - y.^2 - z.^2) , -1, 1, -1, 1, -1, 1, [],  @quadgk), pi ^ (3/2) * erf(1).^3, 1e-6)
-% !#assert (triplequad (@(x,y,z) exp(-x.^2 - y.^2 - z.^2) , -1, 1, -1, 1, -1, 1, [],  @quadl), pi ^ (3/2) * erf(1).^3, 1e-6)
-% !#assert (triplequad (@(x,y,z) exp(-x.^2 - y.^2 - z.^2) , -1, 1, -1, 1, -1, 1, [],  @quadv), pi ^ (3/2) * erf(1).^3, 1e-6)
+
+%!assert (triplequad (@(x,y,z) exp(-x.^2 - y.^2 - z.^2) , -1, 1, -1, 1, -1, 1, [],  @quadcc), pi ^ (3/2) * erf(1).^3, 1e-6)
 
+%% These tests are too expensive to run normally (~30 sec each).  Disable them
+#%!assert (triplequad (@(x,y,z) exp(-x.^2 - y.^2 - z.^2) , -1, 1, -1, 1, -1, 1, [],  @quadgk), pi ^ (3/2) * erf(1).^3, 1e-6)
+#%!#assert (triplequad (@(x,y,z) exp(-x.^2 - y.^2 - z.^2) , -1, 1, -1, 1, -1, 1, [],  @quadl), pi ^ (3/2) * erf(1).^3, 1e-6)
+#%!#assert (triplequad (@(x,y,z) exp(-x.^2 - y.^2 - z.^2) , -1, 1, -1, 1, -1, 1, [],  @quadv), pi ^ (3/2) * erf(1).^3, 1e-6)
+
--- a/scripts/geometry/inpolygon.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/geometry/inpolygon.m	Tue Sep 20 15:38:24 2011 -0400
@@ -130,3 +130,14 @@
 %! disp("Green points are inside polygon, magenta are outside,");
 %! disp("and blue are on boundary.");
 
+%!error inpolygon ();
+%!error inpolygon (1, 2);
+%!error inpolygon (1, 2, 3);
+
+%!error inpolygon (1, [1,2], [3, 4], [5, 6]);
+%!error inpolygon ([1,2], [3, 4], [5, 6], 1);
+
+%!test
+%! [in, on] = inpolygon ([1, 0], [1, 0], [-1, -1, 1, 1], [-1, 1, 1, -1]);
+%! assert (in, [false, true]);
+%! assert (on, [true, false]);
--- a/scripts/geometry/module.mk	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/geometry/module.mk	Tue Sep 20 15:38:24 2011 -0400
@@ -12,9 +12,6 @@
   geometry/griddatan.m \
   geometry/inpolygon.m \
   geometry/rectint.m \
-  geometry/trimesh.m \
-  geometry/triplot.m \
-  geometry/trisurf.m \
   geometry/tsearchn.m \
   geometry/voronoi.m \
   geometry/voronoin.m
--- a/scripts/geometry/trimesh.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-## Copyright (C) 2007-2011 David Bateman
-##
-## 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn  {Function File} {} trimesh (@var{tri}, @var{x}, @var{y}, @var{z})
-## @deftypefnx {Function File} {@var{h} =} trimesh (@dots{})
-## Plot a triangular mesh in 3D@.  The variable @var{tri} is the triangular
-## meshing of the points @code{(@var{x}, @var{y})} which is returned
-## from @code{delaunay}.  The variable @var{z} is value at the point
-## @code{(@var{x}, @var{y})}.  The output argument @var{h} is the graphic
-## handle of the plot.
-## @seealso{triplot, trisurf, delaunay3}
-## @end deftypefn
-
-function h = trimesh (tri, x, y, z, varargin)
-
-  if (nargin < 3)
-    print_usage ();
-  endif
-
-  if (nargin == 3)
-    triplot (tri, x, y);
-  elseif (ischar (z))
-    triplot (tri, x, y, z, varargin{:});
-  else
-    newplot ();
-    if (nargout > 0)
-      h = patch ("Vertices", [x(:), y(:), z(:)], "Faces", tri,
-                 "FaceColor", "none", "EdgeColor", __next_line_color__(),
-                 varargin{:});
-    else
-      patch ("Vertices", [x(:), y(:), z(:)], "Faces", tri,
-             "FaceColor", "none", "EdgeColor", __next_line_color__(),
-             varargin{:});
-    endif
-
-    if (! ishold ())
-      set (gca(), "view", [-37.5, 30],
-           "xgrid", "on", "ygrid", "on", "zgrid", "on");
-    endif
-  endif
-endfunction
-
-%!demo
-%! N = 10;
-%! rand ('state', 10)
-%! x = 3 - 6 * rand (N, N);
-%! y = 3 - 6 * rand (N, N);
-%! z = peaks (x, y);
-%! tri = delaunay (x(:), y(:));
-%! trimesh (tri, x(:), y(:), z(:));
--- a/scripts/geometry/triplot.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-## Copyright (C) 2007-2011 David Bateman
-##
-## 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn  {Function File} {} triplot (@var{tri}, @var{x}, @var{y})
-## @deftypefnx {Function File} {} triplot (@var{tri}, @var{x}, @var{y}, @var{linespec})
-## @deftypefnx {Function File} {@var{h} =} triplot (@dots{})
-## Plot a triangular mesh in 2D@.  The variable @var{tri} is the triangular
-## meshing of the points @code{(@var{x}, @var{y})} which is returned from
-## @code{delaunay}.  If given, the @var{linespec} determines the properties
-## to use for the lines.  The output argument @var{h} is the graphic handle
-## of the plot.
-## @seealso{plot, trimesh, trisurf, delaunay}
-## @end deftypefn
-
-function h = triplot (tri, x, y, varargin)
-
-  if (nargin < 3)
-    print_usage ();
-  endif
-
-  idx = tri(:, [1, 2, 3, 1]).';
-  nt = size (tri, 1);
-  if (nargout > 0)
-    h = plot ([x(idx); NaN(1, nt)](:),
-              [y(idx); NaN(1, nt)](:), varargin{:});
-  else
-    plot ([x(idx); NaN(1, nt)](:),
-          [y(idx); NaN(1, nt)](:), varargin{:});
-  endif
-endfunction
-
-%!demo
-%! rand ('state', 2)
-%! x = rand (20, 1);
-%! y = rand (20, 1);
-%! tri = delaunay (x, y);
-%! triplot (tri, x, y);
--- a/scripts/geometry/trisurf.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,102 +0,0 @@
-## Copyright (C) 2007-2011 David Bateman
-##
-## 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn  {Function File} {} trisurf (@var{tri}, @var{x}, @var{y}, @var{z})
-## @deftypefnx {Function File} {@var{h} =} trisurf (@dots{})
-## Plot a triangular surface in 3D@.  The variable @var{tri} is the triangular
-## meshing of the points @code{(@var{x}, @var{y})} which is returned
-## from @code{delaunay}.  The variable @var{z} is value at the point
-## @code{(@var{x}, @var{y})}.  The output argument @var{h} is the graphic
-## handle of the plot.
-## @seealso{triplot, trimesh, delaunay3}
-## @end deftypefn
-
-function varargout = trisurf (tri, x, y, z, varargin)
-
-  if (nargin < 3)
-    print_usage ();
-  endif
-
-  if (nargin == 3)
-    triplot (tri, x, y);
-  elseif (ischar (z))
-    triplot (tri, x, y, z, varargin{:});
-  else
-    if (nargin > 4 && isnumeric (varargin{1}))
-      c = varargin{1};
-      varargin(1) = [];
-    else
-      c = z;
-    endif
-    if (! any (strcmpi (varargin, "FaceColor")))
-      nfc = numel (varargin) + 1;
-      varargin(nfc+(0:1)) = {"FaceColor", "flat"};
-    else
-      nfc = find (any (strcmpi (varargin, "FaceColor")), 1);
-    endif
-    if (! any (strcmpi (varargin, "EdgeColor"))
-        && strcmpi (varargin{nfc+1}, "interp"))
-      varargin(end+(1:2)) = {"EdgeColor", "none"};
-    endif
-    newplot ();
-    h = patch ("Faces", tri, "Vertices", [x(:), y(:), z(:)],
-               "FaceVertexCData", reshape (c, numel (c), 1),
-               varargin{:});
-    if (nargout > 0)
-      varargout = {h};
-    endif
-
-    if (! ishold ())
-      set (gca(), "view", [-37.5, 30],
-           "xgrid", "on", "ygrid", "on", "zgrid", "on");
-    endif
-  endif
-endfunction
-
-%!demo
-%! N = 10;
-%! rand ('state', 10)
-%! x = 3 - 6 * rand (N, N);
-%! y = 3 - 6 * rand (N, N);
-%! z = peaks (x, y);
-%! tri = delaunay (x(:), y(:));
-%! trisurf (tri, x(:), y(:), z(:));
-
-%!demo
-%! x = rand (100, 1);
-%! y = rand (100, 1);
-%! z = x.^2 + y.^2; 
-%! tri = delaunay (x, y); 
-%! trisurf (tri, x, y, z)
-
-%!demo
-%! x = rand (100, 1);
-%! y = rand (100, 1);
-%! z = x.^2 + y.^2; 
-%! tri = delaunay (x, y); 
-%! trisurf (tri, x, y, z, "facecolor", "interp")
-
-%!demo
-%! x = rand (100, 1);
-%! y = rand (100, 1);
-%! z = x.^2 + y.^2; 
-%! tri = delaunay (x, y); 
-%! trisurf (tri, x, y, z, "facecolor", "interp", "edgecolor", "k")
-
-
--- a/scripts/geometry/voronoi.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/geometry/voronoi.m	Tue Sep 20 15:38:24 2011 -0400
@@ -129,7 +129,7 @@
   idx = find (!infi);
   ll = length (idx);
   c = c(idx).';
-  k = sum (cellfun ('length', c));
+  k = sum (cellfun ("length", c));
   edges = cell2mat(cellfun (@(x) [x ; [x(end), x(1:end-1)]], c,
                             "uniformoutput", false));
 
@@ -166,3 +166,13 @@
   endif
 
 endfunction
+
+%!testif HAVE_QHULL
+%! phi=linspace(-pi,3/4*pi,8);
+%! [x,y]=pol2cart(phi,1);
+%! [vx,vy]=voronoi(x,y);
+%! assert(vx(2,:),zeros(1,size(vx,2)),eps);
+%! assert(vy(2,:),zeros(1,size(vy,2)),eps);
+
+%!demo
+%! voronoi (rand(10,1), rand(10,1));
--- a/scripts/help/__makeinfo__.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/help/__makeinfo__.m	Tue Sep 20 15:38:24 2011 -0400
@@ -57,87 +57,50 @@
 ## The optional output argument @var{status} contains the exit status of the
 ## @code{makeinfo} program as returned by @code{system}.
 
-function [retval, status] = __makeinfo__ (text, output_type = "plain text", see_also = [])
+function [retval, status] = __makeinfo__ (text, output_type = "plain text", fsee_also)
 
   ## Check input
-  if (nargin == 0)
+  if (nargin < 1 || nargin > 3)
     print_usage ();
   endif
 
-  if (!ischar (text))
+  if (! ischar (text))
     error ("__makeinfo__: first input argument must be a string");
   endif
 
-  if (!ischar (output_type))
+  if (! ischar (output_type))
     error ("__makeinfo__: second input argument must be a string");
   endif
 
-  ## Define the function which expands @seealso macro
-  if (isempty (see_also))
+  if (nargin < 3)
     if (strcmpi (output_type, "plain text"))
-      see_also = @simple_see_also;
+      fsee_also = @(T) strcat ...
+          ("\nSee also:", sprintf (" %s,", T{:})(1:end-1), "\n");
     else
-      see_also = @simple_see_also_with_refs;
+      fsee_also = @(T) strcat ...
+          ("\nSee also:", sprintf (" @ref{%s},", T{:})(1:end-1), "\n");
     endif
   endif
 
-  if (!isa (see_also, "function_handle"))
-    error ("__makeinfo__: third input argument must be the empty matrix, or a function handle");
+  if (! isa (fsee_also, "function_handle"))
+    error ("__makeinfo__: third input argument must be a function handle");
   endif
 
+
   ## It seems like makeinfo sometimes gets angry if the first character
   ## on a line is a space, so we remove these.
   text = strrep (text, "\n ", "\n");
 
   ## Handle @seealso macro
-  SEE_ALSO = "@seealso";
-  starts = strfind (text, SEE_ALSO);
-  for start = fliplr (starts)
-    if (start == 1 || (text (start-1) != "@"))
-      bracket_start = find (text (start:end) == "{", 1);
-      stop = find (text (start:end) == "}", 1);
-      if (!isempty (stop) && !isempty (bracket_start))
-        stop += start - 1;
-        bracket_start += start - 1;
-      else
-        bracket_start = start + length (SEE_ALSO);
-        stop = find (text (start:end) == "\n", 1);
-        if (isempty (stop))
-          stop = length (text);
-        else
-          stop += start - 1;
-        endif
-      endif
-      see_also_args = text (bracket_start+1:(stop-1));
-      see_also_args = strtrim (strsplit (see_also_args, ","));
-      expanded = see_also (see_also_args);
-      text = strcat (text (1:start-1), expanded, text (stop+1:end));
-    endif
+  see_also_pat = '@seealso *\{([^}]*)\}';
+  args = regexp (text, see_also_pat, 'tokens');
+  for ii = 1:numel (args)
+    expanded = fsee_also (strtrim (strsplit (args{ii}{:}, ',', true)));
+    text = regexprep (text, see_also_pat, expanded, 'once');
   endfor
 
   ## Handle @nospell macro
-  NOSPELL = "@nospell";
-  starts = strfind (text, NOSPELL);
-  for start = fliplr (starts)
-    if (start == 1 || (text (start-1) != "@"))
-      bracket_start = find (text (start:end) == "{", 1);
-      stop = find (text (start:end) == "}", 1);
-      if (!isempty (stop) && !isempty (bracket_start))
-        stop += start - 1;
-        bracket_start += start - 1;
-      else
-        bracket_start = start + length (NOSPELL);
-        stop = find (text (start:end) == "\n", 1);
-        if (isempty (stop))
-          stop = length (text);
-        else
-          stop += start - 1;
-        endif
-      endif
-      text(stop) = [];
-      text(start:bracket_start) = [];
-    endif
-  endfor
+  text = regexprep (text, '@nospell *\{([^}]*)\}', "$1");
 
   if (strcmpi (output_type, "texinfo"))
     status = 0;
@@ -151,7 +114,7 @@
   unwind_protect
     ## Write Texinfo to tmp file
     template = "octave-help-XXXXXX";
-    [fid, name, msg] = mkstemp (fullfile (P_tmpdir, template), true);
+    [fid, name] = mkstemp (fullfile (P_tmpdir, template), true);
     if (fid < 0)
       error ("__makeinfo__: could not create temporary file");
     endif
@@ -161,11 +124,11 @@
     ## Take action depending on output type
     switch (lower (output_type))
       case "plain text"
-         cmd = sprintf ("%s --no-headers --no-warn --force --no-validate %s",
-                        makeinfo_program (), name);
+        cmd = sprintf ("%s --no-headers --no-warn --force --no-validate %s",
+                       makeinfo_program (), name);
       case "html"
-         cmd = sprintf ("%s --no-headers --html --no-warn --no-validate --force %s",
-                        makeinfo_program (), name);
+        cmd = sprintf ("%s --no-headers --html --no-warn --no-validate --force %s",
+                       makeinfo_program (), name);
       otherwise
         error ("__makeinfo__: unsupported output type: '%s'", output_type);
     endswitch
@@ -180,12 +143,6 @@
   end_unwind_protect
 endfunction
 
-function expanded = simple_see_also (args)
-  expanded = strcat ("\nSee also:", sprintf (" %s,", args {:}));
-  expanded = strcat (expanded (1:end-1), "\n\n");
-endfunction
+## No test needed for internal helper function.
+%!assert (1)
 
-function expanded = simple_see_also_with_refs (args)
-  expanded = strcat ("\nSee also:", sprintf (" @ref{%s},", args {:}));
-  expanded = strcat (expanded (1:end-1), "\n\n");
-endfunction
--- a/scripts/help/__strip_html_tags__.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-## Copyright (C) 2009-2011 Søren Hauberg
-##
-## 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} {[@var{text}, @var{status}] =} __strip_html_tags__ (@var{html_text})
-## Undocumented internal function.
-## @end deftypefn
-
-## Remove HTML tags from text.  This is used as a simple HTML-to-text
-## function.
-
-function [text, status] = __strip_html_tags__ (html_text)
-  start = find (html_text == "<");
-  stop  = find (html_text == ">");
-  if (length (start) == length (stop))
-    text = html_text;
-    for n = length(start):-1:1
-      text (start (n):stop (n)) = [];
-    endfor
-    text = strip_superfluous_endlines (text);
-    status = 0;
-  else
-    warning ("help: invalid HTML data -- raw HTML source follows...");
-    disp (html_text);
-    text = "";
-    status = 1;
-  endif
-endfunction
-
-## This function removes end-lines (\n) that makes printing look bad
-function text = strip_superfluous_endlines (text)
-  ## Find groups of end-lines
-  els = find (text == "\n");
-  dels = diff (els);
-  groups = [els(1), 1]; # list containing [start, length] of each group
-  for k = 1:length (dels)
-    if (dels (k) == 1)
-      groups (end, 2) ++;
-    else
-      groups (end+1, 1:2) = [els(k+1), 1];
-    endif
-  endfor
-
-  keep = true (size (text));
-
-  ## Remove end-lines in the beginning
-  if (groups (1, 1) == 1)
-    keep (1:groups (1, 2)) = false;
-  endif
-
-  ## Remove end-lines from the end
-  if (sum (groups (end, :)) - 1 == length (text))
-    keep (groups (end, 1):end) = false;
-  endif
-
-  ## Remove groups of end-lines with more than 3 end-lines next to each other
-  idx = find (groups (:, 2) >= 3);
-  for k = 1:length (idx)
-    start = groups (idx (k), 1);
-    stop = start + groups (idx (k), 2) - 1;
-    keep (start+2:stop) = false;
-  endfor
-
-  ## Actually remove the elements
-  text = text (keep);
-endfunction
--- a/scripts/help/gen_doc_cache.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/help/gen_doc_cache.m	Tue Sep 20 15:38:24 2011 -0400
@@ -32,6 +32,7 @@
 ## @end deftypefn
 
 function gen_doc_cache (out_file = "doc-cache", directory = [])
+
   ## Check input
   if (!ischar (out_file))
     print_usage ();
@@ -143,3 +144,8 @@
   cache = create_cache (list);
 endfunction
 
+
+%% No true tests desirable for this function.
+%% Test input validation
+%!error gen_doc_cache (1)
+
--- a/scripts/help/module.mk	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/help/module.mk	Tue Sep 20 15:38:24 2011 -0400
@@ -1,11 +1,11 @@
 FCN_FILE_DIRS += help
 
 help_PRIVATE_FCN_FILES = \
-  help/private/__additional_help_message__.m
+  help/private/__additional_help_message__.m \
+  help/private/__strip_html_tags__.m
 
 help_FCN_FILES = \
   help/__makeinfo__.m \
-  help/__strip_html_tags__.m \
   help/doc.m \
   help/gen_doc_cache.m \
   help/get_first_help_sentence.m \
@@ -13,6 +13,7 @@
   help/lookfor.m \
   help/print_usage.m \
   help/type.m \
+  help/unimplemented.m \
   help/which.m \
   $(help_PRIVATE_FCN_FILES)
 
--- a/scripts/help/print_usage.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/help/print_usage.m	Tue Sep 20 15:38:24 2011 -0400
@@ -136,3 +136,7 @@
   retval = get_usage_plain_text (help_text, max_len);
 endfunction
 
+
+## Stop reporting function as missing tests.  No good tests possible.
+%!assert (1)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/help/private/__strip_html_tags__.m	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,81 @@
+## Copyright (C) 2009-2011 Søren Hauberg
+##
+## 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 3 of the License, 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, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {[@var{text}, @var{status}] =} __strip_html_tags__ (@var{html_text})
+## Undocumented internal function.
+## @end deftypefn
+
+## Remove HTML tags from text.  This is used as a simple HTML-to-text
+## function.
+
+function [text, status] = __strip_html_tags__ (html_text)
+  start = find (html_text == "<");
+  stop  = find (html_text == ">");
+  if (length (start) == length (stop))
+    text = html_text;
+    for n = length(start):-1:1
+      text (start (n):stop (n)) = [];
+    endfor
+    text = strip_superfluous_endlines (text);
+    status = 0;
+  else
+    warning ("help: invalid HTML data -- raw HTML source follows...");
+    disp (html_text);
+    text = "";
+    status = 1;
+  endif
+endfunction
+
+## This function removes end-lines (\n) that makes printing look bad
+function text = strip_superfluous_endlines (text)
+  ## Find groups of end-lines
+  els = find (text == "\n");
+  dels = diff (els);
+  groups = [els(1), 1]; # list containing [start, length] of each group
+  for k = 1:length (dels)
+    if (dels (k) == 1)
+      groups (end, 2) ++;
+    else
+      groups (end+1, 1:2) = [els(k+1), 1];
+    endif
+  endfor
+
+  keep = true (size (text));
+
+  ## Remove end-lines in the beginning
+  if (groups (1, 1) == 1)
+    keep (1:groups (1, 2)) = false;
+  endif
+
+  ## Remove end-lines from the end
+  if (sum (groups (end, :)) - 1 == length (text))
+    keep (groups (end, 1):end) = false;
+  endif
+
+  ## Remove groups of end-lines with more than 3 end-lines next to each other
+  idx = find (groups (:, 2) >= 3);
+  for k = 1:length (idx)
+    start = groups (idx (k), 1);
+    stop = start + groups (idx (k), 2) - 1;
+    keep (start+2:stop) = false;
+  endfor
+
+  ## Actually remove the elements
+  text = text (keep);
+endfunction
--- a/scripts/help/type.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/help/type.m	Tue Sep 20 15:38:24 2011 -0400
@@ -111,4 +111,14 @@
   endfor
 endfunction
 
+%!test
+%! var = 1;
+%! typestr = type ("var");
+%! typestr = typestr{1}(1:17);
+%! assert (typestr, "var is a variable");
 
+%!assert (type ('dot'){1}, "dot is a dynamically-linked function")
+%!assert (type ('cat'){1}, "cat is a built-in function")
+%!assert (type ('+'){1}, "+ is an operator")
+%!assert (type ('end'){1}, "end is a keyword")
+%!error (type ('NO_NAME'))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/help/unimplemented.m	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,439 @@
+## Copyright (C) 2010-2011 John W. Eaton
+## Copyright (C) 2010 VZLU Prague
+##
+## 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 3 of the License, 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, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {} unimplemented ()
+## Undocumented internal function.
+## @end deftypefn
+
+function txt = unimplemented (fcn)
+
+  is_matlab_function = true;
+
+  ## Some smarter cases, add more as needed.
+  switch (fcn)
+
+  case "quad2d"
+    txt = ["quad2d is not implemented.  Consider using dblquad."];
+
+  case "gsvd"
+    txt = ["gsvd is not currently part of Octave.  See the linear-algebra",...
+    "package at @url{http://octave.sf.net/linear-algebra/}."];
+
+  case "linprog"
+    txt = ["Octave does not currently provide linprog.  ",...
+    "Linear programming problems may be solved using @code{glpk}.  ",...
+    "Try @code{help glpk} for more info."];
+
+  case {"ode113", "ode15i", "ode15s", "ode23", "ode23s", "ode23t", "ode45", "odeget", "odeset"}
+    txt = ["Octave provides lsode for solving differential equations.  ",...
+    "For more information try @code{help lsode}.  ",...
+    "Matlab-compatible ODE functions are provided by the odepkg package.  ",...
+    "See @url{http://octave.sf.net/odepkg/}."];
+
+  otherwise
+    if (ismember (fcn, missing_functions ()))
+      txt = sprintf ("the `%s' function is not yet implemented in Octave", fcn);
+    else
+      is_matlab_function = false;
+      txt = "";
+    endif
+  endswitch
+
+  if (is_matlab_function)
+    txt = [txt, "\n\n@noindent\nPlease read ",...
+           "@url{http://www.octave.org/missing.html} to learn how ",...
+           "you can contribute missing functionality."];
+    txt = __makeinfo__ (txt);
+  endif
+
+  if (nargout == 0)
+    warning ("Octave:missing-function", "%s", txt);
+  endif
+
+endfunction
+
+function list = missing_functions ()
+  persistent list = {
+  "DelaunayTri",
+  "MException",
+  "RandStream",
+  "TriRep",
+  "TriScatteredInterp",
+  "addpref",
+  "align",
+  "alim",
+  "alpha",
+  "alphamap",
+  "annotation",
+  "audiodevinfo",
+  "audioplayer",
+  "audiorecorder",
+  "aufinfo",
+  "auread",
+  "auwrite",
+  "avifile",
+  "aviinfo",
+  "aviread",
+  "bar3",
+  "bar3h",
+  "bench",
+  "betaincinv",
+  "bicg",
+  "bicgstabl",
+  "brush",
+  "builddocsearchdb",
+  "bvp4c",
+  "bvp5c",
+  "bvpget",
+  "bvpinit",
+  "bvpset",
+  "bvpxtend",
+  "callSoapService",
+  "calllib",
+  "camdolly",
+  "cameratoolbar",
+  "camlight",
+  "camlookat",
+  "camorbit",
+  "campan",
+  "campos",
+  "camproj",
+  "camroll",
+  "camtarget",
+  "camup",
+  "camva",
+  "camzoom",
+  "cdf2rdf",
+  "cdfepoch",
+  "cdfinfo",
+  "cdfread",
+  "cdfwrite",
+  "cellplot",
+  "checkin",
+  "checkout",
+  "cholinc",
+  "clearvars",
+  "clipboard",
+  "cmopts",
+  "cmpermute",
+  "cmunique",
+  "colordef",
+  "colormapeditor",
+  "commandhistory",
+  "commandwindow",
+  "condeig",
+  "coneplot",
+  "contourslice",
+  "copyobj",
+  "createClassFromWsdl",
+  "createSoapMessage",
+  "customverctrl",
+  "daqread",
+  "datacursormode",
+  "datatipinfo",
+  "dbmex",
+  "dde23",
+  "ddeget",
+  "ddesd",
+  "ddeset",
+  "decic",
+  "depdir",
+  "depfun",
+  "deval",
+  "dialog",
+  "dither",
+  "docopt",
+  "docsearch",
+  "dragrect",
+  "dynamicprops",
+  "echodemo",
+  "ellipj",
+  "ellipke",
+  "erfcinv",
+  "errordlg",
+  "evalc",
+  "exifread",
+  "expint",
+  "export2wsdlg",
+  "figurepalette",
+  "filebrowser",
+  "fill3",
+  "findfigs",
+  "fitsinfo",
+  "fitsread",
+  "flow",
+  "fminsearch",
+  "frame2im",
+  "freqspace",
+  "funm",
+  "gallery",
+  "gammaincinv",
+  "gco",
+  "getframe",
+  "getpixelposition",
+  "getpref",
+  "gmres",
+  "grabcode",
+  "graymon",
+  "gsvd",
+  "guidata",
+  "guide",
+  "guihandles",
+  "handle",
+  "hdf",
+  "hdf5",
+  "hdf5info",
+  "hdf5read",
+  "hdf5write",
+  "hdfinfo",
+  "hdfread",
+  "hdftool",
+  "helpbrowser",
+  "helpdesk",
+  "helpdlg",
+  "helpwin",
+  "hgexport",
+  "hgload",
+  "hgsave",
+  "hgsetget",
+  "hgtransform",
+  "hostid",
+  "ilu",
+  "im2frame",
+  "im2java",
+  "imapprox",
+  "imformats",
+  "import",
+  "importdata",
+  "inmem",
+  "inputParser",
+  "inputdlg",
+  "inspect",
+  "instrfind",
+  "instrfindall",
+  "interpstreamspeed",
+  "iscom",
+  "isinterface",
+  "isjava",
+  "isocaps",
+  "ispref",
+  "isstudent",
+  "javaArray",
+  "javaMethod",
+  "javaMethodEDT",
+  "javaObject",
+  "javaObjectEDT",
+  "javaaddpath",
+  "javachk",
+  "javaclasspath",
+  "javarmpath",
+  "ldl",
+  "libfunctions",
+  "libfunctionsview",
+  "libisloaded",
+  "libpointer",
+  "libstruct",
+  "light",
+  "lightangle",
+  "lighting",
+  "linkaxes",
+  "linkdata",
+  "linsolve",
+  "listdlg",
+  "listfonts",
+  "loadlibrary",
+  "lscov",
+  "lsqr",
+  "makehgtform",
+  "material",
+  "matlabrc",
+  "maxNumCompThreads",
+  "memmapfile",
+  "memory",
+  "metaclass",
+  "methodsview",
+  "minres",
+  "mlint",
+  "mlintrpt",
+  "mmfileinfo",
+  "mmreader",
+  "movegui",
+  "movie",
+  "movie2avi",
+  "msgbox",
+  "multibandread",
+  "multibandwrite",
+  "native2unicode",
+  "noanimate",
+  "ode113",
+  "ode15i",
+  "ode15s",
+  "ode23",
+  "ode23s",
+  "ode23t",
+  "ode23tb",
+  "ode45",
+  "odefile",
+  "odeget",
+  "odeset",
+  "odextend",
+  "open",
+  "openfig",
+  "opengl",
+  "openvar",
+  "ordeig",
+  "ordqz",
+  "ordschur",
+  "padecoef",
+  "pagesetupdlg",
+  "pan",
+  "parseSoapResponse",
+  "path2rc",
+  "pathtool",
+  "pcode",
+  "pdepe",
+  "pdeval",
+  "playshow",
+  "plotbrowser",
+  "plotedit",
+  "plottools",
+  "polyeig",
+  "prefdir",
+  "preferences",
+  "printdlg",
+  "printopt",
+  "printpreview",
+  "profile",
+  "profsave",
+  "propedit",
+  "propertyeditor",
+  "publish",
+  "qmr",
+  "quad2d",
+  "questdlg",
+  "rbbox",
+  "recycle",
+  "reducepatch",
+  "reducevolume",
+  "resample",
+  "rgbplot",
+  "rmpref",
+  "root",
+  "rotate",
+  "rotate3d",
+  "selectmoveresize",
+  "sendmail",
+  "serial",
+  "setpixelposition",
+  "setpref",
+  "showplottool",
+  "shrinkfaces",
+  "smooth3",
+  "snapnow",
+  "sound",
+  "soundsc",
+  "ss2tf",
+  "stream2",
+  "stream3",
+  "streamline",
+  "streamparticles",
+  "streamribbon",
+  "streamslice",
+  "streamtube",
+  "strings",
+  "subvolume",
+  "superclasses",
+  "support",
+  "surf2patch",
+  "symmlq",
+  "syntax",
+  "tetramesh",
+  "texlabel",
+  "textwrap",
+  "tfqmr",
+  "timer",
+  "timerfind",
+  "timerfindall",
+  "timeseries",
+  "toolboxdir",
+  "tscollection",
+  "tstool",
+  "uibuttongroup",
+  "uicontextmenu",
+  "uicontrol",
+  "uigetpref",
+  "uiimport",
+  "uiopen",
+  "uipanel",
+  "uipushtool",
+  "uiresume",
+  "uisave",
+  "uisetcolor",
+  "uisetfont",
+  "uisetpref",
+  "uistack",
+  "uitable",
+  "uitoggletool",
+  "uitoolbar",
+  "uiwait",
+  "undocheckout",
+  "unicode2native",
+  "unloadlibrary",
+  "unmesh",
+  "usejava",
+  "userpath",
+  "validateattributes",
+  "verLessThan",
+  "viewmtx",
+  "visdiff",
+  "volumebounds",
+  "waitbar",
+  "waitfor",
+  "warndlg",
+  "waterfall",
+  "wavfinfo",
+  "wavplay",
+  "wavrecord",
+  "web",
+  "whatsnew",
+  "wk1finfo",
+  "wk1read",
+  "wk1write",
+  "workspace",
+  "xlsfinfo",
+  "xlsread",
+  "xlswrite",
+  "xmlread",
+  "xmlwrite",
+  "xslt",
+  "zoom",
+  };
+endfunction
+
+
+%!test
+%! str = unimplemented ("no_name_function");
+%! assert (isempty (str));
+%! str = unimplemented ("quad2d");
+%! assert (str(1:51), "quad2d is not implemented.  Consider using dblquad.");
+%! str = unimplemented ("MException");
+%! assert (str(1:58), "the `MException' function is not yet implemented in Octave");
+
+
--- a/scripts/help/which.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/help/which.m	Tue Sep 20 15:38:24 2011 -0400
@@ -53,3 +53,13 @@
   endif
 
 endfunction
+
+
+%!test
+%! str = which ("ls");
+%! assert (str(end-17:end), strcat ("miscellaneous", filesep(), "ls.m"));
+%!test
+%! str = which ("dot");
+%! assert (str(end-6:end), "dot.oct");
+
+%!assert (which ("NO_NAME"), "");
--- a/scripts/image/image.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/image/image.m	Tue Sep 20 15:38:24 2011 -0400
@@ -19,9 +19,9 @@
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {} image (@var{img})
 ## @deftypefnx {Function File} {} image (@var{x}, @var{y}, @var{img})
-## Display a matrix as a color image.  The elements of @var{x} are indices
+## Display a matrix as a color image.  The elements of @var{img} are indices
 ## into the current colormap, and the colormap will be scaled so that the
-## extremes of @var{x} are mapped to the extremes of the colormap.
+## extremes of @var{img} are mapped to the extremes of the colormap.
 ##
 ## The axis values corresponding to the matrix elements are specified in
 ## @var{x} and @var{y}.  If you're not using gnuplot 4.2 or later, these
--- a/scripts/io/beep.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/io/beep.m	Tue Sep 20 15:38:24 2011 -0400
@@ -26,10 +26,13 @@
 
 function beep ()
 
-  if (nargin == 0)
-    puts ("\a");
-  else
+  if (nargin != 0)
     print_usage ();
   endif
 
+  puts ("\a");
+
 endfunction
+
+
+%!error (beep (1))
--- a/scripts/io/strread.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/io/strread.m	Tue Sep 20 15:38:24 2011 -0400
@@ -19,15 +19,16 @@
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {[@var{a}, @dots{}] =} strread (@var{str})
 ## @deftypefnx {Function File} {[@var{a}, @dots{}] =} strread (@var{str}, @var{format})
+## @deftypefnx {Function File} {[@var{a}, @dots{}] =} strread (@var{str}, @var{format}, @var{format_repeat})
 ## @deftypefnx {Function File} {[@var{a}, @dots{}] =} strread (@var{str}, @var{format}, @var{prop1}, @var{value1}, @dots{})
+## @deftypefnx {Function File} {[@var{a}, @dots{}] =} strread (@var{str}, @var{format}, @var{format_repeat}, @var{prop1}, @var{value1}, @dots{})
 ## Read data from a string.
 ##
 ## The string @var{str} is split into words that are repeatedly matched to the
 ## specifiers in @var{format}.  The first word is matched to the first
-## specifier,
-## the second to the second specifier and so forth.  If there are more words
-## than
-## specifiers, the process is repeated until all words have been processed.
+## specifier, the second to the second specifier and so forth.  If there are
+## more words than specifiers, the process is repeated until all words have
+## been processed.
 ##
 ## The string @var{format} describes how the words in @var{str} should be
 ## parsed.
@@ -36,19 +37,31 @@
 ## @item %s
 ## The word is parsed as a string.
 ##
-## @item %d
 ## @itemx %f
-## The word is parsed as a number.
+## @itemx %n
+## The word is parsed as a number and converted to double.
+##
+## @item  %d
+## @itemx %u
+## The word is parsed as a number and converted to int32.
 ##
-## @item %*
+## @item %*', '%*f', '%*s
 ## The word is skipped.
+##
+## For %s and %d, %f, %n, %u and the associated %*s @dots{} specifiers an
+## optional width can be specified as %Ns, etc. where N is an integer > 1.
+## For %f, format specifiers like %N.Mf are allowed.
+##
+## @item literals
+## In addition the format may contain literal character strings; these will be
+## skipped during reading.
 ## @end table
 ##
 ## Parsed word corresponding to the first specifier are returned in the first
 ## output argument and likewise for the rest of the specifiers.
 ##
 ## By default, @var{format} is @t{"%f"}, meaning that numbers are read from
-## @var{str}.
+## @var{str}.  This will do if @var{str} contains only numeric fields.
 ##
 ## For example, the string
 ##
@@ -68,6 +81,18 @@
 ## [@var{a}, @var{b}, @var{c}] = strread (@var{str}, "%s %s %f");
 ## @end example
 ##
+## Optional numeric argument @var{format_repeat} can be used for
+## limiting the number of items read:
+## @table @asis
+## @item -1
+## (default) read all of the string until the end.
+##
+## @item N
+## Read N times @var{nargout} items.  0 (zero) is an acceptable
+## value for @var{format_repeat}.
+##
+## @end table
+##
 ## The behavior of @code{strread} can be changed via property-value
 ## pairs.  The following properties are recognized:
 ##
@@ -77,94 +102,202 @@
 ## @var{value} is the comment style and can be any of the following.
 ## @itemize
 ## @item "shell"
-## Everything from @code{#} characters to the nearest end-line is skipped.
+## Everything from @code{#} characters to the nearest end-of-line is skipped.
 ##
 ## @item "c"
 ## Everything between @code{/*} and @code{*/} is skipped.
 ##
 ## @item "c++"
-## Everything from @code{//} characters to the nearest end-line is skipped.
+## Everything from @code{//} characters to the nearest end-of-line is skipped.
 ##
 ## @item "matlab"
-## Everything from @code{%} characters to the nearest end-line is skipped.
+## Everything from @code{%} characters to the nearest end-of-line is skipped.
+##
+## @item user-supplied.  Two options:
+## (1) One string, or 1x1 cell string: Skip everything to the right of it;
+## (2) 2x1 cell string array: Everything between the left and right strings
+## is skipped.
 ## @end itemize
 ##
 ## @item "delimiter"
-## Any character in @var{value} will be used to split @var{str} into words.
+## Any character in @var{value} will be used to split @var{str} into words
+## (default value = any whitespace).
 ##
 ## @item "emptyvalue"
 ## Parts of the output where no word is available is filled with @var{value}.
+##
+## @item "multipledelimsasone"
+## Treat a series of consecutive delimiters, without whitespace in between,
+## as a single delimiter.  Consecutive delimiter series need not be vertically
+## "aligned".
+##
+## @item "treatasempty"
+## Treat single occurrences (surrounded by delimiters or whitespace) of the
+## string(s) in @var{value} as missing values.
+##
+## @item "returnonerror"
+## If @var{value} true (1, default), ignore read errors and return normally.
+## If false (0), return an error.
+##
+## @item "whitespace"
+## Any character in @var{value} will be interpreted as whitespace and
+## trimmed; the string defining whitespace must be enclosed in double
+## quotes for proper processing of special characters like \t.
+## The default value for whitespace = " \b\r\n\t" (note the space).
+##
 ## @end table
 ##
-## @seealso{textread, load, dlmread, fscanf}
+## @seealso{textscan, textread, load, dlmread, fscanf}
 ## @end deftypefn
 
 function varargout = strread (str, format = "%f", varargin)
+
   ## Check input
   if (nargin < 1)
     print_usage ();
   endif
 
-  if (!ischar (str) || !ischar (format))
+  if (isempty (format))
+    format = "%f";
+  endif
+
+  if (! ischar (str) || ! ischar (format))
     error ("strread: STR and FORMAT arguments must be strings");
   endif
 
-  ## Parse options
+  ## Parse format string to compare number of conversion fields and nargout
+  nfields = length (strfind (format, "%")) - length (strfind (format, "%*"));
+  ## If str only has numeric fields, a (default) format ("%f") will do.
+  ## Otherwise:
+  if ((max (nargout, 1) != nfields) && ! strcmp (format, "%f"))
+    error ("strread: the number of output variables must match that specified by FORMAT");
+  endif
+
+  ## Check for format string repeat count
+  format_repeat_count = -1;
+  if (nargin > 2 && isnumeric (varargin{1}))
+    if (varargin{1} >= 0)
+      format_repeat_count = varargin{1};
+    endif
+    if (nargin > 3)
+      varargin = varargin(2:end);
+    else
+      varargin = {};
+    endif
+  endif
+
+  ## Parse options.  First initialize defaults
   comment_flag = false;
-  numeric_fill_value = 0;
-  white_spaces = " \n\r\t\b";
   delimiter_str = "";
+  empty_str = "";
+  eol_char = "";
+  err_action = 0;
+  mult_dlms_s1 = false;
+  numeric_fill_value = NaN;
+  white_spaces = " \b\r\n\t";
   for n = 1:2:length (varargin)
-    switch (lower (varargin {n}))
+    switch (lower (varargin{n}))
+      case "bufsize"
+        ## We could synthesize this, but that just seems weird...
+        warning ('strread: property "bufsize" is not implemented');
       case "commentstyle"
         comment_flag = true;
-        switch (lower (varargin {n+1}))
+        switch (lower (varargin{n+1}))
           case "c"
-            comment_specif = {"/*", "*/"};
+            [comment_start, comment_end] = deal ("/*", "*/");
           case "c++"
-            comment_specif = {"//", "\n"};
+            [comment_start, comment_end] = deal ("//", "eol_char");
           case "shell"
-            comment_specif = {"#", "\n"};
+            [comment_start, comment_end] = deal ("#" , "eol_char");
           case "matlab"
-            comment_specif = {"%", "\n"};
+            [comment_start, comment_end] = deal ("%" , "eol_char");
           otherwise
-            warning ("strread: unknown comment style '%s'", val);
+            if (ischar (varargin{n+1}) ||
+               (numel (varargin{n+1}) == 1 && iscellstr (varargin{n+1})))
+              [comment_start, comment_end] = deal (char (varargin{n+1}), "eol_char");
+            elseif (iscellstr (varargin{n+1}) && numel (varargin{n+1}) == 2)
+              [comment_start, comment_end] = deal (varargin{n+1}{:});
+            else
+              ## FIXME - a user may have numeric values specified: {'//', 7}
+              ##         this will lead to an error in the warning message
+              error ("strread: unknown or unrecognized comment style '%s'",
+                      varargin{n+1});
+            endif
         endswitch
       case "delimiter"
-        delimiter_str = varargin {n+1};
+        delimiter_str = varargin{n+1};
       case "emptyvalue"
-        numeric_fill_value = varargin {n+1};
-      case "bufsize"
-        ## XXX: We could synthesize this, but that just seems weird...
-        warning ("strread: property \"bufsize\" is not implemented");
+        numeric_fill_value = varargin{n+1};
+      case "expchars"
+        warning ('strread: property "expchars" is not implemented');
       case "whitespace"
-        white_spaces = varargin {n+1};
-      case "expchars"
-        warning ("strread: property \"expchars\" is not implemented");
+        white_spaces = varargin{n+1};
+      ## The following parameters are specific to textscan and textread
+      case "endofline"
+        eol_char = varargin{n+1};
+      case "returnonerror"
+        err_action = varargin{n+1};
+      case "multipledelimsasone"
+        mult_dlms_s1 = varargin{n+1};
+      case "treatasempty"
+        if (iscellstr (varargin{n+1}))
+          empty_str = varargin{n+1};
+        elseif (ischar (varargin{n+1}))
+          empty_str = varargin(n+1);
+        else
+          error ('strread: "treatasempty" value must be string or cellstr');
+        endif
       otherwise
-        warning ("strread: unknown property \"%s\"", varargin {n});
+        warning ('strread: unknown property "%s"', varargin{n});
     endswitch
   endfor
-  if (isempty (delimiter_str))
-    delimiter_str = white_spaces;
+
+  ## First parse of FORMAT
+  if (strcmpi (strtrim (format), "%f"))
+    ## Default format specified.  Expand it (to desired nargout)
+    fmt_words = cell (nargout, 1);
+    fmt_words (1:nargout) = format;
+  else
+    ## Determine the number of words per line as a first guess.  Forms
+    ## like %f<literal>) (w/o delimiter in between) are fixed further on
+    format = strrep (format, "%", " %");
+    fmt_words = regexp (format, '[^ ]+', 'match');
+    ## Format conversion specifiers following literals w/o space/delim
+    ## in between are separate now.  Separate those w trailing literals
+    idy2 = find (! cellfun ("isempty", strfind (fmt_words, "%")));
+    a = strfind (fmt_words(idy2), "%");
+    b = regexp (fmt_words(idy2), '[nfdus]', 'end');
+    for jj = 1:numel (a)
+      ii = numel (a) - jj + 1;
+      if (! (length (fmt_words{idy2(ii)}) == b{ii}(1)))
+        ## Fix format_words
+        fmt_words(idy2(ii)+1 : end+1) = fmt_words(idy2(ii) : end);
+        fmt_words{idy2(ii)} = fmt_words{idy2(ii)}(a{ii} : b{ii}(1));
+        fmt_words{idy2(ii)+1} = fmt_words{idy2(ii)+1}(b{ii}+1:end);
+      endif
+    endfor
+  endif
+  num_words_per_line = numel (fmt_words);
+
+  ## Special handling for CRLF EOL character in str
+  if (! isempty (eol_char) && strcmp (eol_char, "\r\n"))
+    ## Strip CR from CRLF sequences
+    str = strrep (str, "\r\n", "\n");
+    ## CR serves no further purpose in function
+    eol_char = "\n";
   endif
 
-  ## Parse format string
-  idx = strfind (format, "%")';
-  specif = format ([idx, idx+1]);
-  nspecif = length (idx);
-  idx_star = strfind (format, "%*");
-  nfields = length (idx) - length (idx_star);
-
-  if (max (nargout, 1) != nfields)
-    error ("strread: the number of output variables must match that specified byFORMAT");
-  endif
-
-  ## Remove comments
+  ## Remove comments in str
   if (comment_flag)
-    cstart = strfind (str, comment_specif{1});
-    cstop  = strfind (str, comment_specif{2});
-    if (length (cstart) > 0)
+    ## Expand 'eol_char' here, after option processing which may have set value
+    comment_end = regexprep (comment_end, 'eol_char', eol_char);
+    cstart = strfind (str, comment_start);
+    cstop  = strfind (str, comment_end);
+    ## Treat end of string as additional comment stop
+    if (isempty (cstop) || cstop(end) != length (str))
+      cstop(end+1) = length (str);
+    endif
+    if (! isempty (cstart))
       ## Ignore nested openers.
       [idx, cidx] = unique (lookup (cstop, cstart), "first");
       if (idx(end) == length (cstop))
@@ -172,7 +305,7 @@
       endif
       cstart = cstart(cidx);
     endif
-    if (length (cstop) > 0)
+    if (! isempty (cstop))
       ## Ignore nested closers.
       [idx, cidx] = unique (lookup (cstart, cstop), "first");
       if (idx(1) == 0)
@@ -181,101 +314,406 @@
       cstop = cstop(cidx);
     endif
     len = length (str);
-    c2len = length (comment_specif{2});
+    c2len = length (comment_end);
     str = cellslices (str, [1, cstop + c2len], [cstart - 1, len]);
     str = [str{:}];
   endif
 
-  ## Determine the number of words per line
-  format = strrep (format, "%", " %");
-  [~, ~, ~, fmt_words] = regexp (format, '[^ ]+');
+  if (! isempty (white_spaces))
+    ## Remove any delimiter chars from white_spaces list
+    white_spaces = setdiff (white_spaces, delimiter_str);
+  endif
+  if (isempty (delimiter_str))
+    delimiter_str = " ";
+  endif
+  if (! isempty (eol_char))
+    ## Add eol_char to delimiter collection
+    delimiter_str = unique ([delimiter_str eol_char]);
+    ## .. and remove it from whitespace collection
+    white_spaces = strrep (white_spaces, eol_char, '');
+  endif
 
-  num_words_per_line = numel (fmt_words);
-  for m = 1:numel(fmt_words)
-    ## Convert formats such as "%Ns" to "%s" (see the FIXME below)
-    if (length (fmt_words{m}) > 2)
-      if (strcmp (fmt_words{m}(1:2), "%*"))
-        fmt_words{m} = "%*";
-      elseif (fmt_words{m}(1) == "%")
-        fmt_words{m} = fmt_words{m}([1, end]);
-      endif
+  pad_out = 0;
+  ## Trim whitespace if needed
+  ## FIXME: This is very complicated.  Can this be simplified with regexprep?
+  if (! isempty (white_spaces))
+    ## Check if trailing "\n" might signal padding output arrays to equal size
+    ## before it is trimmed away below
+    if ((str(end) == 10) && (nargout > 1))
+      pad_out = 1;
     endif
-  endfor
+    ## Remove repeated white_space chars.  First find white_space positions
+    idx = strchr (str, white_spaces);
+    ## Find repeated white_spaces
+    idx2 = ! (idx(2:end) - idx(1:end-1) - 1);
+    ## Set all whitespace chars to spaces
+    ## FIXME: this implies real spaces are always part of white_spaces
+    str(idx) = ' ';
+    ## Set all repeated white_space to \0
+    str(idx(idx2)) = "\0";
+    str = strsplit (str, "\0");
+    ## Reconstruct trimmed str
+    str = cell2mat (str);
+    ## Remove leading & trailing space, but preserve delimiters.
+    str = strtrim (str);
+    ## FIXME: Double strrep on str is enormously expensive of CPU time.
+    ## Can this be eliminated
+    ## Wipe leading and trailing whitespace on each line (it may be delimiter too)
+    if (! isempty (eol_char))
+      str = strrep (str, [eol_char " "], eol_char);
+      str = strrep (str, [" " eol_char], eol_char);
+    endif
+  endif
 
   ## Split 'str' into words
-  words = split_by (str, delimiter_str);
+  words = split_by (str, delimiter_str, mult_dlms_s1, eol_char);
+  if (! isempty (white_spaces))
+    ## Trim leading and trailing white_spaces
+    ## FIXME: Is this correct?  strtrim clears what matches isspace(), not
+    ## necessarily what is in white_spaces.
+    words = strtrim (words);
+  endif
   num_words = numel (words);
+  ## First guess at number of lines in file (ignoring leading/trailing literals)
   num_lines = ceil (num_words / num_words_per_line);
 
-  ## For each specifier
+  ## Replace TreatAsEmpty char sequences by empty strings
+  if (! isempty (empty_str))
+    for ii = 1:numel (empty_str)
+      idz = strmatch (empty_str{ii}, words, "exact");
+      words(idz) = {""};
+    endfor
+  endif
+
+  ## We now may have to cope with 3 cases:
+  ## A: Trailing literals (%f<literal>) w/o delimiter in between.
+  ## B: Leading literals (<literal>%f) w/o delimiter in between.
+  ## C. Skipping leftover parts of specified skip fields (%*N )
+  ## fmt_words has been split properly now, but words{} has only been split on
+  ## delimiter positions.  Some words columns may have to be split further.
+  ## We also don't know the number of lines (as EndOfLine may have been set to
+  ## "" (empty) by the caller).
+
+  ## Find indices and pointers to possible literals in fmt_words
+  idf = cellfun ("isempty", strfind (fmt_words, "%"));
+  ## Find indices and pointers to conversion specifiers with fixed width
+  idg = ! cellfun ("isempty", regexp (fmt_words, '%\*?\d'));
+  idy = find (idf | idg);
+
+  ## If needed, split up columns in three steps:
+  if (! isempty (idy))
+    ## Try-catch because complexity of strings to read can be infinite
+    #try
+
+      ## 1. Assess "period" in the split-up words array ( < num_words_per_line).
+      ## Could be done using EndOfLine but that prohibits EndOfLine = "" option.
+      ## Alternative below goes by simply parsing a first grab of words
+      ## and counting words until the fmt_words array is exhausted:
+      iwrd = 1; iwrdp = 0; iwrdl = length (words{iwrd});
+      for ii = 1:numel (fmt_words)
+
+        if (idf(ii))
+          ## Literal expected
+          if (isempty (strfind (fmt_words{ii}, words(iwrd))))
+            ## Not found in current word; supposed to be in next word
+            ++iwrd; iwrdp = 0;
+            if (ii < numel (fmt_words))
+              iwrdl = length (words{iwrd});
+            endif
+          else
+            ## Found it in current word.  Subtract literal length
+            iwrdp += length (fmt_words{ii});
+            if (iwrdp > iwrdl)
+              ## Parse error.  Literal extends beyond delimiter (word boundary)
+              error ("strread: Literal '%s' (fmt spec # %d) does not match data", fmt_words{ii}, ii);
+            elseif (iwrdp == iwrdl)
+              ## Word completely "used up". Next word
+              ++iwrd; iwrdp = 0;
+              if (ii < numel (fmt_words))
+                iwrdl = length (words{iwrd});
+              endif
+            endif
+          endif
+
+        elseif (idg(ii))
+          ## Fixed width specifier (%N or %*N): read just a part of word
+            iwrdp += floor ...
+             (str2double (fmt_words{ii}(regexp(fmt_words{ii}, '\d') : end-1)));
+            if (iwrdp > iwrdl)
+              ## Error. Field extends beyond word boundary.
+              error ("strread: Field width '%s' (fmt spec # %d) extends beyond word limit", fmt_words{ii}, ii);
+            elseif (iwrdp == iwrdl)
+              ## Word completely "used up".  Next word
+              ++iwrd; iwrdp = 0; iwrdl = length (words{iwrd});
+            endif
+
+        else
+          ## A simple format conv. specifier. Either (1) uses rest of word, or
+          ## (2) is squeezed between current iwrdp and next literal, or (3) uses
+          ## next word. (3) is already taken care of.  So just check (1) & (2)
+          if (ii < numel (fmt_words) && idf(ii+1))
+            ## Next fmt_word is a literal...
+            if (! index (words{iwrd}(iwrdp+1:end), fmt_words{ii+1}))
+              ## ...but not found in current word => field uses rest of word
+              ++iwrd; iwrdp = 0; iwrdl = length (words{iwrd});
+            else
+              ## ..or it IS found.  Add inferred width of current conversion field
+              iwrdp += index (words{iwrd}(iwrdp+1:end), fmt_words{ii+1}) - 1;
+            endif
+          elseif (iwrdp < iwrdl)
+            ## No bordering literal to the right => field occupies (rest of) word
+            ++iwrd; iwrdp = 0;
+            if (ii < numel (fmt_words))
+              iwrdl = length (words{iwrd});
+            endif
+          endif
+
+        endif
+      endfor
+      ## Done
+      words_period = max (iwrd - 1, 1);
+      num_lines = ceil (num_words / words_period);
+
+      ## 2. Pad words array so that it can be reshaped
+      tmp_lines = ceil (num_words / words_period);
+      num_words_padded = tmp_lines * words_period - num_words;
+      if (num_words_padded)
+        words = [words'; cell(num_words_padded, 1)];
+      endif
+      words = reshape (words, words_period, tmp_lines);
+
+      ## 3. Do the column splitting on rectangular words array
+      icol = 1; ii = 1;    # icol = current column, ii = current fmt_word
+      while (ii <= num_words_per_line)
+
+        ## Check if fmt_words(ii) contains a literal or fixed-width
+        if ((idf(ii) || idg(ii)) && (rows(words) < num_words_per_line))
+          if (idf(ii))
+            s = strfind (words(icol, 1), fmt_words{ii});
+            if (isempty (s{:}))
+              error ("strread: Literal '%s' not found in column %d", fmt_words{ii}, icol);
+            endif
+            s = s{:}(1);
+            e = s(1) + length (fmt_words{ii}) - 1;
+          endif
+          if (! strcmp (fmt_words{ii}, words{icol, 1}))
+            ## Column doesn't exactly match literal => split needed.  Insert a column
+            words(icol+1:end+1, :) = words(icol:end, :);
+            ## Watch out for empty cells
+            jptr = find (! cellfun ("isempty", words(icol, :)));
+
+            ## Distinguish leading or trailing literals
+            if (! idg(ii) && ! isempty (s) && s(1) == 1)
+              ## Leading literal.  Assign literal to icol, paste rest in icol + 1
+              ## Apply only to those cells that do have something beyond literal
+              jptr = find (cellfun("length", words(icol+1, jptr), ...
+                            "UniformOutput", false) > e(1));
+              words(icol+1, :) = {""};
+              words(icol+1, jptr) = cellfun ...
+                (@(x) substr(x, e(1)+1, length(x)-e(1)), words(icol, jptr), ...
+                "UniformOutput", false);
+              words(icol, jptr) = fmt_words{ii};
+
+            else
+              if (! idg(ii) && ! isempty (strfind (fmt_words{ii-1}, "%s")))
+                ## Trailing literal.  If preceding format == '%s' this is an error
+                warning ("Ambiguous '%s' specifier next to literal in column %d", icol);
+              elseif (idg(ii))
+                ## Current field = fixed width. Strip into icol, rest in icol+1
+                wdth = floor (str2double (fmt_words{ii}(regexp(fmt_words{ii}, ...
+                              '\d') : end-1)));
+                words(icol+1, jptr) = cellfun (@(x) x(wdth+1:end),
+                     words(icol,jptr), "UniformOutput", false);
+                words(icol, jptr) = strtrunc (words(icol, jptr), wdth);
+              else
+                ## FIXME: this assumes char(254)/char(255) won't occur in input!
+                clear wrds;
+                wrds(1:2:2*numel (words(icol, jptr))) = ...
+                     strrep (words(icol, jptr), fmt_words{ii}, ...
+                     [char(255) char(254)]);
+                wrds(2:2:2*numel (words(icol, jptr))-1) = char(255);
+                wrds = strsplit ([wrds{:}], char(255));
+                words(icol, jptr) = ...
+                  wrds(find (cellfun ("isempty", strfind (wrds, char(254)))));
+                wrds(find (cellfun ("isempty", strfind (wrds, char(254))))) ...
+                   = char(255);
+                words(icol+1, jptr) = strsplit (strrep ([wrds{2:end}], ...
+                   char(254), fmt_words{ii}), char(255));
+                ## Former trailing literal may now be leading for next specifier
+                --ii;
+              endif
+            endif
+          endif
+
+        else
+          ## Conv. specifier.  Peek if next fmt_word needs split from current column
+          if (ii < num_words_per_line && idf(ii+1))
+            if (! isempty (strfind (words{icol, 1}, fmt_words{ii+1})))
+              --icol;
+            endif
+          endif
+        endif
+        ## Next fmt_word, next column
+        ++ii; ++icol;
+      endwhile
+
+      ## Done.  Reshape words back into 1 long vector and strip padded empty words
+      words = reshape (words, 1, numel (words))(1 : end-num_words_padded);
+
+    #catch
+    #  warning ("strread: unable to parse text or file with given format string");
+    #  return;
+
+    #end_try_catch
+  endif
+
+  ## For each specifier, process corresponding column
   k = 1;
   for m = 1:num_words_per_line
-    data = words (m:num_words_per_line:end);
-    ## Map to format
-    ## FIXME - add support for formats like "%4s" or "<%s>", "%[a-zA-Z]"
-    ##         Someone with regexp experience is needed.
-    switch fmt_words{m}
-      case "%s"
-        data (end+1:num_lines) = {""};
-        varargout {k} = data';
-        k++;
-      case {"%d", "%f"}
-        n = cellfun (@isempty, data);
-        data = str2double (data);
-        data(n) = numeric_fill_value;
-        data (end+1:num_lines) = numeric_fill_value;
-        varargout {k} = data.';
-        k++;
-      case {"%*", "%*s"}
-        ## skip the word
-      otherwise
-        ## Ensure descriptive content is consistent
-        if (numel (unique (data)) > 1
-            || ! strcmpi (unique (data), fmt_words{m}))
-          error ("strread: FORMAT does not match data");
-        endif
-    endswitch
+    try
+      if (format_repeat_count < 0)
+        data = words(m:num_words_per_line:end);
+      elseif (format_repeat_count == 0)
+        data = {};
+      else
+        lastline = ...
+          min (num_words_per_line * format_repeat_count + m - 1, numel (words));
+        data = words(m:num_words_per_line:lastline);
+      endif
+
+      ## Map to format
+      ## FIXME - add support for formats like "<%s>", "%[a-zA-Z]"
+      ##         Someone with regexp experience is needed.
+      switch fmt_words{m}(1:min (2, length (fmt_words{m})))
+        case "%s"
+          if (pad_out)
+            data(end+1:num_lines) = {""};
+          endif
+          varargout{k} = data';
+          k++;
+        case {"%d", "%u", "%f", "%n"}
+          n = cellfun ("isempty", data);
+          ### FIXME - erroneously formatted data lead to NaN, not an error
+          data = str2double (data);
+          if (! isempty (regexp (fmt_words{m}, "%[du]")))
+            ## Cast to integer
+            ## FIXME: NaNs will be transformed into zeros
+            data = int32 (data);
+          end
+          data(n) = numeric_fill_value;
+          if (pad_out)
+            data(end+1:num_lines) = numeric_fill_value;
+          endif
+          varargout{k} = data.';
+          k++;
+        case {"%0", "%1", "%2", "%3", "%4", "%5", "%6", "%7", "%8", "%9"}
+          nfmt = strsplit (fmt_words{m}(2:end-1), '.');
+          swidth = str2double (nfmt{1});
+          switch fmt_words{m}(end)
+            case {"d", "u", "f", "n%"}
+              n = cellfun ("isempty", data);
+              ### FIXME - erroneously formatted data lead to NaN, not an error
+              ###         => ReturnOnError can't be implemented for numeric data
+              data = str2double (strtrunc (data, swidth));
+              data(n) = numeric_fill_value;
+              if (pad_out)
+                data(end+1:num_lines) = numeric_fill_value;
+              endif
+              if (numel (nfmt) > 1)
+                sprec = str2double (nfmt{2});
+                data = 10^-sprec * round (10^sprec * data);
+              elseif (! isempty (regexp (fmt_words{m}, "[du]")))
+                ## Cast to integer
+                ## FIXME: NaNs will be transformed into zeros
+                data = int32 (data);
+              end
+              varargout{k} = data.';
+              k++;
+            case "s"
+              if (pad_out)
+                data(end+1:num_lines) = {""}
+              endif
+              varargout{k} = strtrunc (data, swidth)';
+              k++;
+            otherwise
+          endswitch
+        case {"%*", "%*s"}
+          ## skip the word
+        otherwise
+          ## Ensure descriptive content is consistent.
+          ## Test made a bit lax to accomodate for incomplete last lines
+          n = find (! cellfun ("isempty", data));
+          if (numel (unique (data(n))) > 1
+              || ! strcmpi (unique (data), fmt_words{m}))
+            error ("strread: FORMAT does not match data");
+          endif
+      endswitch
+    catch
+      ## As strread processes columnwise, ML-compatible error processing
+      ## (row after row) is not feasible. In addition Octave sets unrecognizable
+      ## numbers to NaN w/o error.  But maybe Octave is better in this respect.
+      if (err_action)
+        ## Just try the next column where ML bails out
+      else
+        rethrow (lasterror);
+      endif
+    end_try_catch
   endfor
+
 endfunction
 
-function out = split_by (text, sep)
-  sep = union (sep, "\n");
-  pat = sprintf ('[^%s]+', sep);
-  [~, ~, ~, out] = regexp (text, pat);
-  out(cellfun (@isempty, out)) = {""};
-  out = strtrim (out);
+function out = split_by (text, sep, mult_dlms_s1, eol_char)
+
+  ## Check & if needed, process MultipleDelimsAsOne parameter
+  if (mult_dlms_s1)
+    mult_dlms_s1 = true;
+    ## FIXME: Should re-implement strsplit() function here in order
+    ## to avoid strrep on megabytes of data.
+    ## If \n is in sep collection we need to enclose it in spaces in text
+    ## to avoid it being included in consecutive delim series
+    text = strrep (text, eol_char, [" " eol_char " "]);
+  else
+    mult_dlms_s1 = false;
+  endif
+
+  ## Split text string along delimiters
+  out = strsplit (text, sep, mult_dlms_s1);
+  ## In case of trailing delimiter, strip stray last empty word
+  if (!isempty (out) && any (sep == text(end)))
+    out(end) = [];
+  endif
+
+  ## Empty cells converted to empty cellstrings.
+  out(cellfun ("isempty", out)) = {""};
+
 endfunction
 
+
 %!test
 %! [a, b] = strread ("1 2", "%f%f");
-%! assert (a == 1 && b == 2);
-
-%!test
-%! str = "# comment\n# comment\n1 2 3";
-%! [a, b] = strread (str, '%d %s', 'commentstyle', 'shell');
-%! assert (a, [1; 3]);
-%! assert (b, {"2"; ""});
+%! assert (a, 1);
+%! assert (b, 2);
 
 %!test
 %! str = '';
 %! a = rand (10, 1);
-%! b = char (round (65 + 20 * rand (10, 1)));
+%! b = char (randi ([65, 85], 10, 1));
 %! for k = 1:10
-%!   str = sprintf ('%s %.6f %s\n', str, a (k), b (k));
+%!   str = sprintf ('%s %.6f %s\n', str, a(k), b(k));
 %! endfor
 %! [aa, bb] = strread (str, '%f %s');
-%! assert (a, aa, 1e-5);
+%! assert (a, aa, 1e-6);
 %! assert (cellstr (b), bb);
 
 %!test
 %! str = '';
 %! a = rand (10, 1);
-%! b = char (round (65 + 20 * rand (10, 1)));
+%! b = char (randi ([65, 85], 10, 1));
 %! for k = 1:10
-%!   str = sprintf ('%s %.6f %s\n', str, a (k), b (k));
+%!   str = sprintf ('%s %.6f %s\n', str, a(k), b(k));
 %! endfor
 %! aa = strread (str, '%f %*s');
-%! assert (a, aa, 1e-5);
+%! assert (a, aa, 1e-6);
 
 %!test
 %! str = sprintf ('/* this is\nacomment*/ 1 2 3');
@@ -283,6 +721,12 @@
 %! assert (a, [1; 2; 3]);
 
 %!test
+%! str = "# comment\n# comment\n1 2 3";
+%! [a, b] = strread (str, '%n %s', 'commentstyle', 'shell', 'endofline', "\n");
+%! assert (a, [1; 3]);
+%! assert (b, {"2"});
+
+%!test
 %! str = sprintf ("Tom 100 miles/hr\nDick 90 miles/hr\nHarry 80 miles/hr");
 %! fmt = "%s %f miles/hr";
 %! c = cell (1, 2);
@@ -294,3 +738,65 @@
 %! a = strread ("a b c, d e, , f", "%s", "delimiter", ",");
 %! assert (a, {"a b c"; "d e"; ""; "f"});
 
+%!test
+%! # Bug #33536
+%! [a, b, c] = strread ("1,,2", "%s%s%s", "delimiter", ",");
+%! assert (a{1}, '1');
+%! assert (b{1}, '');
+%! assert (c{1}, '2');
+
+%!test
+%! # Bug #33536
+%! a = strread ("[SomeText]", "[%s", "delimiter", "]");
+%! assert (a{1}, "SomeText");
+
+%!test
+%! dat = "Data file.\r\n=  =  =  =  =\r\nCOMPANY    : <Company name>\r\n";
+%! a = strread (dat, "%s", 'delimiter', "\n", 'whitespace', '', 'endofline', "\r\n");
+%! assert (a{2}, "=  =  =  =  =");
+%! assert (double (a{3}(end-5:end)), [32 110 97 109 101 62]);
+
+%!test
+%! [a, b, c, d] = strread ("1,2,3,,5,6", "%d%f%d%f", 'delimiter', ',');
+%! assert (c, int32 (3));
+%! assert (d, NaN);
+
+%!test
+%! [a, b, c, d] = strread ("1,2,3,,5,6\n", "%d%d%f%d", 'delimiter', ',');
+%! assert (c, [3; NaN]);
+%! assert (d, int32 ([0; 0]));
+
+%!test
+%! # Default format (= %f)
+%1 [a, b, c] = strread ("0.12 0.234 0.3567");
+%1 assert (a, 0.12);
+%1 assert (b, 0.234);
+%1 assert (c, 0.3567);
+
+%!test
+%! [a, b] = strread('0.41 8.24 3.57 6.24 9.27', "%f%f", 2, 'delimiter', ' ');
+%1 assert (a, [0.41; 3.57]);
+
+%!test
+%! # TreatAsEmpty
+%! [a, b, c, d] = strread ("1,2,3,NN,5,6\n", "%d%d%d%f", 'delimiter', ',', 'TreatAsEmpty', 'NN');
+%! assert (c, int32 ([3; 0]));
+%! assert (d, [NaN; NaN]);
+
+%!test
+%! # No delimiters at all besides EOL.  Plain reading numbers & strings
+%! str = "Text1Text2Text\nText398Text4Text\nText57Text";
+%! c = textscan (str, "Text%dText%1sText");
+%! assert (c{1}, int32 ([1; 398; 57]));
+%! assert (c{2}(1:2), {'2'; '4'});
+%! assert (isempty (c{2}{3}), true);
+
+%% MultipleDelimsAsOne
+%!test
+%! str = "11, 12, 13,, 15\n21,, 23, 24, 25\n,, 33, 34, 35";
+%! [a b c d] = strread (str, "%f %f %f %f", 'delimiter', ',', 'multipledelimsasone', 1, 'endofline', "\n");
+%! assert (a', [11, 21, NaN]);
+%! assert (b', [12, 23, 33]);
+%! assert (c', [13, 24, 34]);
+%! assert (d', [15, 25, 35]);
+
--- a/scripts/io/textread.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/io/textread.m	Tue Sep 20 15:38:24 2011 -0400
@@ -19,30 +19,43 @@
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {[@var{a}, @dots{}] =} textread (@var{filename})
 ## @deftypefnx {Function File} {[@var{a}, @dots{}] =} textread (@var{filename}, @var{format})
+## @deftypefnx {Function File} {[@var{a}, @dots{}] =} textread (@var{filename}, @var{format}, @var{n})
 ## @deftypefnx {Function File} {[@var{a}, @dots{}] =} textread (@var{filename}, @var{format}, @var{prop1}, @var{value1}, @dots{})
+## @deftypefnx {Function File} {[@var{a}, @dots{}] =} textread (@var{filename}, @var{format}, @var{n}, @var{prop1}, @var{value1}, @dots{})
 ## Read data from a text file.
 ##
 ## The file @var{filename} is read and parsed according to @var{format}.  The
 ## function behaves like @code{strread} except it works by parsing a file
-## instead
-## of a string.  See the documentation of @code{strread} for details.
+## instead of a string.  See the documentation of @code{strread} for details.
+##
 ## In addition to the options supported by @code{strread}, this function
-## supports one more:
+## supports two more:
+##
 ## @itemize
 ## @item "headerlines":
+## The first @var{value} number of lines of @var{filename} are skipped.
+##
+## @item "endofline":
+## Specify a single character or "\r\n".  If no value is given, it will be
+## inferred from the file.  If set to "" (empty string) EOLs are ignored as
+## delimiters.
 ## @end itemize
-## The first @var{value} number of lines of @var{str} are skipped.
-## @seealso{strread, load, dlmread, fscanf}
+##
+## The optional input @var{n} specifes the number of times to use
+## @var{format} when parsing, i.e., the format repeat count.
+##
+## @seealso{strread, load, dlmread, fscanf, textscan}
 ## @end deftypefn
 
 function varargout = textread (filename, format = "%f", varargin)
+
   ## Check input
   if (nargin < 1)
     print_usage ();
   endif
 
-  if (!ischar (filename) || !ischar (format))
-    error ("textread: first and second input arguments must be strings");
+  if (! ischar (filename) || ! ischar (format))
+    error ("textread: FILENAME and FORMAT arguments must be strings");
   endif
 
   ## Read file
@@ -51,21 +64,85 @@
     error ("textread: could not open '%s' for reading", filename);
   endif
 
-  ## Maybe skip header lines
+  ## Skip header lines if requested
   headerlines = find (strcmpi (varargin, "headerlines"), 1);
-  if (! isempty (headerlines))
-    hdr_lines = floor (varargin{headerlines + 1});
-    ## Beware of zero valued headerline, fskipl will count lines to EOF then
-    if (hdr_lines > 0)
-      fskipl (fid, hdr_lines);
-    endif
+  ## Beware of zero valued headerline, fskipl would skip to EOF
+  if (! isempty (headerlines) && (varargin{headerlines + 1} > 0))
+    fskipl (fid, varargin{headerlines + 1});
     varargin(headerlines:headerlines+1) = [];
   endif
 
-  str = fread (fid, "char=>char").';
+  if (nargin > 2 && isnumeric (varargin{1}))
+    nlines = varargin{1};
+  else
+    nlines = Inf;
+  endif
+
+  if (isfinite (nlines) && (nlines >= 0))
+    str = tmp_str = "";
+    n = 0;
+    ## FIXME: Can this be done without slow loop?
+    while (ischar (tmp_str) && n++ <= nlines)
+      str = strcat (str, tmp_str);
+      tmp_str = fgets (fid);
+    endwhile
+  else
+    str = fread (fid, "char=>char").';
+  endif
   fclose (fid);
 
+  if (isempty (str))
+    warning ("textread: empty file");
+    return;
+  endif
+
+  endofline = find (strcmpi (varargin, "endofline"), 1);
+  if (! isempty (endofline))
+    ## 'endofline' option set by user.
+    if (! ischar (varargin{endofline + 1}));
+      error ("textread: character value required for EndOfLine");
+    endif
+  else
+    ## Determine EOL from file.  Search for EOL candidates in first 3000 chars
+    eol_srch_len = min (length (str), 3000);
+    ## First try DOS (CRLF)
+    if (! isempty (findstr ("\r\n", str(1 : eol_srch_len))))
+      eol_char = "\r\n";
+    ## Perhaps old Macintosh? (CR)
+    elseif (! isempty (findstr ("\r", str(1 : eol_srch_len))))
+      eol_char = "\r";
+    ## Otherwise, use plain UNIX (LF)
+    else
+      eol_char = "\n";
+    endif
+    ## Set up default endofline param value
+    varargin(end+1:end+2) = {'endofline', eol_char};
+  endif
+
+  ## Set up default whitespace param value if needed
+  if (isempty (find (strcmpi ('whitespace', varargin))))
+    varargin(end+1:end+2) = {'whitespace', " \b\t"};
+  endif
+
   ## Call strread to make it do the real work
   [varargout{1:max (nargout, 1)}] = strread (str, format, varargin {:});
 
 endfunction
+
+
+%!test
+%! f = tmpnam();
+%! d = rand (5, 3);
+%! dlmwrite (f, d, 'precision', '%5.2f');
+%! [a, b, c] = textread (f, "%f %f %f", "delimiter", ",", "headerlines", 3);
+%! unlink(f);
+%! assert (a, d(4:5, 1), 1e-2);
+%! assert (b, d(4:5, 2), 1e-2);
+%! assert (c, d(4:5, 3), 1e-2);
+
+%% Test input validation
+%!error textread ()
+%!error textread (1)
+%!error <arguments must be strings> textread (1, '%f')
+%!error <arguments must be strings> textread ("fname", 1)
+
--- a/scripts/io/textscan.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/io/textscan.m	Tue Sep 20 15:38:24 2011 -0400
@@ -22,23 +22,40 @@
 ## @deftypefnx {Function File} {@var{C} =} textscan (@var{fid}, @var{format}, @var{param}, @var{value}, @dots{})
 ## @deftypefnx {Function File} {@var{C} =} textscan (@var{fid}, @var{format}, @var{n}, @var{param}, @var{value}, @dots{})
 ## @deftypefnx {Function File} {@var{C} =} textscan (@var{str}, @dots{})
-## @deftypefnx {Function File} {[@var{C}, @var{position}] =} textscan (@dots{})
-## Read data from a text file.
+## @deftypefnx {Function File} {[@var{C}, @var{position}] =} textscan (@var{fid}, @dots{})
+## Read data from a text file or string.
 ##
 ## The file associated with @var{fid} is read and parsed according to
 ## @var{format}.  The function behaves like @code{strread} except it works by
 ## parsing a file instead of a string.  See the documentation of
-## @code{strread} for details.  In addition to the options supported by
-## @code{strread}, this function supports one more:
+## @code{strread} for details.
+##
+## In addition to the options supported by
+## @code{strread}, this function supports a few more:
+##
 ## @itemize
+## @item "collectoutput":
+## A value of 1 or true instructs textscan to concatenate consecutive columns
+## of the same class in the output cell array.  A value of 0 or false (default)
+## leaves output in distinct columns.
+##
+## @item "endofline":
+## Specify "\r", "\n" or "\r\n" (for CR, LF, or CRLF).  If no value is given,
+## it will be inferred from the file.  If set to "" (empty string) EOLs are
+## ignored as delimiters and added to whitespace.
+##
 ## @item "headerlines":
+## The first @var{value} number of lines of @var{fid} are skipped.
+##
+## @item "returnonerror":
+## If set to numerical 1 or true (default), return normally when read errors
+## have been encountered.  If set to 0 or false, return an error and no data.
 ## @end itemize
-## The first @var{value} number of lines of @var{str} are skipped.
 ##
-## The optional input, @var{n}, specifes the number of lines to be read from
-## the file, associated with @var{fid}.
+## The optional input @var{n} specifes the number of times to use
+## @var{format} when parsing, i.e., the format repeat count.
 ##
-## The output, @var{C}, is a cell array whose length is given by the number
+## The output @var{C} is a cell array whose length is given by the number
 ## of format specifiers.
 ##
 ## The second output, @var{position}, provides the position, in characters,
@@ -47,89 +64,208 @@
 ## @seealso{dlmread, fscanf, load, strread, textread}
 ## @end deftypefn
 
-function [C, p] = textscan (fid, format, varargin)
+function [C, position] = textscan (fid, format = "%f", varargin)
 
   ## Check input
   if (nargin < 1)
     print_usage ();
-  elseif (nargin == 1 || isempty (format))
+  endif
+
+  if (isempty (format))
     format = "%f";
   endif
 
-  if (nargin > 2 && isnumeric (varargin{1}))
-    nlines = varargin{1};
-    args = varargin(2:end);
+  if (! (isa (fid, "double") && fid > 0) && ! ischar (fid))
+    error ("textscan: first argument must be a file id or character string");
+  endif
+
+  if (! ischar (format))
+    error ("textscan: FORMAT must be a string");
+  endif
+
+  args = varargin;
+  if (nargin > 2 && isnumeric (args{1}))
+    nlines = args{1};
   else
     nlines = Inf;
-    args = varargin;
   endif
 
   if (! any (strcmpi (args, "emptyvalue")))
     ## Matlab returns NaNs for missing values
-    args{end+1} = "emptyvalue";
-    args{end+1} = NaN;
+    args(end+1:end+2) = {'emptyvalue', NaN};
+  endif
+
+  ## Check default parameter values that differ for strread & textread
+
+  ipos = find (strcmpi (args, "whitespace"));
+  if (isempty (ipos))
+    ## Matlab default whitespace = " \b\t"
+    args(end+1:end+2) = {'whitespace', " \b\t"};
+    whitespace = " \b\t";
+  else
+    ## Check if there's at least one string format specifier
+    fmt = strrep (format, "%", " %");
+    fmt = regexp (fmt, '[^ ]+', 'match');
+    fmt = strtrim (fmt(strmatch ("%", fmt)))
+    has_str_fmt = all (cellfun ("isempty", strfind (strtrim (fmt(strmatch ("%", fmt))), 's')));
+    ## If there is a format, AND whitespace value = empty,
+    ## don't add a space (char(32)) to whitespace
+    if (! (isempty (args{ipos+1}) &&  has_str_fmt))
+      args{ipos+1} = unique ([" ", whitespace]);
+    endif
+  endif
+
+  if (! any (strcmpi (args, "delimiter")))
+    ## Matlab says default delimiter = whitespace.
+    ## strread() will pick this up further
+    args(end+1:end+2) = {'delimiter', ""};
+  endif
+
+  collop = false;
+  ipos = find (strcmpi (args, "collectoutput"));
+  if (! isempty (ipos))
+    ## Search & concatenate consecutive columns of same class requested
+    if (isscalar (args{ipos+1})
+        && (islogical (args{ipos+1}) || isnumeric (args{ipos+1})))
+      collop = args{ipos+1};
+    else
+      warning ("textscan: illegal value for CollectOutput parameter - ignored");
+    endif
+    ## Remove argument before call to strread() below
+    args(ipos:ipos+1) = [];
+  endif
+
+  if (any (strcmpi (args, "returnonerror")))
+    ## Because of the way strread() reads data (columnwise) this parameter
+    ## can't be neatly implemented.  strread() will pick it up anyway
+    warning ('textscan: ReturnOnError is not fully implemented');
+  else
+    ## Set default value (=true)
+    args(end+1:end+2) = {"returnonerror", 1};
+  endif
+
+  if (ischar (fid))
+    ## Read from a text string
+    if (nargout == 2)
+      error ("textscan: cannot provide position information for character input");
+    endif
+    str = fid;
+  else
+    ## Skip header lines if requested
+    headerlines = find (strcmpi (args, "headerlines"), 1);
+    ## Beware of zero valued headerline, fskipl would skip to EOF
+    if (! isempty (headerlines) && (args{headerlines + 1} > 0))
+      fskipl (fid, varargin{headerlines + 1});
+      args(headerlines:headerlines+1) = [];
+    endif
+    if (isfinite (nlines) && (nlines >= 0))
+      str = tmp_str = "";
+      n = 0;
+      ## FIXME: Can this be done without slow loop?
+      while (ischar (tmp_str) && n++ < nlines)
+        tmp_str = fgets (fid);
+        if (ischar (tmp_str))
+          str = strcat (str, tmp_str);
+        endif
+      endwhile
+    else
+      str = fread (fid, "char=>char").';
+    endif
   endif
 
-  if (isa (fid, "double") && fid > 0 || ischar (fid))
-    if (ischar (format))
-      if (ischar (fid))
-        if (nargout == 2)
-          error ("textscan: cannot provide position information for character input");
-        endif
-        str = fid;
-      else
-        ## Maybe skip header lines
-        headerlines = find (strcmpi (args, "headerlines"), 1);
-        if (! isempty (headerlines))
-          hdr_lines = floor (varargin{headerlines + 1});
-          ## Beware of zero valued headerline, fskipl will count lines to EOF
-          if (hdr_lines > 0)
-            fskipl (fid, hdr_lines);
-          endif
-        endif
-        if (isfinite (nlines))
-          str = "";
-          for n = 1:nlines
-            str = strcat (str, fgets (fid));
-          endfor
-            else
-          str = fread (fid, "char=>char").';
-        endif
+  ## Check for empty result
+  if (isempty (str))
+    warning ("textscan: no data read");
+    C = [];
+    return;
+  endif
+
+  ## Check value of 'endofline'.  String or file doesn't seem to matter
+  endofline = find (strcmpi (args, "endofline"), 1);
+  if (! isempty (endofline))
+    if (ischar (args{endofline + 1}))
+      eol_char = args{endofline + 1};
+      if (isempty (strmatch (eol_char, {"", "\n", "\r", "\r\n"}, 'exact')))
+        error ("textscan: illegal EndOfLine character value specified");
       endif
-
-      ## Determine the number of data fields
-      num_fields = numel (strfind (format, "%")) - ...
-                   numel (idx_star = strfind (format, "%*"));
-
-      ## Call strread to make it do the real work
-      C = cell (1, num_fields);
-      [C{:}] = strread (str, format, args{:});
-
-      if (ischar (fid) && isfinite (nlines))
-        C = cellfun (@(x) x(1:nlines), C, "uniformoutput", false);
-      endif
-
-      if (nargout == 2)
-        p = ftell (fid);
-      endif
-
     else
-      error ("textscan: FORMAT must be a valid specification");
+      error ("textscan: character value required for EndOfLine");
     endif
   else
-    error ("textscan: first argument must be a file id or character string");
+    ## Determine EOL from file.  Search for EOL candidates in first 3000 chars
+    eol_srch_len = min (length (str), 3000);
+    ## First try DOS (CRLF)
+    if (! isempty (findstr ("\r\n", str(1 : eol_srch_len))))
+      eol_char = "\r\n";
+    ## Perhaps old Macintosh? (CR)
+    elseif (! isempty (findstr ("\r", str(1 : eol_srch_len))))
+      eol_char = "\r";
+    ## Otherwise, use plain UNIX (LF)
+    else
+      eol_char = "\n";
+    endif
+    ## Set up the default endofline param value
+    args(end+1:end+2) = {'endofline', eol_char};
+  endif
+
+  ## Determine the number of data fields
+  num_fields = numel (strfind (format, "%")) - numel (strfind (format, "%*"));
+
+  ## Strip trailing EOL to avoid returning stray missing values (f. strread)
+  if (strcmp (str(end-length (eol_char) + 1 : end), eol_char));
+    str(end-length (eol_char) + 1 : end) = "";
+  endif
+
+  ## Call strread to make it do the real work
+  C = cell (1, num_fields);
+  [C{:}] = strread (str, format, args{:});
+
+  ## If requested, collect output columns of same class
+  if (collop)
+    C = colloutp (C);
   endif
 
+  if (nargout == 2)
+    position = ftell (fid);
+  endif
+
+endfunction
+
+
+## Collect consecutive columns of same class into one cell column
+function C = colloutp (C)
+
+  ## Start at rightmost column and work backwards to avoid ptr mixup
+  ii = numel (C);
+  while ii > 1
+    clss1 = class (C{ii});
+    jj = ii;
+    while  (jj > 1 && strcmp (clss1, class (C{jj - 1})))
+      ## Column to the left is still same class; check next column to the left
+      --jj;
+    endwhile
+    if (jj < ii)
+      ## Concatenate columns into current column
+      C{jj} = [C{jj : ii}];
+      ## Wipe concatenated columns to the right, resume search to the left
+      C(jj+1 : ii) = [];
+      ii = jj - 1;
+    else
+      ## No similar class in column to the left, search from there
+      --ii;
+    endif
+  endwhile
+
 endfunction
 
 %!test
 %! str = "1,  2,  3,  4\n 5,  ,  ,  8\n 9, 10, 11, 12";
 %! fmtstr = "%f %d %f %s";
 %! c = textscan (str, fmtstr, 2, "delimiter", ",", "emptyvalue", -Inf);
-%! assert (isequal (c{1}, [1;5]))
+%! assert (isequal (c{1}, [1;5]));
 %! assert (length (c{1}), 2);
-%! assert (iscellstr (c{4}))
-%! assert (isequal (c{3}, [3; -Inf]))
+%! assert (iscellstr (c{4}));
+%! assert (isequal (c{3}, [3; -Inf]));
 
 %!test
 %! b = [10:10:100];
@@ -137,7 +273,60 @@
 %! str = sprintf ("%g miles/hr = %g kilometers/hr\n", b);
 %! fmt = "%f miles/hr = %f kilometers/hr";
 %! c = textscan (str, fmt);
-%! assert (b(1,:)', c{1})
-%! assert (b(2,:)', c{2})
+%! assert (b(1,:)', c{1}, 1e-5);
+%! assert (b(2,:)', c{2}, 1e-5);
+
+#%!test
+#%! str = "13, 72, NA, str1, 25\r\n// Middle line\r\n36, na, 05, str3, 6";
+#%! a = textscan(str, '%d %n %f %s %n', 'delimiter', ',','treatAsEmpty', {'NA', 'na'},'commentStyle', '//');
+#%! assert (a{1}, int32([13; 36]));
+#%! assert (a{2}, [72; NaN]);
+#%! assert (a{3}, [NaN; 5]);
+#%! assert (a{4}, {"str1"; "str3"});
+#%! assert (a{5}, [25; 6]);
+
+%!test
+%! str = "Km:10 = hhhBjjj miles16hour\r\n";
+%! str = [str "Km:15 = hhhJjjj miles241hour\r\n"];
+%! str = [str "Km:2 = hhhRjjj miles3hour\r\n"];
+%! str = [str "Km:25 = hhhZ\r\n"];
+%! fmt = "Km:%d = hhh%1sjjj miles%dhour";
+%! a = textscan (str, fmt, 'delimiter', ' ');
+%! assert (a{1}', int32([10 15 2 25]));
+%! assert (a{2}', {'B' 'J' 'R' 'Z'});
+%! assert (a{3}', int32([16 241 3 0]));
+
+%% Test with default endofline parameter
+%!test
+%! c = textscan ("L1\nL2", "%s");
+%! assert (c{:}, {"L1"; "L2"});
 
+%% Test with endofline parameter set to '' (empty) - newline should be in word
+%!test
+%! c = textscan ("L1\nL2", "%s", 'endofline', '');
+%! assert (int8(c{:}{:}), int8([ 76,  49,  10,  76,  50 ]));
 
+%!test
+%! # No delimiters at all besides EOL.  Skip fields, even empty fields
+%! str = "Text1Text2Text\nTextText4Text\nText57Text";
+%! c = textscan (str, "Text%*dText%dText");
+%! assert (c{1}, int32 ([2; 4; 0]));
+
+%!test
+%% CollectOutput test
+%! b = [10:10:100];
+%! b = [b; 8*b/5; 8*b*1000/5];
+%! str = sprintf ("%g miles/hr = %g (%g) kilometers (meters)/hr\n", b);
+%! fmt = "%f miles%s %s %f (%f) kilometers %*s";
+%! c = textscan (str, fmt, 'collectoutput', 1);
+%! assert (size(c{3}), [10, 2]);
+%! assert (size(c{2}), [10, 2]);
+
+%% Test input validation
+%!error textscan ()
+%!error textscan (single (4))
+%!error textscan ({4})
+%!error <must be a string> textscan ("Hello World", 2)
+%!error <cannot provide position information> [C, pos] = textscan ("Hello World")
+%!error <character value required> textscan ("Hello World", '%s', 'EndOfLine', 3)
+
--- a/scripts/linear-algebra/commutation_matrix.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/linear-algebra/commutation_matrix.m	Tue Sep 20 15:38:24 2011 -0400
@@ -95,3 +95,25 @@
   endfor
 
 endfunction
+
+%!test
+%! c = commutation_matrix(1,1);
+%! assert(c,1);
+
+%!test
+%! A = rand(3,5);
+%! vc = vec(A);
+%! vr = vec(A');
+%! c = commutation_matrix(3,5);
+%! assert(c*vc,vr);
+
+%!test
+%! A = rand(4,6);
+%! vc = vec(A);
+%! vr = vec(A');
+%! c = commutation_matrix(4,6);
+%! assert(c*vc,vr);
+
+%!error commutation_matrix(0,0);
+%!error commutation_matrix(1,0);
+%!error commutation_matrix(0,1);
--- a/scripts/linear-algebra/cross.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/linear-algebra/cross.m	Tue Sep 20 15:38:24 2011 -0400
@@ -90,3 +90,26 @@
   endif
 
 endfunction
+
+%!test
+%! x = [1 0 0];
+%! y = [0 1 0];
+%! r = [0 0 1];
+%! assert(cross(x, y), r, 2e-8);
+
+%!test
+%! x = [1 2 3];
+%! y = [4 5 6];
+%! r = [(2*6-3*5) (3*4-1*6) (1*5-2*4)];
+%! assert(cross(x, y), r, 2e-8);
+
+%!test
+%! x = [1 0 0; 0 1 0; 0 0 1];
+%! y = [0 1 0; 0 0 1; 1 0 0];
+%! r = [0 0 1; 1 0 0; 0 1 0];
+%! assert(cross(x, y, 2), r, 2e-8);
+%! assert(cross(x, y, 1), -r, 2e-8);
+
+%!error cross(0,0);
+%!error cross();
+
--- a/scripts/linear-algebra/duplication_matrix.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/linear-algebra/duplication_matrix.m	Tue Sep 20 15:38:24 2011 -0400
@@ -86,3 +86,35 @@
   endfor
 
 endfunction
+
+%!test
+%! N = 2;
+%! A = rand(N);
+%! B = A * A';
+%! C = A + A';
+%! D = duplication_matrix (N);
+%! assert (D * vech (B), vec (B), 1e-6);
+%! assert (D * vech (C), vec (C), 1e-6);
+
+%!test
+%! N = 3;
+%! A = rand(N);
+%! B = A * A';
+%! C = A + A';
+%! D = duplication_matrix (N);
+%! assert (D * vech (B), vec (B), 1e-6);
+%! assert (D * vech (C), vec (C), 1e-6);
+
+%!test
+%! N = 4;
+%! A = rand(N);
+%! B = A * A';
+%! C = A + A';
+%! D = duplication_matrix (N);
+%! assert (D * vech (B), vec (B), 1e-6);
+%! assert (D * vech (C), vec (C), 1e-6);
+
+%!error duplication_matrix ();
+%!error duplication_matrix (0.5);
+%!error duplication_matrix (-1);
+%!error duplication_matrix (ones(1,4));
--- a/scripts/linear-algebra/gmres.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,214 +0,0 @@
-## Copyright (C) 2009-2011 Carlo de Falco
-##  
-## 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn  {Function File} {@var{x} =} gmres (@var{A}, @var{b}, @var{m}, @var{rtol}, @var{maxit}, @var{M1}, @var{M2}, @var{x0})
-## @deftypefnx {Function File} {@var{x} =} gmres (@var{A}, @var{b}, @var{m}, @var{rtol}, @var{maxit}, @var{P})
-## @deftypefnx {Function File} {[@var{x}, @var{flag}, @var{relres}, @var{iter}, @var{resvec}] =} gmres (@dots{})
-## Solve @code{A x = b} using the Preconditioned GMRES iterative method
-## with restart, a.k.a. PGMRES(m).
-##
-## @itemize @minus
-## @item @var{rtol} is the relative tolerance,
-## if not given or set to [] the default value 1e-6 is used.
-##
-## @item @var{maxit} is the maximum number of outer iterations,
-## if not given or set to [] the default value
-## @code{min (10, numel (b) / restart)} is used.
-##
-## @item @var{x0} is the initial guess,
-## if not given or set to [] the default value @code{zeros(size (b))} is used.
-##
-## @item @var{m} is the restart parameter,
-## if not given or set to [] the default value @code{numel (b)} is used.
-## @end itemize
-##
-## Argument @var{A} can be passed as a matrix, function handle, or
-## inline function @code{f} such that @code{f(x) = A*x}.
-##
-## The preconditioner @var{P} is given as @code{P = M1 * M2}.
-## Both @var{M1} and @var{M2} can be passed as a matrix, function handle, or
-## inline function @code{g} such that @code{g(x) = M1\x} or @code{g(x) = M2\x}.
-##
-## Besides the vector @var{x}, additional outputs are:
-##
-## @itemize @minus
-## @item @var{flag} indicates the exit status:
-##
-## @table @asis
-##   @item 0 : iteration converged to within the specified tolerance
-##
-##   @item 1 : maximum number of iterations exceeded
-##
-##   @item 2 : unused, but skipped for compatibility
-##
-##   @item 3 : algorithm reached stagnation
-## @end table
-##
-## @item @var{relres} is the final value of the relative residual.
-##
-## @item @var{iter} is a vector containing the number of outer iterations and
-## total iterations performed.
-##
-## @item @var{resvec} is a vector containing the relative residual at each
-## iteration.
-## @end itemize
-##
-## @seealso{pcg, cgs, bicgstab}
-## @end deftypefn
-
-function [x, flag, prec_res_norm, itcnt] = gmres (A, b, restart, rtol, maxit, M1, M2, x0)
-
-  if (nargin < 2 || nargin > 8)
-    print_usage ();    
-  endif
-      
-  if (ischar (A))
-    Ax = str2func (A);
-  elseif (ismatrix (A))
-    Ax = @(x) A*x;
-  elseif (isa (A, "function_handle"))
-    Ax = A;
-  else
-    error ("gmres: A must be a function or matrix");
-  endif
-
-  if (nargin < 3 || isempty (restart))
-    restart = rows (b);
-  endif
-
-  if (nargin < 4 || isempty (rtol))
-    rtol = 1e-6;
-  endif
-
-  if (nargin < 5 || isempty (maxit))
-    maxit = min (rows (b)/restart, 10);
-  endif
-
-  if (nargin < 6 || isempty (M1))
-    M1m1x = @(x) x;
-  elseif (ischar (M1))
-    M1m1x = str2func (M1);
-  elseif (ismatrix (M1))
-    M1m1x = @(x) M1 \ x;
-  elseif (isa (M1, "function_handle"))
-    M1m1x = M1;
-  else
-    error ("gmres: preconditioner M1 must be a function or matrix");
-  endif
-  
-  if (nargin < 7 || isempty (M2))
-    M2m1x = @(x) x;
-  elseif (ischar (M2))
-    M2m1x = str2func (M2);
-  elseif (ismatrix (M2))
-    M2m1x = @(x) M2 \ x;
-  elseif (isa (M2, "function_handle"))
-    M2m1x = M2;
-  else
-    error ("gmres: preconditioner M2 must be a function or matrix");
-  endif
-
-  Pm1x = @(x) M2m1x (M1m1x (x));
-
-  if (nargin < 8 || isempty (x0))
-    x0 = zeros (size (b));
-  endif
-
-  x_old = x0; 
-  x = x_old;
-  prec_res = Pm1x (b - Ax (x_old));
-  prec_res_norm = norm (prec_res, 2);
-  
-  B = zeros (restart + 1, 1);
-  V = zeros (rows (x), restart);
-  H = zeros (restart + 1, restart);
-
-  ## begin loop
-  iter = 1;
-  restart_it  = restart + 1; 
-  resids      = zeros (maxit, 1);
-  resids(1)   = prec_res_norm;
-  prec_b_norm = norm (Pm1x (b), 2);
-  flag        = 1;
-
-  while ((iter <= maxit * restart) && (prec_res_norm > rtol * prec_b_norm))
-  
-    ## restart
-    if (restart_it > restart)
-      restart_it = 1;
-      x_old = x;	      
-      prec_res = Pm1x (b - Ax (x_old));
-      prec_res_norm = norm (prec_res, 2);
-      B(1) = prec_res_norm;
-      H(:) = 0;
-      V(:, 1) = prec_res / prec_res_norm;
-    endif  
-    
-    ## basic iteration
-    tmp = Pm1x (Ax (V(:, restart_it)));
-    [V(:,restart_it+1), H(1:restart_it+1, restart_it)] = mgorth (tmp, V(:,1:restart_it));
-    
-    Y = (H(1:restart_it+1, 1:restart_it) \ B (1:restart_it+1));
-	      
-    little_res = B(1:restart_it+1) - H(1:restart_it+1, 1:restart_it) * Y(1:restart_it);
-    prec_res_norm = norm (little_res, 2);
-	      
-    x = x_old + V(:, 1:restart_it) * Y(1:restart_it);
-    
-    resids(iter) = prec_res_norm ;
-    if (norm (x - x_old, inf) <= eps)
-      flag = 3;
-      break
-    endif
-
-    restart_it++ ; iter++;
-  endwhile
-
-  if (prec_res_norm > rtol * prec_b_norm)
-    flag = 0;
-  endif
-
-  resids = resids(1:iter-1);
-  itcnt = [floor(maxit/restart), rem(maxit, restart)];
-endfunction
-
-
-%!shared A, b, dim
-%! dim = 100;
-%!test
-%! A = spdiags ([-ones(dim,1) 2*ones(dim,1) ones(dim,1)], [-1:1], dim, dim);
-%! b = ones(dim, 1); 
-%! x = gmres (A, b, 10, 1e-10, dim, @(x) x./diag(A), [],  b);
-%! assert(x, A\b, 1e-9*norm(x,inf));
-%!
-%!test
-%! x = gmres (A, b, dim, 1e-10, 1e4, @(x) diag(diag(A))\x, [],  b);  
-%! assert(x, A\b, 1e-7*norm(x,inf));
-%!
-%!test
-%! A = spdiags ([[1./(2:2:2*(dim-1)) 0]; 1./(1:2:2*dim-1); [0 1./(2:2:2*(dim-1))]]', -1:1, dim, dim);
-%! A = A'*A;
-%! b = rand (dim, 1);
-%! [x, resids] = gmres (@(x) A*x, b, dim, 1e-10, dim, @(x) x./diag(A), [],  []);
-%! assert(x, A\b, 1e-9*norm(x,inf))
-%! x = gmres (@(x) A*x, b, dim, 1e-10, 1e6, @(x) diag(diag(A))\x, [],  []);
-%! assert(x, A\b, 1e-9*norm(x,inf));
-%!test
-%! x =  gmres (@(x) A*x, b, dim, 1e-10, 1e6, @(x) x./diag(A), [],  []);
-%! assert(x, A\b, 1e-7*norm(x,inf));
--- a/scripts/linear-algebra/housh.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/linear-algebra/housh.m	Tue Sep 20 15:38:24 2011 -0400
@@ -23,8 +23,8 @@
 ##
 ## @example
 ## @group
-## (I - beta*housv*housv')x =  norm(x)*e(j) if x(1) < 0,
-## (I - beta*housv*housv')x = -norm(x)*e(j) if x(1) >= 0
+## (I - beta*housv*housv')x =  norm(x)*e(j) if x(j) < 0,
+## (I - beta*housv*housv')x = -norm(x)*e(j) if x(j) >= 0
 ## @end group
 ## @end example
 ##
@@ -91,3 +91,43 @@
   endif
 
 endfunction
+
+%!test
+%! x = [1 2 3]';
+%! j = 3;
+%! [hv, b, z] = housh(x, j, 0);
+%! r = (eye(3) - b*hv*hv') * x;
+%! d = - norm(x) * [0 0 1]';
+%! assert(r, d, 2e-8);
+%! assert(z, 0, 2e-8);
+
+%!test
+%! x = [7 -3 1]';
+%! j = 2;
+%! [hv, b, z] = housh(x, j, 0);
+%! r = (eye(3) - b*hv*hv') * x;
+%! d = norm(x) * [0 1 0]';
+%! assert(r, d, 2e-8);
+%! assert(z, 0, 2e-8);
+
+%!test
+%! x = [1 0 0]';
+%! j = 1;
+%! [hv, b, z] = housh(x, j, 10);
+%! r = (eye(3) - b*hv*hv') * x;
+%! d = norm(x) * [1 0 0]';
+%! assert(r, d, 2e-8);
+%! assert(z, 1, 2e-8);
+
+%!test
+%! x = [5 0 4 1]';
+%! j = 2;
+%! [hv, b, z] = housh(x, j, 0);
+%! r = (eye(4) - b*hv*hv') * x;
+%! d = - norm(x) * [0 1 0 0]';
+%! assert(r, d, 2e-8);
+%! assert(z, 0, 2e-8);
+
+%!error housh([0]);
+%!error housh();
+
--- a/scripts/linear-algebra/isdefinite.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/linear-algebra/isdefinite.m	Tue Sep 20 15:38:24 2011 -0400
@@ -63,3 +63,22 @@
   endif
 
 endfunction
+
+%!test
+%! A = [-1 0; 0 -1];
+%! assert (isdefinite (A), -1)
+
+%!test
+%! A = [1 0; 0 1];
+%! assert (isdefinite (A), 1)
+
+%!test
+%! A = [2 -1 0; -1 2 -1; 0 -1 2];
+%! assert (isdefinite (A), 1)
+
+%!test
+%! A = [1 0; 0 0];
+%! assert (isdefinite (A), 0)
+
+%!error isdefinite ()
+%!error isdefinite ([1 2; 3 4])
\ No newline at end of file
--- a/scripts/linear-algebra/module.mk	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/linear-algebra/module.mk	Tue Sep 20 15:38:24 2011 -0400
@@ -7,7 +7,6 @@
   linear-algebra/cross.m \
   linear-algebra/duplication_matrix.m \
   linear-algebra/expm.m \
-  linear-algebra/gmres.m \
   linear-algebra/housh.m \
   linear-algebra/isdefinite.m \
   linear-algebra/ishermitian.m \
--- a/scripts/linear-algebra/null.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/linear-algebra/null.m	Tue Sep 20 15:38:24 2011 -0400
@@ -77,3 +77,35 @@
   endif
 
 endfunction
+
+%!test
+%! A = 0;
+%! assert(null(A), 1);
+
+%!test
+%! A = 1;
+%! assert(null(A), zeros(1,0))
+
+%!test
+%! A = [1 0; 0 1];
+%! assert(null(A), zeros(2,0));
+
+%!test
+%! A = [1 0; 1 0];
+%! assert(null(A), [0 1]')
+
+%!test
+%! A = [1 1; 0 0];
+%! assert(null(A), [-1/sqrt(2) 1/sqrt(2)]', eps)
+
+%!test
+%! tol = 1e-4;
+%! A = [1 0; 0 tol-eps];
+%! assert(null(A,tol), [0 1]')
+
+%!test
+%! tol = 1e-4;
+%! A = [1 0; 0 tol+eps];
+%! assert(null(A,tol), zeros(2,0));
+
+%!error null()
--- a/scripts/linear-algebra/orth.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/linear-algebra/orth.m	Tue Sep 20 15:38:24 2011 -0400
@@ -39,6 +39,11 @@
 
   if (nargin == 1 || nargin == 2)
 
+    if (isempty (A))
+      retval = [];
+      return;
+    endif
+
     [U, S, V] = svd (A);
 
     [rows, cols] = size (A);
@@ -74,3 +79,12 @@
   endif
 
 endfunction
+
+%!test
+%! for ii=1:20
+%!   A = rand (10, 10);
+%!   V = orth (A);
+%!   if (det (A) != 0)
+%!     assert (V'*V, eye (10), 100*eps)
+%!   endif
+%! endfor
--- a/scripts/linear-algebra/planerot.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/linear-algebra/planerot.m	Tue Sep 20 15:38:24 2011 -0400
@@ -34,3 +34,14 @@
   G = givens (x(1), x(2));
   y = G * x(:);
 endfunction
+
+%!test
+%! x = [3 4];
+%! [g y] = planerot(x);
+%! assert(g - [x(1) x(2); -x(2) x(1)] / sqrt(x(1)^2 + x(2)^2), zeros(2), 2e-8);
+%! assert(y(2), 0, 2e-8);
+
+%!error planerot([0]);
+%!error planerot([0 0 0]);
+%!error planerot();
+
--- a/scripts/linear-algebra/qzhess.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/linear-algebra/qzhess.m	Tue Sep 20 15:38:24 2011 -0400
@@ -90,3 +90,52 @@
   endfor
 
 endfunction
+
+%!test
+%! a = [1 2 1 3;
+%!      2 5 3 2;
+%!      5 5 1 0;
+%!      4 0 3 2];
+%! b = [0 4 2 1;
+%!      2 3 1 1;
+%!      1 0 2 1;
+%!      2 5 3 2];
+%! mask = [0 0 0 0;
+%!         0 0 0 0;
+%!         1 0 0 0;
+%!         1 1 0 0];
+%! [aa, bb, q, z] = qzhess(a, b);
+%! assert(inv(q) - q', zeros(4), 2e-8);
+%! assert(inv(z) - z', zeros(4), 2e-8);
+%! assert(q * a * z, aa, 2e-8);
+%! assert(aa .* mask, zeros(4), 2e-8);
+%! assert(q * b * z, bb, 2e-8);
+%! assert(bb .* mask, zeros(4), 2e-8);
+
+%!test
+%! a = [1 2 3 4 5;
+%!      3 2 3 1 0;
+%!      4 3 2 1 1;
+%!      0 1 0 1 0;
+%!      3 2 1 0 5];
+%! b = [5 0 4 0 1;
+%!      1 1 1 2 5;
+%!      0 3 2 1 0;
+%!      4 3 0 3 5;
+%!      2 1 2 1 3];
+%! mask = [0 0 0 0 0;
+%!         0 0 0 0 0;
+%!         1 0 0 0 0;
+%!         1 1 0 0 0;
+%!         1 1 1 0 0];
+%! [aa, bb, q, z] = qzhess(a, b);
+%! assert(inv(q) - q', zeros(5), 2e-8);
+%! assert(inv(z) - z', zeros(5), 2e-8);
+%! assert(q * a * z, aa, 2e-8);
+%! assert(aa .* mask, zeros(5), 2e-8);
+%! assert(q * b * z, bb, 2e-8);
+%! assert(bb .* mask, zeros(5), 2e-8);
+
+%!error qzhess([0]);
+%!error qzhess();
+
--- a/scripts/linear-algebra/rank.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/linear-algebra/rank.m	Tue Sep 20 15:38:24 2011 -0400
@@ -58,3 +58,54 @@
   retval = sum (sigma > tolerance);
 
 endfunction
+
+%!test
+%! A = [1 2 3 4 5 6 7;
+%!      4 5 6 7 8 9 12;
+%!      1 2 3.1 4 5 6 7;
+%!      2 3 4 5 6 7 8;
+%!      3 4 5 6 7 8 9;
+%!      4 5 6 7 8 9 10;
+%!      5 6 7 8 9 10 11];
+%! assert(rank(A),4);
+
+%!test
+%! A = [1 2 3 4 5 6 7;
+%!      4 5 6 7 8 9 12;
+%!      1 2 3.0000001 4 5 6 7;
+%!      4 5 6 7 8 9 12.00001;
+%!      3 4 5 6 7 8 9;
+%!      4 5 6 7 8 9 10;
+%!      5 6 7 8 9 10 11];
+%! assert(rank(A),4);
+
+%!test
+%! A = [1 2 3 4 5 6 7;
+%!      4 5 6 7 8 9 12;
+%!      1 2 3 4 5 6 7;
+%!      4 5 6 7 8 9 12.00001;
+%!      3 4 5 6 7 8 9;
+%!      4 5 6 7 8 9 10;
+%!      5 6 7 8 9 10 11];
+%! assert(rank(A),3);
+
+%!test
+%! A = [1 2 3 4 5 6 7;
+%!      4 5 6 7 8 9 12;
+%!      1 2 3 4 5 6 7;
+%!      4 5 6 7 8 9 12;
+%!      3 4 5 6 7 8 9;
+%!      4 5 6 7 8 9 10;
+%!      5 6 7 8 9 10 11];
+%! assert(rank(A),3);
+
+%!test
+%! A = eye(100);
+%! assert(rank(A),100);
+
+%!test
+%! A = [1, 2, 3; 1, 2.001, 3; 1, 2, 3.0000001];
+%! assert(rank(A),3)
+%! assert(rank(A,0.0009),1)
+%! assert(rank(A,0.0006),2)
+%! assert(rank(A,0.00000002),3)
\ No newline at end of file
--- a/scripts/linear-algebra/rref.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/linear-algebra/rref.m	Tue Sep 20 15:38:24 2011 -0400
@@ -86,3 +86,43 @@
   k = find (used);
 
 endfunction
+
+%!test
+%! a = [1];
+%! [r k] = rref(a);
+%! assert(r, [1], 2e-8);
+%! assert(k, [1], 2e-8);
+
+%!test
+%! a = [1 3; 4 5];
+%! [r k] = rref(a);
+%! assert(rank(a), rank(r), 2e-8);
+%! assert(r, eye(2), 2e-8);
+%! assert(k == [1, 2] || k == [2, 1]);
+
+
+%!test
+%! a = [1 3; 4 5; 7 9];
+%! [r k] = rref(a);
+%! assert(rank(a), rank(r), 2e-8);
+%! assert(r, eye(3)(:,1:2), 2e-8);
+%! assert(k, [1 2], 2e-8);
+
+%!test
+%! a = [1 2 3; 2 4 6; 7 2 0];
+%! [r k] = rref(a);
+%! assert(rank(a), rank(r), 2e-8);
+%! assert(r, [1 0 (3-7/2); 0 1 (7/4); 0 0 0], 2e-8);
+%! assert(k, [1 2], 2e-8);
+
+%!test
+%! a = [1 2 1; 2 4 2.01; 2 4 2.1];
+%! tol = 0.02;
+%! [r k] = rref(a, tol);
+%! assert(rank(a, tol), rank(r, tol), 2e-8);
+%! tol = 0.2;
+%! [r k] = rref(a, tol);
+%! assert(rank(a, tol), rank(r, tol), 2e-8);
+
+%!error rref();
+
--- a/scripts/miscellaneous/ans.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/miscellaneous/ans.m	Tue Sep 20 15:38:24 2011 -0400
@@ -28,3 +28,7 @@
 ## @noindent
 ## is evaluated, the value returned by @code{ans} is 25.
 ## @end defvr
+
+## Mark file as being tested.  No real test needed for a documentation .m file
+%!assert (1)
+
--- a/scripts/miscellaneous/bincoeff.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/miscellaneous/bincoeff.m	Tue Sep 20 15:38:24 2011 -0400
@@ -68,46 +68,53 @@
     error ("bincoeff: N and K must be of common size or scalars");
   endif
 
-  sz = size (n);
-  b   = zeros (sz);
+  if (iscomplex (n) || iscomplex (k))
+    error ("bincoeff: N and K must not be complex");
+  endif
 
-  ind = (! (k >= 0) | (k != real (round (k))) | isnan (n));
-  b(ind) = NaN;
+  b = zeros (size (n));
 
-  ind = (k == 0);
-  b(ind) = 1;
+  ok = (k >= 0) & (k == fix (k)) & (! isnan (n));
+  b(! ok) = NaN;
 
-  ind = ((k > 0) & ((n == real (round (n))) & (n < 0)));
-  b(ind) = (-1) .^ k(ind) .* exp (gammaln (abs (n(ind)) + k(ind))
-                                  - gammaln (k(ind) + 1)
-                                  - gammaln (abs (n(ind))));
+  n_int = (n == fix (n));
+  idx = n_int & (n < 0) & ok;
+  b(idx) = (-1) .^ k(idx) .* exp (gammaln (abs (n(idx)) + k(idx))
+                                  - gammaln (k(idx) + 1)
+                                  - gammaln (abs (n(idx))));
 
-  ind = ((k > 0) & (n >= k));
-  b(ind) = exp (gammaln (n(ind) + 1)
-                - gammaln (k(ind) + 1)
-                - gammaln (n(ind) - k(ind) + 1));
+  idx = (n >= k) & ok;
+  b(idx) = exp (gammaln (n(idx) + 1)
+                - gammaln (k(idx) + 1)
+                - gammaln (n(idx) - k(idx) + 1));
 
-  ind = ((k > 0) & ((n != real (round (n))) & (n < k)));
-  b(ind) = (1/pi) * exp (gammaln (n(ind) + 1)
-                         - gammaln (k(ind) + 1)
-                         + gammaln (k(ind) - n(ind))
-                         + log (sin (pi * (n(ind) - k(ind) + 1))));
+  idx = (! n_int) & (n < k) & ok;
+  b(idx) = (1/pi) * exp (gammaln (n(idx) + 1)
+                         - gammaln (k(idx) + 1)
+                         + gammaln (k(idx) - n(idx))
+                         + log (sin (pi * (n(idx) - k(idx) + 1))));
 
   ## Clean up rounding errors.
-  ind = (n == round (n));
-  b(ind) = round (b(ind));
+  b(n_int) = round (b(n_int));
 
-  ind = (n != round (n));
-  b(ind) = real (b(ind));
+  idx = ! n_int;
+  b(idx) = real (b(idx));
 
 endfunction
 
-%!assert(bincoeff(4,2), 6)
-%!assert(bincoeff(2,4), 0)
-%!assert(bincoeff(0.4,2), -.12, 8*eps)
+
+%!assert(bincoeff (4, 2), 6)
+%!assert(bincoeff (2, 4), 0)
+%!assert(bincoeff (-4, 2), 10)
+%!assert(bincoeff (5, 2), 10)
+%!assert(bincoeff (50, 6), 15890700)
+%!assert(bincoeff (0.4, 2), -.12, 8*eps)
 
-%!assert(bincoeff (5, 2) == 10 && bincoeff (50, 6) == 15890700);
+%!assert(bincoeff ([4 NaN 4], [-1, 2, 2.5]), NaN (1, 3))
 
+%% Test input validation
 %!error bincoeff ();
+%!error bincoeff (1, 2, 3);
+%!error bincoeff (ones(3),ones(2))
+%!error bincoeff (ones(2),ones(3))
 
-%!error bincoeff (1, 2, 3);
--- a/scripts/miscellaneous/bug_report.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/miscellaneous/bug_report.m	Tue Sep 20 15:38:24 2011 -0400
@@ -43,3 +43,6 @@
   puts ("\n");
 
 endfunction
+
+## Mark file as being tested.  No real test needed for this function.
+%!assert (1)
--- a/scripts/miscellaneous/comma.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/miscellaneous/comma.m	Tue Sep 20 15:38:24 2011 -0400
@@ -21,3 +21,7 @@
 ## Array index, function argument, or command separator.
 ## @seealso{semicolon}
 ## @end deftypefn
+
+## Mark file as being tested.  No real test needed for a documentation .m file
+%!assert (1)
+
--- a/scripts/miscellaneous/computer.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/miscellaneous/computer.m	Tue Sep 20 15:38:24 2011 -0400
@@ -18,6 +18,7 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {[@var{c}, @var{maxsize}, @var{endian}] =} computer ()
+## @deftypefnx {Function File} {@var{arch} =} computer ("arch")
 ## Print or return a string of the form @var{cpu}-@var{vendor}-@var{os}
 ## that identifies the kind of computer Octave is running on.  If invoked
 ## with an output argument, the value is returned instead of printed.  For
@@ -39,42 +40,52 @@
 ## If three output arguments are requested, also return the byte order
 ## of the current system as a character (@code{"B"} for big-endian or
 ## @code{"L"} for little-endian).
+##
+## If the argument @code{"arch"} is specified, return a string
+## indicating the architecture of the computer on which Octave is
+## running.
 ## @end deftypefn
 
-function [c, maxsize, endian] = computer ()
-
-  if (nargin != 0)
-    warning ("computer: ignoring extra arguments");
-  endif
+function [c, maxsize, endian] = computer (a)
 
-  msg = octave_config_info ("canonical_host_type");
+  if (nargin == 1 && ischar (a) && strcmpi (a, "arch"))
+    tmp = strsplit (octave_config_info ("canonical_host_type"), "-");
+    if (numel (tmp) == 4)
+      c = sprintf ("%s-%s-%s", tmp{4}, tmp{3}, tmp{1});
+    else
+      c = sprintf ("%s-%s", tmp{3}, tmp{1});
+    endif
+  elseif (nargin == 0)
+    msg = octave_config_info ("canonical_host_type");
 
-  if (strcmp (msg, "unknown"))
-    msg = "Hi Dave, I'm a HAL-9000";
-  endif
+    if (strcmp (msg, "unknown"))
+      msg = "Hi Dave, I'm a HAL-9000";
+    endif
 
-  if (nargout == 0)
-    printf ("%s\n", msg);
-  else
-    c = msg;
-    if (strcmp (octave_config_info ("USE_64_BIT_IDX_T"), "true"))
-      maxsize = 2^63-1;
+    if (nargout == 0)
+      printf ("%s\n", msg);
     else
-      maxsize = 2^31-1;
+      c = msg;
+      if (strcmp (octave_config_info ("USE_64_BIT_IDX_T"), "true"))
+        maxsize = 2^63-1;
+      else
+        maxsize = 2^31-1;
+      endif
+      if (octave_config_info ("words_big_endian"))
+        endian = "B";
+      elseif (octave_config_info ("words_little_endian"))
+        endian = "L";
+      else
+        endian = "?";
+      endif
     endif
-    if (octave_config_info ("words_big_endian"))
-      endian = "B";
-    elseif (octave_config_info ("words_little_endian"))
-      endian = "L";
-    else
-      endian = "?";
-    endif
+  else
+    print_usage ();
   endif
 
 endfunction
 
 %!assert((ischar (computer ())
 %! && computer () == octave_config_info ("canonical_host_type")));
-
-%!warning a =computer(2);
-
+%!assert(ischar (computer ("arch")));
+%!error computer (2);
--- a/scripts/miscellaneous/edit.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/miscellaneous/edit.m	Tue Sep 20 15:38:24 2011 -0400
@@ -54,7 +54,7 @@
 ## filename.  If @file{name.ext} is not modifiable, it will be copied to
 ## @env{HOME} before editing.
 ##
-## @strong{WARNING!} You may need to clear name before the new definition
+## @strong{Warning:} You may need to clear name before the new definition
 ## is available.  If you are editing a .cc file, you will need
 ## to mkoctfile @file{name.cc} before the definition will be available.
 ## @end itemize
--- a/scripts/miscellaneous/fullfile.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/miscellaneous/fullfile.m	Tue Sep 20 15:38:24 2011 -0400
@@ -26,7 +26,7 @@
 
   if (nargin > 0)
     ## Discard all empty arguments
-    varargin(cellfun (@isempty, varargin)) = [];
+    varargin(cellfun ("isempty", varargin)) = [];
     nargs = numel (varargin);
     if (nargs > 1)
       filename = varargin{1};
--- a/scripts/miscellaneous/getfield.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/miscellaneous/getfield.m	Tue Sep 20 15:38:24 2011 -0400
@@ -50,8 +50,8 @@
     print_usage ();
   endif
   subs = varargin;
-  flds = cellfun (@ischar, subs);
-  idxs = cellfun (@iscell, subs);
+  flds = cellfun ("isclass", subs, "char");
+  idxs = cellfun ("isclass", subs, "cell");
   if (all (flds | idxs))
     typs = merge (flds, {"."}, {"()"});
     obj = subsref (s, struct ("type", typs, "subs", subs));
--- a/scripts/miscellaneous/gzip.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/miscellaneous/gzip.m	Tue Sep 20 15:38:24 2011 -0400
@@ -31,7 +31,7 @@
   if (nargin != 1 && nargin != 2) || (nargout > 1)
     print_usage ();
   endif
-     
+
   if (nargout == 0)
     __xzip__ ("gzip", "gz", "gzip -r %s", varargin{:});
   else
--- a/scripts/miscellaneous/info.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/miscellaneous/info.m	Tue Sep 20 15:38:24 2011 -0400
@@ -43,3 +43,6 @@
   http://www.octave.org/bugs.html\n");
 
 endfunction
+
+## Mark file as being tested.  No real test needed for this function.
+%! assert (1)
--- a/scripts/miscellaneous/ismac.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/miscellaneous/ismac.m	Tue Sep 20 15:38:24 2011 -0400
@@ -32,3 +32,5 @@
 
 endfunction
 
+%!error ismac (1);
+%!assert (islogical (ismac ()));
--- a/scripts/miscellaneous/ispc.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/miscellaneous/ispc.m	Tue Sep 20 15:38:24 2011 -0400
@@ -31,3 +31,6 @@
   endif
 
 endfunction
+
+%!error ispc (1);
+%!assert (islogical (ispc ()));
--- a/scripts/miscellaneous/isunix.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/miscellaneous/isunix.m	Tue Sep 20 15:38:24 2011 -0400
@@ -31,3 +31,6 @@
   endif
 
 endfunction
+
+%!error isunix (1);
+%!assert (islogical (isunix ()));
--- a/scripts/miscellaneous/list_primes.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/miscellaneous/list_primes.m	Tue Sep 20 15:38:24 2011 -0400
@@ -83,3 +83,9 @@
   endwhile
 
 endfunction
+
+%!test
+%! assert (list_primes(), [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41,\
+%!                        43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]);
+%! assert (list_primes(5), [2, 3, 5, 7, 11]);
+
--- a/scripts/miscellaneous/ls.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/miscellaneous/ls.m	Tue Sep 20 15:38:24 2011 -0400
@@ -63,7 +63,7 @@
           retval = strvcat (regexp (output, '\S+', 'match'){:});
         endif
       else
-        error ("ls: command exited abnormally with status %d", status);
+        error ("ls: command exited abnormally with status %d\n", status);
       endif
 
     else
--- a/scripts/miscellaneous/mkoctfile.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/miscellaneous/mkoctfile.m	Tue Sep 20 15:38:24 2011 -0400
@@ -75,26 +75,30 @@
 ## Print the configuration variable VAR@.  Recognized variables are:
 ##
 ## @example
-##    ALL_CFLAGS                FFTW_LIBS
+##    ALL_CFLAGS                FFTW3F_LIBS
 ##    ALL_CXXFLAGS              FLIBS
 ##    ALL_FFLAGS                FPICFLAG
 ##    ALL_LDFLAGS               INCFLAGS
-##    BLAS_LIBS                 LDFLAGS
-##    CC                        LD_CXX
-##    CFLAGS                    LD_STATIC_FLAG
-##    CPICFLAG                  LFLAGS
-##    CPPFLAGS                  LIBCRUFT
-##    CXX                       LIBOCTAVE
-##    CXXFLAGS                  LIBOCTINTERP
-##    CXXPICFLAG                LIBREADLINE
+##    BLAS_LIBS                 LAPACK_LIBS
+##    CC                        LDFLAGS
+##    CFLAGS                    LD_CXX
+##    CPICFLAG                  LD_STATIC_FLAG
+##    CPPFLAGS                  LFLAGS
+##    CXX                       LIBCRUFT
+##    CXXFLAGS                  LIBOCTAVE
+##    CXXPICFLAG                LIBOCTINTERP
 ##    DEPEND_EXTRA_SED_PATTERN  LIBS
 ##    DEPEND_FLAGS              OCTAVE_LIBS
-##    DL_LD                     RDYNAMIC_FLAG
-##    DL_LDFLAGS                RLD_FLAG
-##    F2C                       SED
-##    F2CFLAGS                  XTRA_CFLAGS
-##    F77                       XTRA_CXXFLAGS
-##    FFLAGS
+##    DL_LD                     OCTAVE_LINK_DEPS
+##    DL_LDFLAGS                OCT_LINK_DEPS
+##    EXEEXT                    RDYNAMIC_FLAG
+##    F77                       READLINE_LIBS
+##    F77_INTEGER_8_FLAG        SED
+##    FFLAGS                    XTRA_CFLAGS
+##    FFTW3_LDFLAGS             XTRA_CXXFLAGS
+##    FFTW3_LIBS
+##    FFTW3F_LDFLAGS
+##
 ## @end example
 ##
 ## @item --link-stand-alone
--- a/scripts/miscellaneous/module.mk	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/miscellaneous/module.mk	Tue Sep 20 15:38:24 2011 -0400
@@ -50,6 +50,7 @@
   miscellaneous/paren.m \
   miscellaneous/parseparams.m \
   miscellaneous/perl.m \
+  miscellaneous/python.m \
   miscellaneous/rmappdata.m \
   miscellaneous/run.m \
   miscellaneous/semicolon.m \
@@ -61,7 +62,6 @@
   miscellaneous/tar.m \
   miscellaneous/tempdir.m \
   miscellaneous/tempname.m \
-  miscellaneous/unimplemented.m \
   miscellaneous/unix.m \
   miscellaneous/unpack.m \
   miscellaneous/untar.m \
--- a/scripts/miscellaneous/news.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/miscellaneous/news.m	Tue Sep 20 15:38:24 2011 -0400
@@ -36,3 +36,7 @@
   endif
 
 endfunction
+
+
+## Remove from test statistics.  No real tests possible
+%!assert (1)
--- a/scripts/miscellaneous/paren.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/miscellaneous/paren.m	Tue Sep 20 15:38:24 2011 -0400
@@ -21,3 +21,7 @@
 ## @deftypefnx {Operator} {} )
 ## Array index or function argument delimeter.
 ## @end deftypefn
+
+## Mark file as being tested.  No real test needed for a documentation .m file
+%!assert (1)
+
--- a/scripts/miscellaneous/private/__xzip__.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/miscellaneous/private/__xzip__.m	Tue Sep 20 15:38:24 2011 -0400
@@ -36,7 +36,7 @@
   if (nargin != 4 && nargin != 5)
     print_usage ();
   endif
-  
+
   if (! ischar (extension) || length (extension) == 0)
     error ("__xzip__: EXTENSION must be a string with finite length");
   endif
@@ -112,10 +112,10 @@
 endfunction
 
 function [d, f] = myfileparts (files)
-  [d, f, ext] = cellfun (@(x) fileparts (x), files, "uniformoutput", false);
+  [d, f, ext] = cellfun ("fileparts", files, "uniformoutput", false);
   f = cellfun (@(x, y) sprintf ("%s%s", x, y), f, ext,
                "uniformoutput", false);
-  idx = cellfun (@isdir, files);
+  idx = cellfun ("isdir", files);
   d(idx) = "";
   f(idx) = files(idx);
 endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/miscellaneous/python.m	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,45 @@
+## Copyright (C) 2008-2011 Julian Schnidder
+## Copyright (C) 2011 Carnë Draug <carandraug+dev@gmail.com>
+##
+## 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 3 of the License, 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, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {Function File} {[@var{output}, @var{status}] =} python (@var{scriptfile})
+## @deftypefnx {Function File} {[@var{output}, @var{status}] =} python (@var{scriptfile}, @var{argument1}, @var{argument2}, @dots{})
+## Invoke python script @var{scriptfile} with possibly a list of
+## command line arguments.
+## Returns output in @var{output} and status
+## in @var{status}.
+## @seealso{system}
+## @end deftypefn
+
+function [output, status] = python (scriptfile = "-c ''", varargin)
+
+  ## VARARGIN is intialized to {}(1x0) if no additional arguments are
+  ## supplied, so there is no need to check for it, or provide an
+  ## initial value in the argument list of the function definition.
+
+  if (ischar (scriptfile)
+      && ((nargin != 1 && iscellstr (varargin))
+          || (nargin == 1 && ! isempty (scriptfile))))
+    [status, output] = system (cstrcat ("python ", scriptfile,
+                                        sprintf (" %s", varargin{:})));
+  else
+    error ("python: invalid arguments");
+  endif
+
+endfunction
--- a/scripts/miscellaneous/semicolon.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/miscellaneous/semicolon.m	Tue Sep 20 15:38:24 2011 -0400
@@ -21,3 +21,7 @@
 ## Array row or command separator.
 ## @seealso{comma}
 ## @end deftypefn
+
+## Mark file as being tested.  No real test needed for a documentation .m file
+%!assert (1)
+
--- a/scripts/miscellaneous/setfield.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/miscellaneous/setfield.m	Tue Sep 20 15:38:24 2011 -0400
@@ -50,8 +50,8 @@
   endif
   subs = varargin(1:end-1);
   rhs = varargin{end};
-  flds = cellfun (@ischar, subs);
-  idxs = cellfun (@iscell, subs);
+  flds = cellfun ("isclass", subs, "char");
+  idxs = cellfun ("isclass", subs, "cell");
   if (all (flds | idxs))
     typs = merge (flds, {"."}, {"()"});
     obj = subsasgn (obj, struct ("type", typs, "subs", subs), rhs);
--- a/scripts/miscellaneous/swapbytes.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/miscellaneous/swapbytes.m	Tue Sep 20 15:38:24 2011 -0400
@@ -32,6 +32,7 @@
 ## @end deftypefn
 
 function y = swapbytes (x)
+
   if (nargin != 1)
     print_usage ();
   endif
@@ -53,4 +54,11 @@
     y = reshape (typecast (reshape (typecast (x(:), "uint8"), nb, numel (x))
                            ([nb : -1 : 1], :) (:), clx), size(x));
   endif
+
 endfunction
+
+
+%!assert (double (swapbytes (uint16 (1:4))), [256 512 768 1024])
+%!error (swapbytes ())
+%!error (swapbytes (1, 2))
+
--- a/scripts/miscellaneous/symvar.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/miscellaneous/symvar.m	Tue Sep 20 15:38:24 2011 -0400
@@ -28,3 +28,6 @@
 function args = symvar (s)
   args = argnames (inline (s));
 endfunction
+
+## This function is tested by the tests for argnames().
+%!assert (1)
--- a/scripts/miscellaneous/tempdir.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/miscellaneous/tempdir.m	Tue Sep 20 15:38:24 2011 -0400
@@ -37,3 +37,19 @@
   endif
 
 endfunction
+
+
+%!assert (ischar (tempdir ()))
+
+%!test
+%! old_wstate = warning ("query");
+%! warning ("off");
+%! old_tmpdir = getenv ("TMPDIR");
+%! unwind_protect
+%!   setenv ("TMPDIR", "__MY_TMP_DIR__");
+%!   assert (tempdir (), ["__MY_TMP_DIR__" filesep()]);
+%! unwind_protect_cleanup
+%!   setenv ("TMPDIR", old_tmpdir);
+%!   warning (old_wstate);
+%! end_unwind_protect
+
--- a/scripts/miscellaneous/tempname.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/miscellaneous/tempname.m	Tue Sep 20 15:38:24 2011 -0400
@@ -29,3 +29,7 @@
   filename = tmpnam (varargin{:});
 
 endfunction
+
+
+%% No tests needed for alias.
+%!assert (1)
--- a/scripts/miscellaneous/unimplemented.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,430 +0,0 @@
-## Copyright (C) 2010-2011 John W. Eaton
-## Copyright (C) 2010 VZLU Prague
-##
-## 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} {} unimplemented ()
-## Undocumented internal function.
-## @end deftypefn
-
-function txt = unimplemented (fcn)
-
-  is_matlab_function = true;
-
-  ## Some smarter cases, add more as needed.
-  switch (fcn)
-
-  case "quad2d"
-    txt = ["quad2d is not implemented.  Consider using dblquad."];
-
-  case "gsvd"
-    txt = ["gsvd is not currently part of Octave.  See the linear-algebra",...
-    "package at @url{http://octave.sf.net/linear-algebra/}."];
-
-  case "linprog"
-    txt = ["Octave does not currently provide linprog.  ",...
-    "Linear programming problems may be solved using @code{glpk}.  ",...
-    "Try @code{help glpk} for more info."];
-
-  case {"ode113", "ode15i", "ode15s", "ode23", "ode23s", "ode23t", "ode45", "odeget", "odeset"}
-    txt = ["Octave provides lsode for solving differential equations.  ",...
-    "For more information try @code{help lsode}.  ",...
-    "Matlab-compatible ODE functions are provided by the odepkg package.  ",...
-    "See @url{http://octave.sf.net/odepkg/}."];
-
-  otherwise
-    if (ismember (fcn, missing_functions ()))
-      txt = sprintf ("the `%s' function is not yet implemented in Octave", fcn);
-    else
-      is_matlab_function = false;
-      txt = "";
-    endif
-  endswitch
-
-  if (is_matlab_function)
-    txt = [txt, "\n\n@noindent\nPlease read ",...
-           "@url{http://www.octave.org/missing.html} to learn how ",...
-           "you can contribute missing functionality."];
-    txt = __makeinfo__ (txt);
-  endif
-
-  if (nargout == 0)
-    warning ("Octave:missing-function", "%s", txt);
-  endif
-
-endfunction
-
-function list = missing_functions ()
-  persistent list = {
-  "DelaunayTri",
-  "MException",
-  "RandStream",
-  "TriRep",
-  "TriScatteredInterp",
-  "addpref",
-  "align",
-  "alim",
-  "alpha",
-  "alphamap",
-  "annotation",
-  "audiodevinfo",
-  "audioplayer",
-  "audiorecorder",
-  "aufinfo",
-  "auread",
-  "auwrite",
-  "avifile",
-  "aviinfo",
-  "aviread",
-  "bar3",
-  "bar3h",
-  "bench",
-  "betaincinv",
-  "bicg",
-  "bicgstabl",
-  "brush",
-  "builddocsearchdb",
-  "bvp4c",
-  "bvp5c",
-  "bvpget",
-  "bvpinit",
-  "bvpset",
-  "bvpxtend",
-  "callSoapService",
-  "calllib",
-  "camdolly",
-  "cameratoolbar",
-  "camlight",
-  "camlookat",
-  "camorbit",
-  "campan",
-  "campos",
-  "camproj",
-  "camroll",
-  "camtarget",
-  "camup",
-  "camva",
-  "camzoom",
-  "cdf2rdf",
-  "cdfepoch",
-  "cdfinfo",
-  "cdfread",
-  "cdfwrite",
-  "cellplot",
-  "checkin",
-  "checkout",
-  "cholinc",
-  "clearvars",
-  "clipboard",
-  "cmopts",
-  "cmpermute",
-  "cmunique",
-  "colordef",
-  "colormapeditor",
-  "commandhistory",
-  "commandwindow",
-  "condeig",
-  "coneplot",
-  "contourslice",
-  "copyobj",
-  "createClassFromWsdl",
-  "createSoapMessage",
-  "customverctrl",
-  "daqread",
-  "datacursormode",
-  "datatipinfo",
-  "dbmex",
-  "dde23",
-  "ddeget",
-  "ddesd",
-  "ddeset",
-  "decic",
-  "depdir",
-  "depfun",
-  "deval",
-  "dialog",
-  "dither",
-  "docopt",
-  "docsearch",
-  "dragrect",
-  "dynamicprops",
-  "echodemo",
-  "ellipj",
-  "ellipke",
-  "erfcinv",
-  "errordlg",
-  "evalc",
-  "exifread",
-  "expint",
-  "export2wsdlg",
-  "figurepalette",
-  "filebrowser",
-  "fill3",
-  "findfigs",
-  "fitsinfo",
-  "fitsread",
-  "flow",
-  "fminsearch",
-  "frame2im",
-  "freqspace",
-  "funm",
-  "gallery",
-  "gammaincinv",
-  "gco",
-  "getframe",
-  "getpixelposition",
-  "getpref",
-  "gmres",
-  "grabcode",
-  "graymon",
-  "gsvd",
-  "guidata",
-  "guide",
-  "guihandles",
-  "handle",
-  "hdf",
-  "hdf5",
-  "hdf5info",
-  "hdf5read",
-  "hdf5write",
-  "hdfinfo",
-  "hdfread",
-  "hdftool",
-  "helpbrowser",
-  "helpdesk",
-  "helpdlg",
-  "helpwin",
-  "hgexport",
-  "hgload",
-  "hgsave",
-  "hgsetget",
-  "hgtransform",
-  "hostid",
-  "ilu",
-  "im2frame",
-  "im2java",
-  "imapprox",
-  "imformats",
-  "import",
-  "importdata",
-  "inmem",
-  "inputParser",
-  "inputdlg",
-  "inspect",
-  "instrfind",
-  "instrfindall",
-  "interpstreamspeed",
-  "iscom",
-  "isinterface",
-  "isjava",
-  "isocaps",
-  "ispref",
-  "isstudent",
-  "javaArray",
-  "javaMethod",
-  "javaMethodEDT",
-  "javaObject",
-  "javaObjectEDT",
-  "javaaddpath",
-  "javachk",
-  "javaclasspath",
-  "javarmpath",
-  "ldl",
-  "libfunctions",
-  "libfunctionsview",
-  "libisloaded",
-  "libpointer",
-  "libstruct",
-  "light",
-  "lightangle",
-  "lighting",
-  "linkaxes",
-  "linkdata",
-  "linsolve",
-  "listdlg",
-  "listfonts",
-  "loadlibrary",
-  "lscov",
-  "lsqr",
-  "makehgtform",
-  "material",
-  "matlabrc",
-  "maxNumCompThreads",
-  "memmapfile",
-  "memory",
-  "metaclass",
-  "methodsview",
-  "minres",
-  "mlint",
-  "mlintrpt",
-  "mmfileinfo",
-  "mmreader",
-  "movegui",
-  "movie",
-  "movie2avi",
-  "msgbox",
-  "multibandread",
-  "multibandwrite",
-  "native2unicode",
-  "noanimate",
-  "ode113",
-  "ode15i",
-  "ode15s",
-  "ode23",
-  "ode23s",
-  "ode23t",
-  "ode23tb",
-  "ode45",
-  "odefile",
-  "odeget",
-  "odeset",
-  "odextend",
-  "open",
-  "openfig",
-  "opengl",
-  "openvar",
-  "ordeig",
-  "ordqz",
-  "ordschur",
-  "padecoef",
-  "pagesetupdlg",
-  "pan",
-  "parseSoapResponse",
-  "path2rc",
-  "pathtool",
-  "pcode",
-  "pdepe",
-  "pdeval",
-  "playshow",
-  "plotbrowser",
-  "plotedit",
-  "plottools",
-  "polyeig",
-  "prefdir",
-  "preferences",
-  "printdlg",
-  "printopt",
-  "printpreview",
-  "profile",
-  "profsave",
-  "propedit",
-  "propertyeditor",
-  "publish",
-  "qmr",
-  "quad2d",
-  "questdlg",
-  "rbbox",
-  "recycle",
-  "reducepatch",
-  "reducevolume",
-  "resample",
-  "reset",
-  "rgbplot",
-  "rmpref",
-  "root",
-  "rotate",
-  "rotate3d",
-  "rsf2csf",
-  "selectmoveresize",
-  "sendmail",
-  "serial",
-  "setpixelposition",
-  "setpref",
-  "showplottool",
-  "shrinkfaces",
-  "smooth3",
-  "snapnow",
-  "sound",
-  "soundsc",
-  "ss2tf",
-  "stream2",
-  "stream3",
-  "streamline",
-  "streamparticles",
-  "streamribbon",
-  "streamslice",
-  "streamtube",
-  "strings",
-  "subvolume",
-  "superclasses",
-  "support",
-  "surf2patch",
-  "symmlq",
-  "syntax",
-  "tetramesh",
-  "texlabel",
-  "textwrap",
-  "tfqmr",
-  "timer",
-  "timerfind",
-  "timerfindall",
-  "timeseries",
-  "toolboxdir",
-  "tscollection",
-  "tstool",
-  "uibuttongroup",
-  "uicontextmenu",
-  "uicontrol",
-  "uigetpref",
-  "uiimport",
-  "uiopen",
-  "uipanel",
-  "uipushtool",
-  "uiresume",
-  "uisave",
-  "uisetcolor",
-  "uisetfont",
-  "uisetpref",
-  "uistack",
-  "uitable",
-  "uitoggletool",
-  "uitoolbar",
-  "uiwait",
-  "undocheckout",
-  "unicode2native",
-  "unloadlibrary",
-  "unmesh",
-  "usejava",
-  "userpath",
-  "validateattributes",
-  "verLessThan",
-  "viewmtx",
-  "visdiff",
-  "volumebounds",
-  "waitbar",
-  "waitfor",
-  "warndlg",
-  "waterfall",
-  "wavfinfo",
-  "wavplay",
-  "wavrecord",
-  "web",
-  "whatsnew",
-  "wk1finfo",
-  "wk1read",
-  "wk1write",
-  "workspace",
-  "xlsfinfo",
-  "xlsread",
-  "xlswrite",
-  "xmlread",
-  "xmlwrite",
-  "xslt",
-  "zoom",
-  };
-endfunction
--- a/scripts/miscellaneous/unpack.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/miscellaneous/unpack.m	Tue Sep 20 15:38:24 2011 -0400
@@ -38,12 +38,12 @@
     print_usage ();
   endif
 
-  if (! ischar (file) && ! iscellstr (file)) 
+  if (! ischar (file) && ! iscellstr (file))
     error ("unpack: invalid input file class, %s", class(file));
   endif
 
   ## character arrays of more than one string must be treated as cell strings
-  if (ischar (file) && ! isvector (file)) 
+  if (ischar (file) && ! isvector (file))
     file = cellstr (file);
   endif
 
@@ -222,7 +222,7 @@
   ## Parse the output from zip and unzip.
 
   ## Skip first line which is Archive header
-  output(1) = []; 
+  output(1) = [];
   for i = 1:length (output)
     files{i} = output{i}(14:length(output{i}));
   endfor
--- a/scripts/miscellaneous/warning_ids.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/miscellaneous/warning_ids.m	Tue Sep 20 15:38:24 2011 -0400
@@ -284,3 +284,6 @@
 function warning_ids ()
   help ("warning_ids");
 endfunction
+
+## Remove from test statistics.  No real tests possible
+%!assert (1)
--- a/scripts/miscellaneous/what.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/miscellaneous/what.m	Tue Sep 20 15:38:24 2011 -0400
@@ -90,7 +90,7 @@
   if (length (f) > 0)
     printf ("%s %s:\n\n", msg, p);
 
-    maxlen = max (cellfun (@length, f));
+    maxlen = max (cellfun ("length", f));
     ncols = max (1, floor (terminal_size()(2) / (maxlen + 3)));
     fmt = "";
     for i = 1: ncols
--- a/scripts/miscellaneous/xor.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/miscellaneous/xor.m	Tue Sep 20 15:38:24 2011 -0400
@@ -48,7 +48,11 @@
       ## Typecast to logicals is necessary for other numeric types.
       z = logical (x) != logical (y);
     else
-      error ("xor: X and Y must be of common size or scalars");
+      try
+        z = bsxfun (@xor, x, y);
+      catch
+        error ("xor: X and Y must be of compatible size or scalars");
+      end_try_catch
     endif
   else
     print_usage ();
--- a/scripts/optimization/__all_opts__.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/optimization/__all_opts__.m	Tue Sep 20 15:38:24 2011 -0400
@@ -67,3 +67,7 @@
 
 endfunction
 
+
+## No test needed for internal helper function.
+%!assert (1)
+
--- a/scripts/optimization/fminbnd.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/optimization/fminbnd.m	Tue Sep 20 15:38:24 2011 -0400
@@ -49,7 +49,8 @@
 ## This is patterned after opt/fmin.f from Netlib, which in turn is taken from
 ## Richard Brent: Algorithms For Minimization Without Derivatives, Prentice-Hall (1973)
 
-## PKG_ADD: __all_opts__ ("fminbnd");
+## PKG_ADD: ## Discard result to avoid polluting workspace with ans at startup.
+## PKG_ADD: [~] = __all_opts__ ("fminbnd");
 
 function [x, fval, info, output] = fminbnd (fun, xmin, xmax, options = struct ())
 
--- a/scripts/optimization/fminunc.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/optimization/fminunc.m	Tue Sep 20 15:38:24 2011 -0400
@@ -77,7 +77,8 @@
 ## @seealso{fminbnd, optimset}
 ## @end deftypefn
 
-## PKG_ADD: __all_opts__ ("fminunc");
+## PKG_ADD: ## Discard result to avoid polluting workspace with ans at startup.
+## PKG_ADD: [~] = __all_opts__ ("fminunc");
 
 function [x, fval, info, output, grad, hess] = fminunc (fcn, x0, options = struct ())
 
--- a/scripts/optimization/fsolve.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/optimization/fsolve.m	Tue Sep 20 15:38:24 2011 -0400
@@ -127,7 +127,8 @@
 ## @end example
 ## @end deftypefn
 
-## PKG_ADD: __all_opts__ ("fsolve");
+## PKG_ADD: ## Discard result to avoid polluting workspace with ans at startup.
+## PKG_ADD: [~] = __all_opts__ ("fsolve");
 
 function [x, fvec, info, output, fjac] = fsolve (fcn, x0, options = struct ())
 
--- a/scripts/optimization/fzero.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/optimization/fzero.m	Tue Sep 20 15:38:24 2011 -0400
@@ -93,7 +93,8 @@
 ## the need for external functions and error handling. The algorithm has
 ## also been slightly modified.
 
-## PKG_ADD: __all_opts__ ("fzero");
+## PKG_ADD: ## Discard result to avoid polluting workspace with ans at startup.
+## PKG_ADD: [~] = __all_opts__ ("fzero");
 
 function [x, fval, info, output] = fzero (fun, x0, options = struct ())
 
--- a/scripts/optimization/lsqnonneg.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/optimization/lsqnonneg.m	Tue Sep 20 15:38:24 2011 -0400
@@ -63,7 +63,8 @@
 ## @seealso{optimset, pqpnonneg}
 ## @end deftypefn
 
-## PKG_ADD: __all_opts__ ("lsqnonneg");
+## PKG_ADD: ## Discard result to avoid polluting workspace with ans at startup.
+## PKG_ADD: [~] = __all_opts__ ("lsqnonneg");
 
 ## This is implemented from Lawson and Hanson's 1973 algorithm on page
 ## 161 of Solving Least Squares Problems.
--- a/scripts/optimization/pqpnonneg.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/optimization/pqpnonneg.m	Tue Sep 20 15:38:24 2011 -0400
@@ -58,7 +58,8 @@
 ## @seealso{optimset, lsqnonneg, qp}
 ## @end deftypefn
 
-## PKG_ADD: __all_opts__ ("pqpnonneg");
+## PKG_ADD: ## Discard result to avoid polluting workspace with ans at startup.
+## PKG_ADD: [~] = __all_opts__ ("pqpnonneg");
 
 ## This is analogical to the lsqnonneg implementation, which is
 ## implemented from Lawson and Hanson's 1973 algorithm on page
--- a/scripts/optimization/qp.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/optimization/qp.m	Tue Sep 20 15:38:24 2011 -0400
@@ -108,7 +108,8 @@
 ## @end table
 ## @end deftypefn
 
-## PKG_ADD: __all_opts__ ("qp");
+## PKG_ADD: ## Discard result to avoid polluting workspace with ans at startup.
+## PKG_ADD: [~] = __all_opts__ ("qp");
 
 function [x, obj, INFO, lambda] = qp (x0, H, varargin)
 
--- a/scripts/path/matlabroot.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/path/matlabroot.m	Tue Sep 20 15:38:24 2011 -0400
@@ -31,5 +31,5 @@
 
 endfunction
 
+%!assert (matlabroot(), OCTAVE_HOME())
 
-
--- a/scripts/pkg/pkg.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/pkg/pkg.m	Tue Sep 20 15:38:24 2011 -0400
@@ -20,8 +20,10 @@
 ## -*- texinfo -*-
 ## @deftypefn  {Command} {} pkg @var{command} @var{pkg_name}
 ## @deftypefnx {Command} {} pkg @var{command} @var{option} @var{pkg_name}
-## This command interacts with the package manager.  Different actions will
-## be taken depending on the value of @var{command}.
+## Manage packages (groups of add-on functions) for Octave.  Different actions
+## are available depending on the value of @var{command}.
+##
+## Available commands:
 ##
 ## @table @samp
 ##
@@ -40,34 +42,44 @@
 ##
 ## @table @code
 ## @item -nodeps
-## The package manager will disable the dependency checking.  That way it
-## is possible to install a package even if it depends on another package
-## that's not installed on the system.  @strong{Use this option with care.}
+## The package manager will disable dependency checking.  With this option it
+## is possible to install a package even when it depends on another package
+## which is not installed on the system.  @strong{Use this option with care.}
 ##
 ## @item -noauto
 ## The package manager will not automatically load the installed package
-## when starting Octave, even if the package requests that it is.
+## when starting Octave.  This overrides any setting within the package.
 ##
 ## @item -auto
 ## The package manager will automatically load the installed package when
-## starting Octave, even if the package requests that it isn't.
+## starting Octave.  This overrides any setting within the package.
 ##
 ## @item -local
-## A local installation is forced, even if the user has system privileges.
+## A local installation (package available only to current user) is forced,
+## even if the user has system privileges.
 ##
 ## @item -global
-## A global installation is forced, even if the user doesn't normally have
-## system privileges
+## A global installation (package available to all users) is forced, even if
+## the user doesn't normally have system privileges.
 ##
 ## @item -forge
 ## Install a package directly from the Octave-Forge repository.  This
 ## requires an internet connection and the cURL library.
 ##
 ## @item -verbose
-## The package manager will print the output of all of the commands that are
-## performed.
+## The package manager will print the output of all commands as
+## they are performed.
 ## @end table
 ##
+## @item update
+## Check installed Octave-Forge pacakages against repository and update any
+## outdated items.  This requires an internet connection and the cURL library.
+## Usage:
+##
+## @example
+## pkg update
+## @end example
+##
 ## @item uninstall
 ## Uninstall named packages.  For example,
 ##
@@ -90,47 +102,53 @@
 ##
 ## @noindent
 ## adds the @code{image} package to the path.  It is possible to load all
-## installed packages at once with the command
+## installed packages at once with the keyword @samp{all}.  Usage:
 ##
 ## @example
 ## pkg load all
 ## @end example
 ##
 ## @item unload
-## Removes named packages from the path.  After unloading a package it is
-## no longer possible to use the functions provided by the package.
-## This command behaves like the @code{load} command.
+## Remove named packages from the path.  After unloading a package it is
+## no longer possible to use the functions provided by the package.  It is
+## possible to unload all installed packages at once with the keyword
+## @samp{all}.  Usage:
+##
+## @example
+## pkg unload all
+## @end example
 ##
 ## @item list
-## Show a list of the currently installed packages.  By requesting one or two
-## output argument it is possible to get a list of the currently installed
-## packages.  For example,
+## Show the list of currently installed packages.  For example,
 ##
 ## @example
-## installed_packages = pkg list;
+## installed_packages = pkg ("list")
 ## @end example
 ##
 ## @noindent
 ## returns a cell array containing a structure for each installed package.
-## The command
+##
+## If two output arguments are requested @code{pkg} splits the list of
+## installed packages into those which were installed by the current user,
+## and those which were installed by the system administrator.
 ##
 ## @example
-## [@var{user_packages}, @var{system_packages}] = pkg list
+## [user_packages, system_packages] = pkg ("list")
 ## @end example
 ##
-## @noindent
-## splits the list of installed packages into those who are installed by
-## the current user, and those installed by the system administrator.
+## The option '-forge' lists packages available at the Octave-Forge repository.
+## This requires an internet connection and the cURL library.  For example:
 ##
-## The option '-forge' lists packages available at the Octave-Forge repository.
-## This requires an internet connection and the cURL library.
+## @example
+## oct_forge_pkgs = pkg ("list", "-forge")
+## @end example
 ##
 ## @item describe
 ## Show a short description of the named installed packages, with the option
-## '-verbose' also list functions provided by the package, e.g.:
+## '-verbose' also list functions provided by the package.  For example,
 ##
 ## @example
-##  pkg describe -verbose all
+## pkg describe -verbose all
 ## @end example
 ##
 ## @noindent
@@ -140,7 +158,7 @@
 ## output rather than printed on screen:
 ##
 ## @example
-##  desc = pkg ("describe", "secs1d", "image")
+## desc = pkg ("describe", "secs1d", "image")
 ## @end example
 ##
 ## @noindent
@@ -148,7 +166,7 @@
 ## error, unless a second output is requested:
 ##
 ## @example
-##  [ desc, flag] = pkg ("describe", "secs1d", "image")
+## [desc, flag] = pkg ("describe", "secs1d", "image")
 ## @end example
 ##
 ## @noindent
@@ -170,20 +188,20 @@
 ## output argument.  For example:
 ##
 ## @example
-## p = pkg prefix
+## pfx = pkg ("prefix")
 ## @end example
 ##
 ## The location in which to install the architecture dependent files can be
-## independent specified with an addition argument.  For example:
+## independently specified with an addition argument.  For example:
 ##
 ## @example
 ## pkg prefix ~/my_octave_packages ~/my_arch_dep_pkgs
 ## @end example
 ##
 ## @item local_list
-## Set the file in which to look for information on the locally
+## Set the file in which to look for information on locally
 ## installed packages.  Locally installed packages are those that are
-## typically available only to the current user.  For example:
+## available only to the current user.  For example:
 ##
 ## @example
 ## pkg local_list ~/.octave_packages
@@ -196,9 +214,9 @@
 ## @end example
 ##
 ## @item global_list
-## Set the file in which to look for, for information on the globally
+## Set the file in which to look for information on globally
 ## installed packages.  Globally installed packages are those that are
-## typically available to all users.  For example:
+## available to all users.  For example:
 ##
 ## @example
 ## pkg global_list /usr/share/octave/octave_packages
@@ -210,21 +228,8 @@
 ## pkg global_list
 ## @end example
 ##
-## @item rebuild
-## Rebuilds the package database from the installed directories.  This can
-## be used in cases where for some reason the package database is corrupted.
-## It can also take the @option{-auto} and @option{-noauto} options to allow the
-## autoloading state of a package to be changed.  For example,
-##
-## @example
-## pkg rebuild -noauto image
-## @end example
-##
-## @noindent
-## will remove the autoloading status of the image package.
-##
 ## @item build
-## Builds a binary form of a package or packages.  The binary file produced
+## Build a binary form of a package or packages.  The binary file produced
 ## will itself be an Octave package that can be installed normally with
 ## @code{pkg}.  The form of the command to build a binary package is
 ##
@@ -236,7 +241,21 @@
 ## where @code{builddir} is the name of a directory where the temporary
 ## installation will be produced and the binary packages will be found.
 ## The options @option{-verbose} and @option{-nodeps} are respected, while
-## the other options are ignored.
+## all other options are ignored.
+##
+## @item rebuild
+## Rebuild the package database from the installed directories.  This can
+## be used in cases where the package database has been corrupted.
+## It can also take the @option{-auto} and @option{-noauto} options to allow the
+## autoloading state of a package to be changed.  For example,
+##
+## @example
+## pkg rebuild -noauto image
+## @end example
+##
+## @noindent
+## will remove the autoloading status of the image package.
+##
 ## @end table
 ## @end deftypefn
 
@@ -267,7 +286,8 @@
 
   available_actions = {"list", "install", "uninstall", "load", ...
                        "unload", "prefix", "local_list", ...
-                       "global_list", "rebuild", "build","describe"};
+                       "global_list", "rebuild", "build", ...
+                       "describe", "update"};
   ## Handle input
   if (length (varargin) == 0 || ! iscellstr (varargin))
     print_usage ();
@@ -349,8 +369,8 @@
       unwind_protect
 
         if (octave_forge)
-          [urls, local_files] = cellfun (@get_forge_download, files, "uniformoutput", false);
-          [files, succ] = cellfun (@urlwrite, urls, local_files, "uniformoutput", false);
+          [urls, local_files] = cellfun ("get_forge_download", files, "uniformoutput", false);
+          [files, succ] = cellfun ("urlwrite", urls, local_files, "uniformoutput", false);
           succ = [succ{:}];
           if (! all (succ))
             i = find (! succ, 1);
@@ -362,7 +382,7 @@
                  global_list, global_install);
 
       unwind_protect_cleanup
-        cellfun (@unlink, local_files);
+        cellfun ("unlink", local_files);
       end_unwind_protect
 
     case "uninstall"
@@ -492,6 +512,21 @@
           error ("you can request at most two outputs when calling 'pkg describe'");
       endswitch
 
+    case "update"
+      if (nargout == 0)
+        installed_pkgs_lst = installed_packages (local_list, global_list);
+        for i = 1:length (installed_pkgs_lst)
+          installed_pkg_name = installed_pkgs_lst{i}.name;
+          installed_pkg_version = installed_pkgs_lst{i}.version;
+          forge_pkg_version = get_forge_pkg (installed_pkg_name);
+          if (compare_versions (forge_pkg_version, installed_pkg_version, ">"))
+            feval (@pkg, "install", "-forge", installed_pkg_name);
+          endif
+        endfor
+      else
+        error ("no output arguments available");
+      endif
+
     otherwise
       error ("you must specify a valid action for 'pkg'. See 'help pkg' for details");
   endswitch
@@ -1320,7 +1355,7 @@
         flags = cstrcat (flags, " RANLIB=\"", octave_config_info ("RANLIB"), "\"");
       endif
       [status, output] = shell (cstrcat ("cd '", src, "'; ", scenv,
-					 "./configure --prefix=\"",
+                                         "./configure --prefix=\"",
                                          desc.dir, "\"", flags));
       if (status != 0)
         rm_rf (desc.dir);
@@ -1383,7 +1418,7 @@
     if (isempty (filenames))
       idx = [];
     else
-      idx = cellfun (@is_architecture_dependent, filenames);
+      idx = cellfun ("is_architecture_dependent", filenames);
     endif
     archdependent = filenames (idx);
     archindependent = filenames (!idx);
--- a/scripts/plot/__fltk_ginput__.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,105 +0,0 @@
-## Copyright (C) 2010-2011 Shai Ayal
-##
-## 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} {[@var{x}, @var{y}, @var{buttons}] =} __fltk_ginput__ (@var{f}, @var{n})
-## Undocumented internal function.
-## @end deftypefn
-
-## This is ginput.m implementation for fltk.
-
-## FIXME -- Key presses cannot toggle menu items nor hotkey functionality
-## (grid, autoscale) during ginput!
-
-function [x, y, button] = __fltk_ginput__ (f, n = -1)
-
-  if (isempty (get (f, "currentaxes")))
-    error ("ginput: must have at least one axes");
-  endif
-
-  x = y = button = [];
-  ginput_aggregator (0, 0, 0, 0);
-
-  unwind_protect
-
-    orig_windowbuttondownfcn = get (f, "windowbuttondownfcn");
-    set (f, "windowbuttondownfcn", @ginput_windowbuttondownfcn);
-
-    orig_ginput_keypressfcn = get (f, "keypressfcn");
-    set (f, "keypressfcn", @ginput_keypressfcn);
-
-    while (true)
-      __fltk_redraw__ ();
-
-      ## Release CPU.
-      sleep (0.01);
-
-      [x, y, n0, button] = ginput_aggregator (-1, 0, 0, 0);
-      if (n0 == n || n0 < 0)
-        break;
-      endif
-    endwhile
-
-  unwind_protect_cleanup
-    set (f, "windowbuttondownfcn", orig_windowbuttondownfcn);
-    set (f, "keypressfcn", orig_ginput_keypressfcn);
-  end_unwind_protect
-
-endfunction
-
-function [x, y, n, button] = ginput_aggregator (mode, xn, yn, btn)
-  persistent x y n button;
-
-  if (mode == 0)
-    ## Initialize.
-    x = [];
-    y = [];
-    button = [];
-    n = 0;
-  elseif (mode == 1)
-    ## Accept mouse button or key press.
-    x = [x; xn];
-    y = [y; yn];
-    button = [button; btn];
-    n += 1;
-  elseif (mode == 2)
-    ## The end due to Enter.
-    n = -1;
- endif
-endfunction
-
-function ginput_windowbuttondownfcn (src, data)
-  point = get (get (src,"currentaxes"), "currentpoint");
-  ## FIXME -- How to get the actual mouse button pressed (1,2,3) into
-  ## "button"?
-  button = 1;
-  ginput_aggregator (1, point(1,1), point(2,1), button);
-endfunction
-
-function ginput_keypressfcn (src, evt)
-  point = get (get (src, "currentaxes"), "currentpoint");
-  ## FIXME -- use evt.Key or evt.Character?
-  key = evt.Key;
-  if (key == 10)
-    ## Enter key.
-    ginput_aggregator (2, point(1,1), point(2,1), key);
-  else
-    ginput_aggregator (1, point(1,1), point(2,1), key);
-  endif
-endfunction
-
--- a/scripts/plot/__fltk_print__.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,161 +0,0 @@
-## Copyright (C) 2010-2011 Shai Ayal
-##
-## 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} {} __fltk_print__ (@var{@dots{}})
-## Undocumented internal function.
-## @end deftypefn
-
-function opts = __fltk_print__ (opts)
-
-  dos_shell = (ispc () && ! isunix ());
-
-  figure (opts.figure);
-  drawnow ("expose");
-  __fltk_redraw__ ();
-
-  if (! isempty (opts.fig2dev_binary))
-    ## fig2dev is prefered for conversion to emf
-    fig2dev_devices = {"pstex", "mf", "emf"};
-  else
-    fig2dev_devices = {"pstex", "mf"};
-  endif
-
-  gl2ps_device = {};
-  pipeline = {};
-  switch (lower (opts.devopt))
-  case {"eps", "eps2", "epsc", "epsc2"}
-    ## format GL2PS_EPS
-    gl2ps_device = {"eps"};
-    ## FIXME - use epstool to tighten bbox and provide preview.
-    pipeline = {opts.epstool_cmd(opts, "-", opts.name)};
-  case {"epslatex", "pslatex", "pdflatex", "epslatexstandalone", ...
-        "pslatexstandalone", "pdflatexstandalone"}
-    ## format GL2PS_TEX
-    n = find (opts.devopt == "l", 1);
-    suffix = opts.devopt(1:n-1);
-    dot = find (opts.name == ".", 1, "last");
-    if ((! isempty (dot))
-        && any (strcmpi (opts.name(dot:end), ...
-                {".eps", ".ps", ".pdf", ".tex", "."})))
-      name = opts.name(1:dot-1);
-      if (dot < numel (opts.name)
-          && any (strcmpi (opts.name(dot+1:end), {"eps", "ps", "pdf"})))
-        ## If user provides eps/ps/pdf suffix, use it.
-        suffix = opts.name(dot+1:end);
-      endif
-    elseif (dot == numel (opts.name))
-      name = opts.name;
-    endif
-    gl2ps_device = {sprintf("%snotxt", lower (suffix))};
-    gl2ps_device{2} = "tex";
-    if (dos_shell)
-      ## FIXME - this will only work on MinGW with the MSYS shell
-      pipeline = {sprintf("cat > %s-inc.%s", name, suffix)};
-      pipeline{2} = sprintf ("cat > %s.tex", name);
-    else
-      pipeline = {sprintf("cat > %s-inc.%s", name, suffix)};
-      pipeline{2} = sprintf ("cat > %s.tex", name);
-    endif
-  case "tikz"
-    ## format GL2PS_PGF
-    gl2ps_device = {"pgf"};
-    pipeline = {sprintf("cat > %s", opts.name)};
-  case "svg"
-    ## format GL2PS_SVG
-    gl2ps_device = {"svg"};
-    pipeline = {sprintf("cat > %s", opts.name)};
-  case fig2dev_devices
-    cmd_pstoedit = opts.pstoedit_cmd (opts, "fig");
-    cmd_fig2dev = opts.fig2dev_cmd (opts, opts.devopt);
-    if (strcmp (opts.devopt, "pstex"))
-      [~, ~, ext] = fileparts (opts.name);
-      if (any (strcmpi (ext, {".ps", ".tex", "."})))
-        opts.name = opts.name(1:end-numel(ext));
-      endif
-      opts.name = strcat (opts.name, ".ps");
-      cmd = sprintf ("%s | %s > %s", cmd_pstoedit, cmd_fig2dev, opts.name);
-      gl2ps_device = {"eps"};
-      pipeline = {cmd};
-      cmd_fig2dev = opts.fig2dev_cmd (opts, "pstex_t");
-      gl2ps_device{2} = "eps";
-      pipeline{2} = sprintf ("%s | %s > %s", cmd_pstoedit,
-                             cmd_fig2dev, strrep(opts.name, ".ps", ".tex"));
-    else
-      cmd = sprintf ("%s | %s > %s", cmd_pstoedit, cmd_fig2dev, opts.name);
-      gl2ps_device = {"eps"};
-      pipeline = {cmd};
-    endif
-  case "aifm"
-    cmd = opts.pstoedit_cmd (opts, "ps2ai");
-    gl2ps_device = {"eps"};
-    pipeline = {sprintf("%s > %s", cmd, opts.name)};
-  case {"dxf", "emf", "fig", "hpgl"}
-    cmd = opts.pstoedit_cmd (opts);
-    gl2ps_device = {"eps"};
-    pipeline = {sprintf("%s > %s", cmd, opts.name)};
-  case {"corel", "gif"}
-    error ("print:unsupporteddevice",
-           "print.m: %s output is not available for the FLTK graphics toolkit",
-           upper (opts.devopt));
-  case opts.ghostscript.device
-    opts.ghostscript.source = "-";
-    opts.ghostscript.output = opts.name;
-    if (opts.send_to_printer)
-      opts.unlink(strcmp (opts.unlink, opts.ghostscript.output)) = [];
-      opts.ghostscript.output = "-";
-    endif
-    [cmd_gs, cmd_cleanup] = __ghostscript__ (opts.ghostscript);
-    if (opts.send_to_printer || isempty (opts.name))
-      cmd_lpr = opts.lpr_cmd (opts);
-      cmd = sprintf("%s | %s", cmd_gs, cmd_lpr);
-    else
-      cmd = sprintf("%s", cmd_gs);
-    endif
-    if (! isempty (cmd_cleanup))
-      gl2ps_device = {"eps"};
-      if (dos_shell)
-        pipeline = {sprintf("%s & %s", cmd, cmd_cleanup)};
-      else
-        pipeline = {sprintf("%s ; %s", cmd, cmd_cleanup)};
-      endif
-    else
-      gl2ps_device = {"eps"};
-      pipeline = {cmd};
-    endif
-  otherwise
-    error (sprintf ("print:no%soutput", opts.devopt),
-           "print.m: %s output is not available for GL2PS output",
-           upper (opts.devopt));
-  endswitch
-
-  opts.pipeline = pipeline;
-
-  for n = 1:numel(pipeline)
-    if (opts.debug)
-      fprintf ("fltk-pipeline: '%s'\n", pipeline{n});
-    endif
-    drawnow (gl2ps_device{n}, strcat('|',pipeline{n}));
-  endfor
-
-  if (! isempty (strfind (opts.devopt, "standalone")))
-    opts.latex_standalone (opts);
-  endif
-
-endfunction
-
--- a/scripts/plot/__gnuplot_drawnow__.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/__gnuplot_drawnow__.m	Tue Sep 20 15:38:24 2011 -0400
@@ -386,3 +386,7 @@
     endif
   endif
 endfunction
+
+
+## No test needed for internal helper function.
+%!assert (1)
--- a/scripts/plot/__gnuplot_get_var__.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,161 +0,0 @@
-## Copyright (C) 2009-2011 Ben Abbott
-##
-## 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} {@var{value} =} __gnuplot_get_var__ (@var{h}, @var{name}, @var{fmt})
-## Undocumented internal function.
-## @end deftypefn
-
-## Author: Ben Abbott <bpabbott@mac.com>
-## Created: 2009-02-07
-
-function gp_var_value = __gnuplot_get_var__ (h, gp_var_name, fmt)
-
-  if (nargin == 0)
-    h = gcf ();
-  endif
-  if (nargin < 2)
-    print_usage ();
-  endif
-  if (nargin < 3)
-    fmt = '';
-  endif
-
-  if (numel (h) == 1 && isfigure (h))
-    if (isempty (get (gcf, "__plot_stream__")))
-      ostream = __gnuplot_open_stream__ (2, h);
-    else
-      ostream = get (h, "__plot_stream__");
-    endif
-  else
-    ostream = h;
-  endif
-  if (numel (ostream) < 1)
-    error ("__gnuplot_get_var__: stream to gnuplot not open");
-  elseif (ispc ())
-    if (numel (ostream) == 1)
-      error ("__gnuplot_get_var__: Need mkfifo that is not implemented under Windows");
-    endif
-    use_mkfifo = false;
-    istream = ostream(2);
-    ostream = ostream(1);
-  else
-    use_mkfifo = true;
-    ostream = ostream(1);
-  endif
-
-  if (use_mkfifo)
-    gpin_name = tmpnam ();
-
-    ## Mode: 6*8*8 ==  0600
-    [err, msg] = mkfifo (gpin_name, 6*8*8);
-
-    if (err != 0)
-      error ("__gnuplot_get_var__: Can not make fifo (%s)", msg);
-    endif
-  endif
-
-  gp_var_name = strtrim (gp_var_name);
-  n = min (strfind (gp_var_name, " "), strfind (gp_var_name, ",")) - 1;
-  if (isempty (n))
-    n = numel (gp_var_name);
-  endif
-
-  unwind_protect
-
-    ## Notes: Variables may be undefined if user closes gnuplot by "q"
-    ## or Alt-F4. Further, this abrupt close also requires the leading
-    ## "\n" on the next line.
-    if (use_mkfifo)
-      fprintf (ostream, "\nset print \"%s\";\n", gpin_name);
-      fflush (ostream);
-      [gpin, err] = fopen (gpin_name, "r");
-      if (err != 0)
-        ## Try a second time, and then give an error.
-        [gpin, err] = fopen (gpin_name, "r");
-      endif
-      if (err != 0)
-        error ("__gnuplot_get_var__: can not open fifo");
-      endif
-      gp_cmd = sprintf ("\nif (exists(\"%s\")) print %s; else print NaN\n",
-                        gp_var_name(1:n), gp_var_name);
-      fputs (ostream, gp_cmd);
-
-      ## Close output file, to force it to be flushed
-      fputs (ostream, "set print;\n");
-      fflush (ostream);
-
-      ## Now read from fifo.
-      reading = true;
-      str = {};
-      while (reading)
-        str{end+1} = fgets (gpin);
-        if (isnumeric (str{end}) && (str{end} == -1))
-          reading = false;
-          str = str(1:(end-1));
-        endif
-      endwhile
-      str = strcat (str{:});
-      fclose (gpin);
-    else
-      ## Direct gnuplot to print to <STDOUT>
-      fprintf (ostream, "set print \"-\";\n");
-      fflush (ostream);
-      gp_cmd = sprintf ("\nif (exists(\"%s\")) print \"OCTAVE: \", %s; else print NaN\n",
-                        gp_var_name(1:n), gp_var_name);
-      fputs (ostream, gp_cmd);
-      fflush (ostream);
-      ## Direct gnuplot to print to <STDERR>
-      fputs (ostream, "set print;\n");
-      fflush (ostream);
-
-      str = {};
-      while (isempty (str))
-        str = char (fread (istream)');
-        if (isempty (str))
-          sleep (0.05);
-        else
-          str = regexp (str, 'OCTAVE:.*', "match");
-          str = str{end}(8:end);
-        endif
-        fclear (istream);
-      endwhile
-    endif
-
-    ## Strip out EOLs and the continuation character "|"
-    str(str=="\n") = "";
-    str(str=="\r") = "";
-    n_continue = strfind (str, " \\ ");
-    if (! isempty (n_continue))
-      str(n_continue+1) = "";
-    endif
-
-    if (isempty (fmt))
-      gp_var_value = strtrim (str);
-    else
-      gp_var_value = sscanf (str, fmt);
-    endif
-
-  unwind_protect_cleanup
-    if (use_mkfifo)
-      unlink (gpin_name);
-    endif
-  end_unwind_protect
-
-endfunction
-
--- a/scripts/plot/__gnuplot_ginput__.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,154 +0,0 @@
-## Copyright (C) 2004-2011 Petr Mikulik
-##
-## 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} {[@var{x}, @var{y}, @var{buttons}] =} __gnuplot_ginput__ (@var{f}, @var{n})
-## Undocumented internal function.
-## @end deftypefn
-
-## This is ginput.m implementation for gnuplot and X11.
-## It requires gnuplot 4.1 and later.
-
-## This file initially bore the copyright statement
-## Petr Mikulik
-## History: June 2006; August 2005; June 2004; April 2004
-## License: public domain
-
-function [x, y, button] = __gnuplot_ginput__ (f, n)
-
-  ostream = get (f, "__plot_stream__");
-  if (numel (ostream) < 1)
-    error ("ginput: stream to gnuplot not open");
-  elseif (ispc ())
-    if (numel (ostream) == 1)
-      error ("ginput: Need mkfifo that is not implemented under Windows");
-    endif
-    use_mkfifo = false;
-    istream = ostream(2);
-    ostream = ostream(1);
-  else
-    use_mkfifo = true;
-    ostream = ostream(1);
-  endif
-
-  if (compare_versions (__gnuplot_version__ (), "4.0", "<="))
-    error ("ginput: version %s of gnuplot not supported", gnuplot_version ());
-  endif
-
-  if (nargin == 1)
-    x = zeros (100, 1);
-    y = zeros (100, 1);
-    button = zeros (100, 1);
-  else
-    x = zeros (n, 1);
-    y = zeros (n, 1);
-    button = zeros (n, 1);
-  endif
-
-  if (use_mkfifo)
-    gpin_name = tmpnam ();
-
-    ##Mode: 6*8*8 ==  0600
-    [err, msg] = mkfifo (gpin_name, 6*8*8);
-
-    if (err != 0)
-      error ("ginput: Can not open fifo (%s)", msg);
-    endif
-  endif
-
-  unwind_protect
-
-    k = 0;
-    while (true)
-      k++;
-
-      ## Notes: MOUSE_* can be undefined if user closes gnuplot by "q"
-      ## or Alt-F4. Further, this abrupt close also requires the leading
-      ## "\n" on the next line.
-      if (use_mkfifo)
-        fprintf (ostream, "set print \"%s\";\n", gpin_name);
-        fflush (ostream);
-        [gpin, err] = fopen (gpin_name, "r");
-        if (err != 0)
-          error ("ginput: Can not open fifo (%s)", msg);
-        endif
-        fputs (ostream, "pause mouse any;\n\n");
-        fputs (ostream, "\nif (exists(\"MOUSE_KEY\") && exists(\"MOUSE_X\")) print MOUSE_X, MOUSE_Y, MOUSE_KEY; else print \"0 0 -1\"\n");
-
-        ## Close output file, to force it to be flushed
-        fputs (ostream, "set print;\n");
-        fflush (ostream);
-
-        ## Now read from fifo.
-        [x(k), y(k), button(k), count] = fscanf (gpin, "%f %f %d", "C");
-        fclose (gpin);
-      else
-        fprintf (ostream, "set print \"-\";\n");
-        fflush (ostream);
-        fputs (ostream, "pause mouse any;\n\n");
-        fputs (ostream, "\nif (exists(\"MOUSE_KEY\") && exists(\"MOUSE_X\")) print \"OCTAVE: \", MOUSE_X, MOUSE_Y, MOUSE_KEY; else print \"0 0 -1\"\n");
-
-        ## Close output file, to force it to be flushed
-        fputs (ostream, "set print;\n");
-        fflush (ostream);
-
-        str = {};
-        while (isempty (str))
-          str = char (fread (istream)');
-          if (isempty (str))
-            sleep (0.05);
-          else
-            str = regexp (str, 'OCTAVE:\s+[-+.\d]+\s+[-+.\d]+\s+\d*', 'match');
-          endif
-          fclear (istream);
-        endwhile
-        [x(k), y(k), button(k), count] = sscanf (str{end}(8:end), "%f %f %d", "C");
-      endif
-
-      if ([x(k), y(k), button(k)] == [0, 0, -1])
-        ## Mousing not active (no plot yet).
-        break;
-      endif
-
-      if (nargin > 1)
-        ## Input argument n was given => stop when k == n.
-        if (k == n)
-          break;
-        endif
-      else
-        ## Input argument n not given => stop when hitting a return key.
-        ## if (button(k) == 0x0D || button(k) == 0x0A)
-        ##   ## hit Return or Enter
-        if (button(k) == 0x0D)
-          ## hit Return
-          x(k:end) = [];
-          y(k:end) = [];
-          button(k:end) = [];
-          break;
-        endif
-      endif
-    endwhile
-
-  unwind_protect_cleanup
-    if (use_mkfifo)
-      unlink (gpin_name);
-    endif
-  end_unwind_protect
-
-endfunction
-
--- a/scripts/plot/__gnuplot_has_feature__.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-## Copyright (C) 2009-2011 Ben Abbott
-##
-## 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} {@var{has_feature} =} __gnuplot_has_feature__ (@var{feature})
-## Undocumented internal function.
-## @end deftypefn
-
-## Author: Ben Abbott <bpabbott@mac.com>
-## Created: 2009-01-27
-
-function res = __gnuplot_has_feature__ (feature)
-  persistent features has_features
-  features = {"x11_figure_position",
-              "wxt_figure_size",
-              "transparent_patches",
-              "transparent_surface",
-              "epslatex_implies_eps_filesuffix",
-              "epslatexstandalone_terminal",
-              "screen_coordinates_for_{lrtb}margin",
-              "variable_GPVAL_TERMINALS",
-              "key_has_font_properties"};
-
-  if (isempty (has_features))
-    try
-      gnuplot_version = __gnuplot_version__ ();
-    catch
-      ## Don't throw an error if gnuplot isn't installed
-      gnuplot_version = "0.0.0";
-    end_try_catch
-    versions = {"4.2.5", "4.4", "4.4", "4.4", "4.2", "4.2", "4.4", "4.4", "4.4"};
-    operators = {">=", ">=", ">=", ">=", ">=", ">=", ">=", ">=", ">="};
-    have_features = logical (zeros (size (features)));
-    for n = 1 : numel (have_features)
-      has_features(n) = compare_versions (gnuplot_version, versions{n}, operators{n});
-    endfor
-  endif
-
-  n = find (strcmpi (feature, features));
-  if (isempty (n))
-    res = NaN;
-  else
-    res = has_features(n);
-  endif
-endfunction
-
--- a/scripts/plot/__gnuplot_open_stream__.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-## Copyright (C) 2009-2011 Ben Abbott
-##
-## 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} {@var{stream} =} __gnuplot_open_stream__ (@var{npipes}, @var{h})
-## Undocumented internal function.
-## @end deftypefn
-
-## Author: Ben Abbott <bpabbott@mac.com>
-## Created: 2009-04-11
-
-function plot_stream = __gnuplot_open_stream__ (npipes, h)
-  [prog, args] = gnuplot_binary ();
-  if (npipes > 1)
-    [plot_stream(1), plot_stream(2), pid] = popen2 (prog, args{:});
-    if (pid < 0)
-      error ("__gnuplot_open_stream__: failed to open connection to gnuplot");
-    else
-      plot_stream(3) = pid;
-    endif
-  else
-    plot_stream = popen (sprintf ("%s ", prog, args{:}), "w");
-    if (plot_stream < 0)
-      error ("__gnuplot_open_stream__: failed to open connection to gnuplot");
-    endif
-  endif
-  if (nargin > 1)
-    set (h, "__plot_stream__", plot_stream);
-  endif
-endfunction
--- a/scripts/plot/__gnuplot_print__.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,300 +0,0 @@
-## Copyright (C) 1999-2011 Daniel Heiserer
-## Copyright (C) 2001 Laurent Mazet
-##
-## 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} {} __gnuplot_print__ (@var{@dots{}})
-## Undocumented internal function.
-## @end deftypefn
-
-## Author: Daniel Heiserer <Daniel.heiserer@physik.tu-muenchen.de>
-## Adapted-By: jwe
-
-function opts = __gnuplot_print__ (opts)
-
-  dos_shell = (ispc () && ! isunix ());
-
-  if (isempty (opts.fontsize))
-    ## If no fontsize, determine the nominal axes fontsize.
-    defaultfontsize = get (0, "defaultaxesfontsize");
-    axesfontsize = get (findobj (opts.figure, "type", "axes"), "fontsize");
-    if (iscell (axesfontsize))
-      axesfontsize = round (median (cell2mat (axesfontsize)));
-    endif
-    if (isempty (axesfontsize))
-      opts.fontsize = defaultfontsize;
-    else
-      opts.fontsize = axesfontsize;
-    endif
-  endif
-  ## The axes-label and tick-label spacing is determined by
-  ## the font spec given in "set terminal ..."
-  gp_opts = font_spec (opts);
-
-  pipeline = "";
-
-  switch (lower (opts.devopt))
-  case {"eps", "eps2", "epsc", "epsc2"}
-    if (any (strcmp (opts.devopt, {"eps", "epsc"})))
-      gp_opts = sprintf ("%s level1", gp_opts);
-    endif
-    if (opts.tight_flag || ! isempty (opts.preview))
-      tmp_file = strcat (tmpnam (), ".eps");
-      eps_drawnow (opts, tmp_file, gp_opts);
-      if (dos_shell)
-        cleanup = sprintf (" & del %s", strrep (tmp_file, '/', '\'));
-      else
-        cleanup = sprintf (" ; rm %s", tmp_file);
-      endif
-      pipeline = {sprintf("%s %s",
-                          opts.epstool_cmd (opts, tmp_file, opts.name),
-                          cleanup)};
-    else
-      eps_drawnow (opts, opts.name, gp_opts);
-    endif
-  case {"epslatex", "pslatex", "pstex", "epslatexstandalone"}
-    dot = find (opts.name == ".", 1, "last");
-    if ((! isempty (dot))
-        && any (strcmpi (opts.name(dot:end),
-                {".eps", ".ps", ".pdf", ".tex", "."})))
-      name = opts.name(1:dot-1);
-    endif
-    if (strfind (opts.devopt, "standalone"))
-      term = sprintf ("%s ",
-                      strrep (opts.devopt, "standalone", " standalone"));
-    else
-      term = sprintf ("%s ", opts.devopt);
-    endif
-    if (__gnuplot_has_feature__ ("epslatex_implies_eps_filesuffix"))
-      suffix = "tex";
-    else
-      %% Gnuplot 4.0 wants a ".eps" suffix.
-      suffix = "eps";
-    endif
-    local_drawnow (sprintf ("%s %s", term, gp_opts),
-                   strcat (name, ".", suffix), opts);
-  case "tikz"
-    if (__gnuplot_has_terminal__ ("tikz"))
-      local_drawnow (sprintf ("lua tikz %s", gp_opts), opts.name, opts);
-    else
-      error (sprintf ("print:no%soutput", opts.devopt),
-             "print.m: '%s' output is not available for gnuplot-%s",
-             upper (opts.devopt), __gnuplot_version__ ());
-    endif
-  case "svg"
-    local_drawnow (sprintf ("svg dynamic %s", gp_opts), opts.name, opts);
-  case {"aifm", "corel", "eepic", "emf", "fig"}
-    local_drawnow (sprintf ("%s %s", opts.devopt, gp_opts), opts.name, opts);
-  case {"pdfcairo", "pngcairo"}
-    if (__gnuplot_has_terminal__ (opts.devopt))
-      local_drawnow (sprintf ("%s %s", opts.devopt, gp_opts), opts.name, opts);
-    else
-      error (sprintf ("print:no%soutput", opts.devopt),
-             "print.m: '%s' output is not available for gnuplot-%s",
-             upper (opts.devopt), __gnuplot_version__ ());
-    endif
-  case {"canvas", "dxf", "hpgl", "mf", "gif", "pstricks", "texdraw"}
-    local_drawnow (sprintf ("%s %s", opts.devopt, gp_opts), opts.name, opts);
-  case opts.ghostscript.device
-    gp_opts = font_spec (opts, "devopt", "eps");
-    opts.ghostscript.output = opts.name;
-    opts.ghostscript.source = strcat (tmpnam (), ".eps");
-    eps_drawnow (opts, opts.ghostscript.source, gp_opts);
-    [cmd_gs, cmd_cleanup] = __ghostscript__ (opts.ghostscript);
-    if (opts.send_to_printer || isempty (opts.name))
-      cmd_lpr = opts.lpr_cmd (opts);
-      cmd = sprintf ("%s | %s", cmd_gs, cmd_lpr);
-    else
-      cmd = sprintf ("%s", cmd_gs);
-    endif
-    if (dos_shell)
-      cmd = sprintf ("%s & del %s", cmd, strrep (opts.ghostscript.source, '/', '\'));
-    else
-      cmd = sprintf ("%s ; rm %s", cmd, opts.ghostscript.source);
-    endif
-    if (! isempty (cmd_cleanup))
-      if (dos_shell)
-        pipeline = {sprintf("%s & %s", cmd, cmd_cleanup)};
-      else
-        pipeline = {sprintf("%s ; %s", cmd, cmd_cleanup)};
-      endif
-    else
-      pipeline = {cmd};
-    endif
-  otherwise
-    error (sprintf ("print:no%soutput", opts.devopt),
-           "print.m: %s output is not available for the Gnuplot graphics toolkit",
-           upper (opts.devopt));
-  endswitch
-
-
-  opts.pipeline = pipeline;
-
-  for n = 1:numel(pipeline)
-    if (opts.debug)
-      fprintf ("gnuplot-pipeline: '%s'\n", pipeline{n});
-    endif
-    [status, output] = system (pipeline{n});
-    if (status)
-      fprintf ("%s\n%s\n%s\n",
-               "---------- output begin ----------",
-               output,
-               "----------- output end -----------");
-      error ("gnuplot:failedpipe", "print: failed to print");
-    endif
-  endfor
-
-endfunction
-
-function eps_drawnow (opts, epsfile, gp_opts)
-  [h, fontsize] = get_figure_text_objs (opts);
-  unwind_protect
-    for n = 1:numel(h)
-      set (h(n), "fontsize", 2 * fontsize{n});
-    endfor
-    local_drawnow (sprintf ("postscript eps %s", gp_opts), epsfile, opts);
-  unwind_protect_cleanup
-    for n = 1:numel(h)
-      set (h(n), "fontsize", fontsize{n});
-    endfor
-  end_unwind_protect
-endfunction
-
-function local_drawnow (term, file, opts)
-  if (opts.use_color < 0)
-    mono = true;
-  else
-    mono = false;
-  endif
-  figure (opts.figure);
-  if (isempty (opts.debug_file) || ! opts.debug)
-    drawnow (term, file, mono);
-  else
-    drawnow (term, file, mono, opts.debug_file);
-  endif
-endfunction
-
-function f = font_spec (opts, varargin)
-  for n = 1:2:numel(varargin)
-    opts.(varargin{n}) = varargin{n+1};
-  endfor
-  f = "";
-  switch (opts.devopt)
-  case "cgm"
-    if (! isempty (opts.font) && ! isempty (opts.fontsize))
-      f = sprintf ("font ""%s,%d""", opts.font, opts.fontsize);
-    elseif (! isempty (opts.font))
-      f = sprintf ("font ""%s""", opts.font);
-    elseif (! isempty (opts.fontsize))
-      f = sprintf ("%d", opts.fontsize);
-    endif
-  case {"eps", "eps2", "epsc", "epsc2"}
-    ## Gnuplot renders fonts as half their specification, which
-    ## results in a tight spacing for the axes-labels and tick-labels.
-    ## Compensate for the half scale. This will produce the proper
-    ## spacing for the requested fontsize.
-    if (! isempty (opts.font) && ! isempty (opts.fontsize))
-      f = sprintf ("font ""%s,%d""", opts.font, 2 * opts.fontsize);
-    elseif (! isempty (opts.font))
-      f = sprintf ("font ""%s""", opts.font);
-    elseif (! isempty (opts.fontsize))
-      f = sprintf ("%d", 2 * opts.fontsize);
-    endif
-  case "svg"
-    if (! isempty (opts.font) && ! isempty (opts.fontsize))
-      fontsize = round (opts.fontsize * 0.75);
-      f = sprintf ("fname ""%s"" fsize %d", opts.font, fontsize);
-    elseif (! isempty (opts.font))
-      f = sprintf ("fname ""%s""", opts.font);
-    elseif (! isempty (opts.fontsize))
-      fontsize = round (opts.fontsize * 0.75);
-      f = sprintf ("%s fsize %d", f, fontsize);
-    endif
-  case "pdf"
-    if (! isempty (opts.font) && ! isempty (opts.fontsize))
-      f = sprintf ("font ""%s,%d""", opts.font, opts.fontsize);
-    elseif (! isempty (opts.font))
-      f = sprintf ("font ""%s""", opts.font);
-    elseif (! isempty (opts.fontsize))
-      f = sprintf ("fsize %d", f, opts.fontsize);
-    endif
-  case {"pdfcairo", "pngcairo"}
-    if (! isempty (opts.font))
-      f = sprintf ("font ""%s""", opts.font);
-    endif
-  case {"epslatex", "epslatexstandalone"}
-    if (! isempty (opts.font) && ! isempty (opts.fontsize))
-      f = sprintf ("font ""%s,%d""", opts.font, opts.fontsize);
-    elseif (! isempty (opts.font))
-      f = sprintf ("font ""%s""", opts.font);
-    elseif (! isempty (opts.fontsize))
-      f = sprintf ("%d", opts.fontsize);
-    endif
-  case "pslatex"
-    if (! isempty (opts.fontsize))
-      f = sprintf ("%d", opts.fontsize);
-    endif
-  case {"gif", "jpeg", "png"}
-    if (! isempty (opts.font) && ! isempty (opts.fontsize))
-      f = sprintf ("font ""%s ,%d""", opts.font, opts.fontsize);
-    elseif (! isempty (opts.font))
-      f = sprintf ("font ""%s""", opts.font);
-    elseif (! isempty (opts.fontsize))
-      f = sprintf ("font ""%d""", opts.fontsize);
-    endif
-  case "emf"
-    if (! isempty (opts.font) && ! isempty (opts.fontsize))
-      f = sprintf ("""%s"" %d", opts.font, opts.fontsize);
-    elseif (! isempty (opts.font))
-      f = sprintf ("""%s""", opts.font);
-    elseif (! isempty (opts.fontsize))
-      f = sprintf ("%d", opts.fontsize);
-    endif
-  case "canvas"
-    if (! isempty (opts.fontsize))
-      f = sprintf ("fsize %d", opts.fontsize);
-    endif
-  case {"aifm", "corel"}
-    if (! isempty (opts.font) && ! isempty (opts.fontsize))
-      f = sprintf ("%s %d", opts.font, opts.fontsize);
-    elseif (! isempty (opts.font))
-      f = sprintf ("%s", opts.font);
-    elseif (! isempty (opts.fontsize))
-      f = sprintf ("%d", opts.fontsize);
-    endif
-  case "fig"
-    if (! isempty (opts.font) && ! isempty (opts.fontsize))
-      f = sprintf ("font %s fontsize %d", opts.font, opts.fontsize);
-    elseif (! isempty (opts.font))
-      f = sprintf ("font %s", opts.font);
-    elseif (! isempty (opts.fontsize))
-      f = sprintf ("fontsize %d", opts.fontsize);
-    endif
-  endswitch
-endfunction
-
-function [h, fontsize] = get_figure_text_objs (opts)
-  h = findall (opts.figure, "-property", "fontsize");
-  fontsize = get (h, "fontsize");
-  switch (numel (fontsize))
-  case 0
-    fontsize = {};
-  case 1
-    fontsize = {fontsize};
-  endswitch
-endfunction
--- a/scripts/plot/__gnuplot_version__.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-## Copyright (C) 2006-2011 Daniel Sebald
-##
-## 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} {@var{version} =} __gnuplot_version__ ()
-## Undocumented internal function.
-## @end deftypefn
-
-## Return the version of gnuplot we are using.  Note that we do not
-## attempt to handle the case of the user switching to different
-## versions of gnuplot during the same session.
-
-function version = __gnuplot_version__ ()
-
-  persistent __version__ = "";
-
-  if (isempty (__version__))
-    [status, output] = system (sprintf ("\"%s\" --version", gnuplot_binary ()));
-    if (status != 0)
-      ## This message ends in a newline so that the traceback messages
-      ## are skipped and people might actually see the message, read it,
-      ## comprehend it, actually take the advice it gives, and stop
-      ## asking us why plotting fails when gnuplot is not found.
-      error ("you must have gnuplot installed to display graphics; if you have gnuplot installed in a non-standard location, see the 'gnuplot_binary' function\n");
-    endif
-    output = strrep (output, "gnuplot", "");
-    output = strrep (output, "patchlevel", ".");
-    output = strrep (output, "\n", "");
-    output = strrep (output, "\r", "");
-    __version__ = strrep (output, " ", "");
-  endif
-
-  version = __version__;
-
-endfunction
-
--- a/scripts/plot/__go_close_all__.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/__go_close_all__.m	Tue Sep 20 15:38:24 2011 -0400
@@ -26,3 +26,7 @@
 function __go_close_all__ ()
   close ("all", "hidden");
 endfunction
+
+
+## No test needed for internal helper function.
+%!assert (1)
--- a/scripts/plot/__go_draw_axes__.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2484 +0,0 @@
-## Copyright (C) 2005-2011 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} {} __go_draw_axes__ (@var{h}, @var{plot_stream}, @var{enhanced}, @var{mono})
-## Undocumented internal function.
-## @end deftypefn
-
-## Author: jwe
-
-function __go_draw_axes__ (h, plot_stream, enhanced, mono,
-                           bg_is_set, fg_is_set, hlgnd)
-
-  if (nargin >= 4 && nargin <= 7)
-
-    showhiddenhandles = get (0, "showhiddenhandles");
-    unwind_protect
-      set (0, "showhiddenhandles", "on");
-      axis_obj = __get__ (h);
-    unwind_protect_cleanup
-      set (0, "showhiddenhandles", showhiddenhandles);
-    end_unwind_protect
-
-    parent_figure_obj = get (axis_obj.parent);
-    gnuplot_term = __gnuplot_get_var__ (axis_obj.parent, "GPVAL_TERM");
-
-    ## Set to false for plotyy axes.
-    if (strcmp (axis_obj.tag, "plotyy"))
-      ymirror = false;
-    else
-      ymirror = true;
-    endif
-
-    nd = __calc_dimensions__ (h);
-
-    if (strcmp (axis_obj.dataaspectratiomode, "manual")
-        && strcmp (axis_obj.xlimmode, "manual")
-        && strcmp (axis_obj.ylimmode, "manual"))
-      ## All can't be "manual"
-      axis_obj.plotboxaspectratiomode = "auto";
-    endif
-
-    if (strcmp (axis_obj.dataaspectratiomode, "manual")
-        && strcmp (axis_obj.xlimmode, "manual")
-        && strcmp (axis_obj.ylimmode, "manual")
-        && (nd == 2 || all (mod (axis_obj.view, 90) == 0)))
-      ## FIXME - adjust plotboxaspectratio to respect other
-      fpos = get (axis_obj.parent, "position");
-      apos = axis_obj.position;
-    endif
-
-    pos = __actual_axis_position__ (h);
-
-    if (strcmpi (axis_obj.dataaspectratiomode, "manual"))
-      dr = axis_obj.dataaspectratio;
-      if (nd == 2 || all (mod (axis_obj.view, 90) == 0))
-        dr = dr(1) / dr(2);
-      else
-        ## FIXME - need to properly implement 3D
-        dr = mean (dr(1:2)) / dr(3);
-      endif
-    else
-      dr = 1;
-    endif
-
-    if (strcmp (axis_obj.activepositionproperty, "position"))
-      if (__gnuplot_has_feature__ ("screen_coordinates_for_{lrtb}margin"))
-        if (nd == 2 || all (mod (axis_obj.view, 90) == 0))
-          x = [1, 1];
-        else
-          ## 3D plots need to be sized down to fit in the window.
-          x = 1.0 ./ sqrt([2, 2.5]);
-        endif
-        fprintf (plot_stream, "set tmargin screen %.15g;\n",
-                 pos(2)+pos(4)/2+x(2)*pos(4)/2);
-        fprintf (plot_stream, "set bmargin screen %.15g;\n",
-                 pos(2)+pos(4)/2-x(2)*pos(4)/2);
-        fprintf (plot_stream, "set lmargin screen %.15g;\n",
-                 pos(1)+pos(3)/2-x(1)*pos(3)/2);
-        fprintf (plot_stream, "set rmargin screen %.15g;\n",
-                 pos(1)+pos(3)/2+x(1)*pos(3)/2);
-        sz_str = "";
-      else
-        fprintf (plot_stream, "set tmargin 0;\n");
-        fprintf (plot_stream, "set bmargin 0;\n");
-        fprintf (plot_stream, "set lmargin 0;\n");
-        fprintf (plot_stream, "set rmargin 0;\n");
-
-        if (nd == 3 && all (axis_obj.view == [0, 90]))
-          ## FIXME -- Kludge to allow colorbar to be added to a pcolor() plot
-          pos(3:4) = pos(3:4) * 1.4;
-          pos(1:2) = pos(1:2) - pos(3:4) * 0.125;
-        endif
-
-        fprintf (plot_stream, "set origin %.15g, %.15g;\n", pos(1), pos(2));
-
-        if (strcmpi (axis_obj.dataaspectratiomode, "manual"))
-          sz_str = sprintf ("set size ratio %.15g", -dr);
-        else
-          sz_str = "set size noratio";
-        endif
-        sz_str = sprintf ("%s %.15g, %.15g;\n", sz_str, pos(3), pos(4));
-      endif
-    else ## activepositionproperty == outerposition
-      fprintf (plot_stream, "unset tmargin;\n");
-      fprintf (plot_stream, "unset bmargin;\n");
-      fprintf (plot_stream, "unset lmargin;\n");
-      fprintf (plot_stream, "unset rmargin;\n");
-      fprintf (plot_stream, "set origin %g, %g;\n", pos(1:2));
-      sz_str = "";
-      if (strcmpi (axis_obj.dataaspectratiomode, "manual"))
-        sz_str = sprintf ("ratio %g", -dr);
-      else
-        sz_str = "noratio";
-      endif
-      sz_str = sprintf ("set size %s %g, %g;\n", sz_str, pos(3:4));
-    endif
-    if (! isempty (sz_str))
-      fputs (plot_stream, sz_str);
-    endif
-
-    ## Reset all labels, axis-labels, tick-labels, and title
-    ## FIXME - We should have an function to initialize the axis.
-    ##         Presently, this is dispersed in this function.
-    fputs (plot_stream, "unset label;\n");
-    fputs (plot_stream, "unset xtics;\n");
-    fputs (plot_stream, "unset ytics;\n");
-    fputs (plot_stream, "unset ztics;\n");
-    fputs (plot_stream, "unset x2tics;\n");
-    fputs (plot_stream, "unset x2tics;\n");
-
-    if (! isempty (axis_obj.title))
-      t = get (axis_obj.title);
-      if (isempty (t.string))
-        fputs (plot_stream, "unset title;\n");
-      else
-        [tt, f, s] = __maybe_munge_text__ (enhanced, t, "string");
-        fontspec = create_fontspec (f, s, gnuplot_term);
-        fprintf (plot_stream, "set title \"%s\" %s %s;\n",
-                 undo_string_escapes (tt), fontspec,
-                 __do_enhanced_option__ (enhanced, t));
-      endif
-    endif
-
-    if (! isempty (axis_obj.xlabel))
-      t = get (axis_obj.xlabel);
-      angle = t.rotation;
-      colorspec = get_text_colorspec (axis_obj.xcolor, mono);
-      if (isempty (t.string))
-        fprintf (plot_stream, "unset xlabel;\n");
-        fprintf (plot_stream, "unset x2label;\n");
-      else
-        [tt, f, s] = __maybe_munge_text__ (enhanced, t, "string");
-        fontspec = create_fontspec (f, s, gnuplot_term);
-        if (strcmpi (axis_obj.xaxislocation, "top"))
-          fprintf (plot_stream, "set x2label \"%s\" %s %s %s",
-                   undo_string_escapes (tt), colorspec, fontspec,
-                   __do_enhanced_option__ (enhanced, t));
-        else
-          fprintf (plot_stream, "set xlabel \"%s\" %s %s %s",
-                   undo_string_escapes (tt), colorspec, fontspec,
-                   __do_enhanced_option__ (enhanced, t));
-        endif
-        fprintf (plot_stream, " rotate by %f;\n", angle);
-        if (strcmpi (axis_obj.xaxislocation, "top"))
-          fprintf (plot_stream, "unset xlabel;\n");
-        else
-          fprintf (plot_stream, "unset x2label;\n");
-        endif
-      endif
-    endif
-
-    if (! isempty (axis_obj.ylabel))
-      t = get (axis_obj.ylabel);
-      angle = t.rotation;
-      colorspec = get_text_colorspec (axis_obj.ycolor, mono);
-      if (isempty (t.string))
-        fprintf (plot_stream, "unset ylabel;\n");
-        fprintf (plot_stream, "unset y2label;\n");
-      else
-        [tt, f, s] = __maybe_munge_text__ (enhanced, t, "string");
-        fontspec = create_fontspec (f, s, gnuplot_term);
-        if (strcmpi (axis_obj.yaxislocation, "right"))
-          fprintf (plot_stream, "set y2label \"%s\" %s %s %s",
-                   undo_string_escapes (tt), colorspec, fontspec,
-                   __do_enhanced_option__ (enhanced, t));
-        else
-          fprintf (plot_stream, "set ylabel \"%s\" %s %s %s",
-                   undo_string_escapes (tt), colorspec, fontspec,
-                   __do_enhanced_option__ (enhanced, t));
-        endif
-        fprintf (plot_stream, " rotate by %f;\n", angle);
-        if (strcmpi (axis_obj.yaxislocation, "right"))
-          fprintf (plot_stream, "unset ylabel;\n");
-        else
-          fprintf (plot_stream, "unset y2label;\n");
-        endif
-      endif
-    endif
-
-    if (! isempty (axis_obj.zlabel))
-      t = get (axis_obj.zlabel);
-      angle = t.rotation;
-      colorspec = get_text_colorspec (axis_obj.zcolor, mono);
-      if (isempty (t.string))
-        fputs (plot_stream, "unset zlabel;\n");
-      else
-        [tt, f, s] = __maybe_munge_text__ (enhanced, t, "string");
-        fontspec = create_fontspec (f, s, gnuplot_term);
-        fprintf (plot_stream, "set zlabel \"%s\" %s %s %s",
-                 undo_string_escapes (tt), colorspec, fontspec,
-                 __do_enhanced_option__ (enhanced, t));
-        fprintf (plot_stream, " rotate by %f;\n", angle);
-      endif
-    endif
-
-    if (strcmpi (axis_obj.xaxislocation, "top"))
-      xaxisloc = "x2";
-      xaxisloc_using = "x2";
-    else
-      xaxisloc = "x";
-      xaxisloc_using = "x1";
-      if (strcmpi (axis_obj.xaxislocation, "zero"))
-        fputs (plot_stream, "set xzeroaxis;\n");
-      endif
-    endif
-    if (strcmpi (axis_obj.yaxislocation, "right"))
-      yaxisloc = "y2";
-      yaxisloc_using = "y2";
-    else
-      yaxisloc = "y";
-      yaxisloc_using = "y1";
-      if (strcmpi (axis_obj.yaxislocation, "zero"))
-        fputs (plot_stream, "set yzeroaxis;\n");
-      endif
-    endif
-
-    have_grid = false;
-
-    if (strcmpi (axis_obj.xgrid, "on"))
-      have_grid = true;
-      fprintf (plot_stream, "set grid %stics;\n", xaxisloc);
-    else
-      fprintf (plot_stream, "set grid no%stics;\n", xaxisloc);
-    endif
-
-    if (strcmpi (axis_obj.ygrid, "on"))
-      have_grid = true;
-      fprintf (plot_stream, "set grid %stics;\n", yaxisloc);
-    else
-      fprintf (plot_stream, "set grid no%stics;\n", yaxisloc);
-    endif
-
-    if (strcmpi (axis_obj.zgrid, "on"))
-      have_grid = true;
-      fputs (plot_stream, "set grid ztics;\n");
-    else
-      fputs (plot_stream, "set grid noztics;\n");
-    endif
-
-    if (strcmpi (axis_obj.xminorgrid, "on"))
-      have_grid = true;
-      if (strcmp (axis_obj.xscale, "log"))
-        m = 10;
-      else
-        m = 5;
-      endif
-      fprintf (plot_stream, "set m%stics %d;\n", xaxisloc, m);
-      fprintf (plot_stream, "set grid m%stics;\n", xaxisloc);
-    else
-      fprintf (plot_stream, "set grid nom%stics;\n", xaxisloc);
-    endif
-
-    if (strcmpi (axis_obj.yminorgrid, "on"))
-      have_grid = true;
-      if (strcmp (axis_obj.yscale, "log"))
-        m = 10;
-      else
-        m = 5;
-      endif
-      fprintf (plot_stream, "set m%stics %d;\n", yaxisloc, m);
-      fprintf (plot_stream, "set grid m%stics;\n", yaxisloc);
-    else
-      fprintf (plot_stream, "set grid nom%stics;\n", yaxisloc);
-    endif
-
-    if (strcmpi (axis_obj.zminorgrid, "on"))
-      have_grid = true;
-      if (strcmp (axis_obj.zscale, "log"))
-        m = 10;
-      else
-        m = 5;
-      endif
-      fprintf (plot_stream, "set mztics %d;\n", m);
-      fputs (plot_stream, "set grid mztics;\n");
-    else
-      fputs (plot_stream, "set grid nomztics;\n");
-    endif
-
-    ## The grid front/back/layerdefault option also controls the
-    ## appearance of tics, so it is used even if the grid is absent.
-    if (strcmpi (axis_obj.layer, "top"))
-      fputs (plot_stream, "set grid front;\n");
-      fputs (plot_stream, "set border front;\n");
-    else
-      fputs (plot_stream, "set grid layerdefault;\n");
-      ## FIXME -- the gnuplot help says that "layerdefault" should work
-      ## for set border too, but it fails for me with gnuplot 4.2.5.  So
-      ## use "back" instead.
-      fputs (plot_stream, "set border back;\n");
-    endif
-
-    fprintf (plot_stream, "set grid linewidth %f, linewidth %f;\n",
-             axis_obj.linewidth, axis_obj.linewidth);
-
-    if (! have_grid)
-      fputs (plot_stream, "unset grid;\n");
-    endif
-
-    do_tics (axis_obj, plot_stream, ymirror, mono, gnuplot_term);
-
-    fputs (plot_stream, "unset logscale;\n");
-    xlogscale = strcmpi (axis_obj.xscale, "log");
-    ylogscale = strcmpi (axis_obj.yscale, "log");
-    zlogscale = strcmpi (axis_obj.zscale, "log");
-    if (xlogscale)
-      fprintf (plot_stream, "set logscale %s;\n", xaxisloc);
-    endif
-    if (ylogscale)
-      fprintf (plot_stream, "set logscale %s;\n", yaxisloc);
-    endif
-    if (zlogscale)
-      fputs (plot_stream, "set logscale z;\n");
-    endif
-
-    xautoscale = strcmpi (axis_obj.xlimmode, "auto");
-    yautoscale = strcmpi (axis_obj.ylimmode, "auto");
-    zautoscale = strcmpi (axis_obj.zlimmode, "auto");
-    cautoscale = strcmpi (axis_obj.climmode, "auto");
-    cdatadirect = false;
-    truecolor = false;
-
-    fputs (plot_stream, "set clip two;\n");
-
-    kids = axis_obj.children;
-    ## Remove the axis labels and title from the children, and
-    ## preserved the original order.
-    [jnk, k] = setdiff (kids, [axis_obj.xlabel; axis_obj.ylabel; ...
-                               axis_obj.zlabel; axis_obj.title]);
-    kids = kids (sort (k));
-
-    if (nd == 3)
-      fputs (plot_stream, "set parametric;\n");
-      fputs (plot_stream, "set style data lines;\n");
-      fputs (plot_stream, "set surface;\n");
-      fputs (plot_stream, "unset contour;\n");
-    endif
-
-    data_idx = 0;
-    data = cell ();
-    is_image_data = [];
-    hidden_removal = NaN;
-    view_map = false;
-
-    xlim = axis_obj.xlim;
-    ylim = axis_obj.ylim;
-    zlim = axis_obj.zlim;
-    clim = axis_obj.clim;
-
-    if (! cautoscale && clim(1) == clim(2))
-      clim(2)++;
-    endif
-    addedcmap = [];
-
-    ximg_data = {};
-    ximg_data_idx = 0;
-
-    while (! isempty (kids))
-
-      obj = get (kids(end));
-      if (isfield (obj, "units"))
-        units = obj.units;
-        unwind_protect
-          set (kids(end), "units", "data");
-          obj = get (kids(end));
-        unwind_protect_cleanup
-          set (kids(end), "units", units);
-        end_unwind_protect
-      endif
-      kids = kids(1:(end-1));
-
-      if (strcmpi (obj.visible, "off"))
-        continue;
-      endif
-
-      if (xlogscale && isfield (obj, "xdata"))
-        obj.xdata(obj.xdata<=0) = NaN;
-      endif
-      if (ylogscale && isfield (obj, "ydata"))
-        obj.ydata(obj.ydata<=0) = NaN;
-      endif
-      if (zlogscale && isfield (obj, "zdata"))
-        obj.zdata(obj.zdata<=0) = NaN;
-      endif
-
-      ## Check for facecolor interpolation for surfaces.
-      doing_interp_color = ...
-         isfield (obj, "facecolor") && strncmp (obj.facecolor, "interp", 6);
-
-      switch (obj.type)
-        case "image"
-          img_data = obj.cdata;
-          img_xdata = obj.xdata;
-          img_ydata = obj.ydata;
-
-          if (ndims (img_data) == 3)
-            truecolor = true;
-          elseif (strcmpi (obj.cdatamapping, "direct"))
-            cdatadirect = true;
-          endif
-          data_idx++;
-          is_image_data(data_idx) = true;
-          parametric(data_idx) = false;
-          have_cdata(data_idx) = false;
-          have_3d_patch(data_idx) = false;
-
-          if (img_xdata(2) < img_xdata(1))
-            img_xdata = img_xdata(2:-1:1);
-            img_data = img_data(:,end:-1:1,:);
-          elseif (img_xdata(1) == img_xdata(2))
-            img_xdata = img_xdata(1) + [0, size(img_data,2)-1];
-          endif
-          if (img_ydata(2) < img_ydata(1))
-            img_ydata = img_ydata(2:-1:1);
-            img_data = img_data(end:-1:1,:,:);
-          elseif (img_ydata(1) == img_ydata(2))
-            img_ydata = img_ydata(1) + [0, size(img_data,1)-1];
-          endif
-
-          [y_dim, x_dim] = size (img_data(:,:,1));
-          if (x_dim > 1)
-            dx = abs (img_xdata(2)-img_xdata(1))/(x_dim-1);
-          else
-            x_dim = 2;
-            img_data = [img_data, img_data];
-            dx = abs (img_xdata(2)-img_xdata(1));
-          endif
-          if (y_dim > 1)
-            dy = abs (img_ydata(2)-img_ydata(1))/(y_dim-1);
-          else
-            y_dim = 2;
-            img_data = [img_data; img_data];
-            dy = abs (img_ydata(2)-img_ydata(1));
-          endif
-
-          x_origin = min (img_xdata);
-          y_origin = min (img_ydata);
-
-          if (ndims (img_data) == 3)
-            data{data_idx} = permute (img_data, [3, 1, 2])(:);
-            format = "1:2:3";
-            imagetype = "rgbimage";
-          else
-            data{data_idx} = img_data(:);
-            format = "1";
-            imagetype = "image";
-          endif
-
-          titlespec{data_idx} = "title \"\"";
-          usingclause{data_idx} = sprintf ("binary array=%dx%d scan=yx origin=(%.15g,%.15g) dx=%.15g dy=%.15g using %s",
-              x_dim, y_dim, x_origin, y_origin, dx, dy, format);
-          withclause{data_idx} = sprintf ("with %s;", imagetype);
-
-        case "line"
-          if (strncmp (obj.linestyle, "none", 4)
-              && (! isfield (obj, "marker")
-                  || (isfield (obj, "marker")
-                      && strncmp (obj.marker, "none", 4))))
-            continue;
-          endif
-          data_idx++;
-          is_image_data(data_idx) = false;
-          parametric(data_idx) = true;
-          have_cdata(data_idx) = false;
-          have_3d_patch(data_idx) = false;
-          if (isempty (obj.displayname))
-            titlespec{data_idx} = "title \"\"";
-          else
-            tmp = undo_string_escapes (__maybe_munge_text__ (enhanced, obj, "displayname"));
-            titlespec{data_idx} = cstrcat ("title \"", tmp, "\"");
-          endif
-          usingclause{data_idx} = sprintf ("record=%d", numel (obj.xdata));
-          errbars = "";
-          if (nd == 3)
-            xdat = obj.xdata(:);
-            ydat = obj.ydata(:);
-            if (! isempty (obj.zdata))
-              zdat = obj.zdata(:);
-            else
-              zdat = zeros (size (xdat));
-            endif
-            data{data_idx} = [xdat, ydat, zdat]';
-            usingclause{data_idx} = sprintf ("record=%d using ($1):($2):($3)", numel (xdat));
-            ## fputs (plot_stream, "set parametric;\n");
-          else
-            xdat = obj.xdata(:);
-            ydat = obj.ydata(:);
-            data{data_idx} = [xdat, ydat]';
-            usingclause{data_idx} = sprintf ("record=%d using ($1):($2) axes %s%s",
-                                            rows(xdat), xaxisloc_using, yaxisloc_using);
-          endif
-
-          style = do_linestyle_command (obj, obj.color, data_idx, mono,
-                                        plot_stream, errbars);
-
-          withclause{data_idx} = sprintf ("with %s linestyle %d",
-                                          style{1}, data_idx);
-
-          if (length (style) > 1)
-            data_idx++;
-            is_image_data(data_idx) = is_image_data(data_idx - 1);
-            parametric(data_idx) = parametric(data_idx - 1);
-            have_cdata(data_idx) = have_cdata(data_idx - 1);
-            have_3d_patch(data_idx) = have_3d_patch(data_idx - 1);
-            titlespec{data_idx} = "title \"\"";
-            usingclause{data_idx} = usingclause{data_idx - 1};
-            data{data_idx} = data{data_idx - 1};
-            withclause{data_idx} = sprintf ("with %s linestyle %d",
-                                          style{2}, data_idx);
-          endif
-          if (length (style) > 2)
-            data_idx++;
-            is_image_data(data_idx) = is_image_data(data_idx - 1);
-            parametric(data_idx) = parametric(data_idx - 1);
-            have_cdata(data_idx) = have_cdata(data_idx - 1);
-            have_3d_patch(data_idx) = have_3d_patch(data_idx - 1);
-            titlespec{data_idx} = "title \"\"";
-            usingclause{data_idx} = usingclause{data_idx - 1};
-            data{data_idx} = data{data_idx - 1};
-            withclause{data_idx} = sprintf ("with %s linestyle %d",
-                                          style{3}, data_idx);
-          endif
-
-       case "patch"
-         cmap = parent_figure_obj.colormap;
-         [nr, nc] = size (obj.xdata);
-
-         if (! isempty (obj.cdata))
-           cdat = obj.cdata;
-           if (strcmpi (obj.cdatamapping, "direct"))
-             cdatadirect = true;
-           endif
-         else
-           cdat = [];
-         endif
-
-         data_3d_idx = NaN;
-         for i = 1:nc
-           xcol = obj.xdata(:,i);
-           ycol = obj.ydata(:,i);
-           if (nd == 3)
-             if (! isempty (obj.zdata))
-               zcol = obj.zdata(:,i);
-             else
-               zcol = zeros (size (xcol));
-             endif
-           endif
-
-           if (! isnan (xcol) && ! isnan (ycol))
-             ## Is the patch closed or not
-             if (strncmp (obj.facecolor, "none", 4))
-               hidden_removal = false;
-             else
-
-               if (isnan (hidden_removal))
-                 hidden_removal = true;
-               endif
-               if (nd == 3)
-                 if (numel (xcol) > 3)
-                   error ("__go_draw_axes__: gnuplot (as of v4.2) only supports 3D filled triangular patches");
-                 else
-                   if (isnan (data_3d_idx))
-                     data_idx++;
-                     data_3d_idx = data_idx;
-                     is_image_data(data_idx) = false;
-                     parametric(data_idx) = false;
-                     have_cdata(data_idx) = true;
-                     have_3d_patch(data_idx) = true;
-                     withclause{data_3d_idx} = sprintf ("with pm3d");
-                     usingclause{data_3d_idx} =  "using 1:2:3:4";
-                     data{data_3d_idx} = [];
-                   endif
-                   local_idx = data_3d_idx;
-                   ccdat = NaN;
-                 endif
-               else
-                 data_idx++;
-                 local_idx = data_idx;
-                 is_image_data(data_idx) = false;
-                 parametric(data_idx) = false;
-                 have_cdata(data_idx) = false;
-                 have_3d_patch(data_idx) = false;
-               endif
-
-               if (i > 1 || isempty (obj.displayname))
-                 titlespec{local_idx} = "title \"\"";
-               else
-                 tmp = undo_string_escapes (__maybe_munge_text__ (enhanced, obj, "displayname"));
-                 titlespec{local_idx} = cstrcat ("title \"", tmp, "\"");
-               endif
-               if (isfield (obj, "facecolor"))
-                 if ((strncmp (obj.facecolor, "flat", 4)
-                     || strncmp (obj.facecolor, "interp", 6))
-                     && isfield (obj, "cdata"))
-                   if (ndims (obj.cdata) == 2
-                       && (size (obj.cdata, 2) == nc
-                           && (size (obj.cdata, 1) == 1
-                               || size (obj.cdata, 1) == 3)))
-                     ccol = cdat (:, i);
-                   elseif (ndims (obj.cdata) == 2
-                       && (size (obj.cdata, 1) == nc
-                           && (size (obj.cdata, 2) == 1
-                               || size (obj.cdata, 2) == 3)))
-                     ccol = cdat (i, :);
-                   elseif (ndims (obj.cdata) == 3)
-                     ccol = permute (cdat (:, i, :), [1, 3, 2]);
-                   else
-                     ccol = cdat;
-                   endif
-                   if (strncmp (obj.facecolor, "flat", 4))
-                     if (numel(ccol) == 3)
-                       color = ccol;
-                     elseif (nd == 3 && numel (xcol) == 3)
-                       ccdat = ccol * ones (3,1);
-                     else
-                       r = 1 + round ((size (cmap, 1) - 1)
-                                      * (ccol - clim(1))/(clim(2) - clim(1)));
-                       r = max (1, min (r, size (cmap, 1)));
-                       color = cmap(r, :);
-                     endif
-                   elseif (strncmp (obj.facecolor, "interp", 6))
-                     if (nd == 3 && numel (xcol) == 3)
-                       ccdat = ccol;
-                       if (! isvector (ccdat))
-                         tmp = rows(cmap) + rows(addedcmap) + ...
-                              [1 : rows(ccdat)];
-                         addedcmap = [addedcmap; ccdat];
-                         ccdat = tmp(:);
-                       else
-                         ccdat = ccdat(:);
-                       endif
-                     else
-                       warning ("\"interp\" not supported, using 1st entry of cdata");
-                       r = 1 + round ((size (cmap, 1) - 1) * ccol(1));
-                       r = max (1, min (r, size (cmap, 1)));
-                       color = cmap(r,:);
-                     endif
-                   endif
-                 elseif (isnumeric (obj.facecolor))
-                   color = obj.facecolor;
-                 else
-                   color = [0, 1, 0];
-                 endif
-               else
-                 color = [0, 1, 0];
-               endif
-
-               if (nd == 3 && numel (xcol) == 3)
-                 if (isnan (ccdat))
-                   ccdat = (rows (cmap) + rows(addedcmap) + 1) * ones(3, 1);
-                   addedcmap = [addedcmap; reshape(color, 1, 3)];
-                 endif
-                 data{data_3d_idx} = [data{data_3d_idx}, ...
-                                      [[xcol; xcol(end)], [ycol; ycol(end)], ...
-                                      [zcol; zcol(end)], [ccdat; ccdat(end)]]'];
-               else
-                 if (mono)
-                   colorspec = "";
-                 elseif (__gnuplot_has_feature__ ("transparent_patches")
-                         && isscalar (obj.facealpha))
-                   colorspec = sprintf ("lc rgb \"#%02x%02x%02x\" fillstyle transparent solid %f",
-                                      round (255*color), obj.facealpha);
-                 else
-                   colorspec = sprintf ("lc rgb \"#%02x%02x%02x\"",
-                                        round (255*color));
-                 endif
-
-                 withclause{data_idx} = sprintf ("with filledcurve %s",
-                                               colorspec);
-                 data{data_idx} = [xcol, ycol]';
-                 usingclause{data_idx} = sprintf ("record=%d using ($1):($2)",
-                                                  numel (xcol));
-               endif
-             endif
-           endif
-
-           ## patch outline
-           if (!(strncmp (obj.edgecolor, "none", 4)
-                  && (strncmp (obj.marker, "none", 4)
-                      || (strncmp (obj.markeredgecolor, "none", 4)
-                          && strncmp (obj.markerfacecolor, "none", 4)))))
-
-             data_idx++;
-             is_image_data(data_idx) = false;
-             parametric(data_idx) = false;
-             have_cdata(data_idx) = false;
-             have_3d_patch(data_idx) = false;
-             titlespec{data_idx} = "title \"\"";
-             usingclause{data_idx} = sprintf ("record=%d", numel (obj.xdata));
-
-             if (isfield (obj, "markersize"))
-               mdat = obj.markersize / 3;
-             endif
-
-             if (isfield (obj, "edgecolor"))
-               ## FIXME
-               ## This is the wrong thing to do as edgecolor, markeredgecolor
-               ## and markerfacecolor can have different values and we should
-               ## treat them seperately. However, the below allow the scatter
-               ## functions to work as expected, where only one of these values
-               ## is set
-               if (strncmp (obj.edgecolor, "none", 4))
-                 if (strncmp (obj.markeredgecolor, "none", 4))
-                   ec = obj.markerfacecolor;
-                 else
-                   ec = obj.markeredgecolor;
-                 endif
-               else
-                 ec = obj.edgecolor;
-               endif
-
-               if ((strncmp (ec, "flat", 4)
-                    || strncmp (ec, "interp", 6))
-                   && isfield (obj, "cdata"))
-                 if (ndims (obj.cdata) == 2
-                     && (size (obj.cdata, 2) == nc
-                         && (size (obj.cdata, 1) == 1
-                             || size (obj.cdata, 1) == 3)))
-                   ccol = cdat (:, i);
-                 elseif (ndims (obj.cdata) == 2
-                         && (size (obj.cdata, 1) == nc
-                             && (size (obj.cdata, 2) == 1
-                                 || size (obj.cdata, 2) == 3)))
-                   ccol = cdat (i, :);
-                 elseif (ndims (obj.cdata) == 3)
-                   ccol = permute (cdat (:, i, :), [1, 3, 2]);
-                 else
-                   ccol = cdat;
-                 endif
-                 if (strncmp (ec, "flat", 4))
-                   if (numel(ccol) == 3)
-                     color = ccol;
-                   else
-                     if (isscalar (ccol))
-                       ccol = repmat(ccol, numel (xcol), 1);
-                     endif
-                     color = "flat";
-                     have_cdata(data_idx) = true;
-                   endif
-                 elseif (strncmp (ec, "interp", 6))
-                   if (numel(ccol) == 3)
-                     warning ("\"interp\" not supported, using 1st entry of cdata");
-                     color = ccol(1,:);
-                   else
-                     if (isscalar (ccol))
-                       ccol = repmat(ccol, numel (xcol), 1);
-                     endif
-                     color = "interp";
-                     have_cdata(data_idx) = true;
-                   endif
-                 endif
-               elseif (isnumeric (ec))
-                 color = ec;
-               else
-                 color = [0, 0, 0];
-               endif
-             else
-               color = [0, 0, 0];
-             endif
-
-             if (isfield (obj, "linestyle"))
-               switch (obj.linestyle)
-                 case "-"
-                   lt = "lt 1";
-                 case "--"
-                   lt = "lt 2";
-                 case ":"
-                   lt = "lt 3";
-                 case "-."
-                   lt = "lt 6";
-                 case "none"
-                   lt = "";
-                 otherwise
-                   lt = "";
-               endswitch
-             else
-               lt = "";
-             endif
-
-             if (isfield (obj, "linewidth"))
-               lw = sprintf("linewidth %f", obj.linewidth);
-             else
-               lw  = "";
-             endif
-
-             [pt, pt2, obj] = gnuplot_pointtype (obj);
-             if (! isempty (pt))
-               pt = sprintf ("pointtype %s", pt);
-             endif
-             if (! isempty (pt2))
-               pt2 = sprintf ("pointtype %s", pt2);
-             endif
-
-             if (mono)
-               colorspec = "";
-             else
-               if (ischar (color))
-                 colorspec = "palette";
-               else
-                 colorspec = sprintf ("lc rgb \"#%02x%02x%02x\"",
-                                      round (255*color));
-               endif
-             endif
-
-             sidx = 1;
-             if (isempty (lt))
-               style = "";
-             else
-               style = "lines";
-             endif
-             tmpwith = {};
-
-             facesame = true;
-             if (! isequal (pt, pt2) && isfield (obj, "markerfacecolor")
-                 && !strncmp (obj.markerfacecolor, "none", 4))
-               if (strncmp (obj.markerfacecolor, "auto", 4)
-                   || ! isnumeric (obj.markerfacecolor)
-                   || (isnumeric (obj.markerfacecolor)
-                       && isequal (color, obj.markerfacecolor)))
-                 style = strcat (style, "points");
-                 if (isfield (obj, "markersize"))
-                   if (length (mdat) == nc)
-                     m = mdat(i);
-                   else
-                     m = mdat;
-                   endif
-                   ps = sprintf("pointsize %f", m / 3);
-                 else
-                   ps = "";
-                 endif
-
-                 tmpwith{sidx} = sprintf ("with %s %s %s %s %s %s",
-                                          style, lw, pt2, lt, ps,
-                                          colorspec);
-               else
-                 facesame = false;
-                 if (! isempty (style))
-                   tmpwith{sidx} = sprintf ("with %s %s %s %s",
-                                            style, lw, lt,
-                                            colorspec);
-                   sidx ++;
-                 endif
-                 if (isnumeric (obj.markerfacecolor) && ! mono)
-                   colorspec = sprintf ("lc rgb \"#%02x%02x%02x\"",
-                                        round (255*obj.markerfacecolor));
-                 endif
-                 style = "points";
-                 if (isfield (obj, "markersize"))
-                   if (length (mdat) == nc)
-                     m = mdat(i);
-                   else
-                     m = mdat;
-                   endif
-                   ps = sprintf("pointsize %f", m / 3);
-                 else
-                   ps = "";
-                 endif
-                 tmpwith{sidx} = sprintf ("with %s %s %s %s %s %s",
-                                          style, lw, pt2, lt, ps,
-                                          colorspec);
-               endif
-             endif
-
-             if (isfield (obj, "markeredgecolor")
-                 && !strncmp (obj.markeredgecolor, "none", 4))
-               if (facesame && !isempty (pt)
-                   && (strncmp (obj.markeredgecolor, "auto", 4)
-                       || ! isnumeric (obj.markeredgecolor)
-                       || (isnumeric (obj.markeredgecolor)
-                           && isequal (color, obj.markeredgecolor))))
-                 if (sidx == 1 && ((length (style) == 5
-                          && strncmp (style, "lines", 5))
-                         || isempty (style)))
-                   style = strcat (style, "points");
-                   if (isfield (obj, "markersize"))
-                     if (length (mdat) == nc)
-                       m = mdat(i);
-                     else
-                       m = mdat;
-                     endif
-                     ps = sprintf("pointsize %f", m / 3);
-                   else
-                     ps = "";
-                   endif
-                   tmpwith{sidx} = sprintf ("with %s %s %s %s %s %s",
-                                            style, lw, pt, lt, ps,
-                                            colorspec);
-                 endif
-               else
-                 if (!isempty (style))
-                   if (length(tmpwith) < sidx || isempty (tmpwith{sidx}))
-                     tmpwith{sidx} = sprintf ("with %s %s %s %s",
-                                              style, lw, lt,
-                                              colorspec);
-                   endif
-                   sidx ++;
-                 endif
-
-                 if (!isempty (pt))
-                   if (! mono)
-                     if (strncmp (obj.markeredgecolor, "auto", 4))
-                       colorspec = sprintf ("lc rgb \"#%02x%02x%02x\"",
-                                            round (255*color));
-                     elseif (isnumeric (obj.markeredgecolor) && ! mono)
-                       colorspec = sprintf ("lc rgb \"#%02x%02x%02x\"",
-                                            round (255*obj.markeredgecolor));
-                     endif
-                   endif
-                   style = "points";
-                   if (isfield (obj, "markersize"))
-                     if (length (mdat) == nc)
-                       m = mdat(i);
-                     else
-                       m = mdat;
-                     endif
-                     ps = sprintf("pointsize %f", m / 3);
-                   else
-                     ps = "";
-                   endif
-                   tmpwith{sidx} = sprintf ("with %s %s %s %s %s %s",
-                                            style, lw, pt, lt, ps,
-                                            colorspec);
-                 endif
-               endif
-             endif
-
-             if (isempty (tmpwith))
-               withclause{data_idx} = sprintf ("with %s %s %s %s %s",
-                                               style, lw, pt, lt,
-                                               colorspec);
-             else
-               withclause{data_idx} = tmpwith{1};
-             endif
-             if (nd == 3)
-               if (ischar (color))
-                 if (! isnan (xcol) && ! isnan (ycol) && ! isnan (zcol))
-                   data{data_idx} = [[xcol; xcol(1)], [ycol; ycol(1)], ...
-                                     [zcol; zcol(1)], [ccol; ccol(1)]]';
-                 else
-                   data{data_idx} = [xcol, ycol, zcol, ccol]';
-                 endif
-                 usingclause{data_idx} = sprintf ("record=%d using ($1):($2):($3):($4)", columns (data{data_idx}));
-               else
-                 if (! isnan (xcol) && ! isnan (ycol) && ! isnan (zcol))
-                   data{data_idx} = [[xcol; xcol(1)], [ycol; ycol(1)], ...
-                                     [zcol; zcol(1)]]';
-                 else
-                   data{data_idx} = [xcol, ycol, zcol]';
-                 endif
-                 usingclause{data_idx} = sprintf ("record=%d using ($1):($2):($3)", columns (data{data_idx}));
-               endif
-             else
-               if (ischar (color))
-                 if (! isnan (xcol) && ! isnan (ycol))
-                   data{data_idx} = [[xcol; xcol(1)], [ycol; ycol(1)], ...
-                                     [ccol; ccol(1)]]';
-                 else
-                   data{data_idx} = [xcol, ycol, ccol]';
-                 endif
-                 usingclause{data_idx} = sprintf ("record=%d using ($1):($2):($3)", columns (data{data_idx}));
-               else
-                 if (! isnan (xcol) && ! isnan (ycol))
-                   data{data_idx} = [[xcol; xcol(1)], [ycol; ycol(1)]]';
-                 else
-                   data{data_idx} = [xcol, ycol]';
-                 endif
-                 usingclause{data_idx} = sprintf ("record=%d using ($1):($2)", columns (data{data_idx}));
-               endif
-             endif
-
-             if (length (tmpwith) > 1)
-               data_idx++;
-               is_image_data(data_idx) = is_image_data(data_idx - 1);
-               parametric(data_idx) = parametric(data_idx - 1);
-               have_cdata(data_idx) = have_cdata(data_idx - 1);
-               have_3d_patch(data_idx) = have_3d_patch(data_idx - 1);
-               titlespec{data_idx} = "title \"\"";
-               usingclause{data_idx} = usingclause{data_idx - 1};
-               data{data_idx} = data{data_idx - 1};
-               withclause{data_idx} = tmpwith{2};
-             endif
-             if (length (tmpwith) > 2)
-               data_idx++;
-               is_image_data(data_idx) = is_image_data(data_idx - 1);
-               parametric(data_idx) = parametric(data_idx - 1);
-               have_cdata(data_idx) = have_cdata(data_idx - 1);
-               have_3d_patch(data_idx) = have_3d_patch(data_idx - 1);
-               titlespec{data_idx} = "title \"\"";
-               usingclause{data_idx} = usingclause{data_idx - 1};
-               data{data_idx} = data{data_idx - 1};
-               withclause{data_idx} = tmpwith{3};
-             endif
-           endif
-         endfor
-
-        case "surface"
-          view_map = true;
-          if (! (strncmp (obj.edgecolor, "none", 4)
-                 && strncmp (obj.facecolor, "none", 4)))
-            data_idx++;
-            is_image_data(data_idx) = false;
-            parametric(data_idx) = false;
-            have_cdata(data_idx) = true;
-            have_3d_patch(data_idx) = false;
-            style = do_linestyle_command (obj, obj.edgecolor,
-                                          data_idx, mono,
-                                          plot_stream);
-
-            if (isempty (obj.displayname))
-              titlespec{data_idx} = "title \"\"";
-            else
-              tmp = undo_string_escapes (__maybe_munge_text__ (enhanced, obj, "displayname"));
-              titlespec{data_idx} = cstrcat ("title \"", tmp, "\"");
-            endif
-            withclause{data_idx} = sprintf ("with pm3d linestyle %d",
-                                            data_idx);
-            withpm3d = true;
-            pm3didx = data_idx;
-
-            xdat = obj.xdata;
-            ydat = obj.ydata;
-            zdat = obj.zdata;
-            cdat = obj.cdata;
-
-            err = false;
-            if (! size_equal(zdat, cdat))
-              err = true;
-            endif
-            if (isvector (xdat) && isvector (ydat) && ismatrix (zdat))
-              if (rows (zdat) == length (ydat)
-                  && columns (zdat) == length (xdat))
-                [xdat, ydat] = meshgrid (xdat, ydat);
-              else
-                err = true;
-              endif
-            elseif (ismatrix (xdat) && ismatrix (ydat) && ismatrix (zdat))
-              if (! size_equal (xdat, ydat, zdat))
-                err = true;
-              endif
-            else
-              err = true;
-            endif
-            if (err)
-              error ("__go_draw_axes__: invalid grid data");
-            endif
-            xlen = columns (zdat);
-            ylen = rows (zdat);
-            if (xlen == columns (xdat) && xlen == columns (ydat)
-                && ylen == rows (xdat) && ylen == rows (ydat))
-              len = 4 * xlen;
-              zz = zeros (ylen, len);
-              k = 1;
-              for kk = 1:4:len
-                zz(:,kk)   = xdat(:,k);
-                zz(:,kk+1) = ydat(:,k);
-                zz(:,kk+2) = zdat(:,k);
-                zz(:,kk+3) = cdat(:,k);
-                k++;
-              endfor
-              data{data_idx} = zz.';
-            endif
-
-            if (doing_interp_color)
-              interp_str = "interpolate 0, 0";
-            else
-              ## No interpolation of facecolors.
-              interp_str = "";
-            endif
-            usingclause{data_idx} = sprintf ("record=%dx%d using ($1):($2):($3):($4)", ylen, xlen);
-
-            flat_interp_face = (strncmp (obj.facecolor, "flat", 4)
-                                || strncmp (obj.facecolor, "interp", 6));
-            flat_interp_edge = (strncmp (obj.edgecolor, "flat", 4)
-                                || strncmp (obj.edgecolor, "interp", 6));
-
-            facecolor_none_or_white = (strncmp (obj.facecolor, "none", 4)
-                                       || (isnumeric (obj.facecolor)
-                                           && all (obj.facecolor == 1)));
-            hidden_removal = false;
-            fputs (plot_stream, "set style increment default;\n");
-            if (flat_interp_edge && facecolor_none_or_white)
-              withpm3d = false;
-              withclause{data_idx} = sprintf ("with %s palette", style {1});
-              fputs (plot_stream, "unset pm3d\n");
-              if (all (obj.facecolor == 1))
-                hidden_removal = true;
-              endif
-            elseif (facecolor_none_or_white)
-              if (all (obj.facecolor == 1))
-                hidden_removal = true;
-              endif
-              fputs(plot_stream,"unset pm3d;\n");
-              fputs(plot_stream,"set style increment user;\n");
-              withpm3d = false;
-              withclause{data_idx} = sprintf("with %s linestyle %d",
-                                             style{1}, data_idx);
-              fputs (plot_stream, "unset pm3d\n");
-            endif
-
-            if (doing_interp_color)
-              ## "depthorder" interferes with interpolation of colors.
-              dord = "scansautomatic";
-            else
-              dord = "depthorder";
-            endif
-
-            if (flat_interp_face && strncmp (obj.edgecolor, "flat", 4))
-              fprintf (plot_stream, "set pm3d explicit at s %s %s corners2color c3;\n",
-                       interp_str, dord);
-            elseif (!facecolor_none_or_white)
-              if (strncmp (obj.edgecolor, "none", 4))
-                if (__gnuplot_has_feature__ ("transparent_surface")
-                    && isscalar (obj.facealpha))
-                  fprintf (plot_stream,
-                           "set style fill transparent solid %f;\n",
-                           obj.facealpha);
-                endif
-                fprintf (plot_stream, "set pm3d explicit at s %s corners2color c3;\n",
-                         interp_str, dord);
-              else
-                fprintf (plot_stream, "set pm3d explicit at s hidden3d %d %s %s corners2color c3;\n",
-                         data_idx, interp_str, dord);
-
-                if (__gnuplot_has_feature__ ("transparent_surface")
-                    && isscalar (obj.facealpha))
-                  fprintf (plot_stream,
-                           "set style fill transparent solid %f;\n",
-                           obj.facealpha);
-                endif
-              endif
-            endif
-
-            zz = [];
-            if (length (style) > 1)
-              len = 3 * xlen;
-              zz = zeros (ylen, len);
-              k = 1;
-              for kk = 1:3:len
-                zz(:,kk)   = xdat(:,k);
-                zz(:,kk+1) = ydat(:,k);
-                zz(:,kk+2) = zdat(:,k);
-                k++;
-              endfor
-              zz = zz.';
-
-              data_idx++;
-              is_image_data(data_idx) = is_image_data(data_idx - 1);
-              parametric(data_idx) = parametric(data_idx - 1);
-              have_cdata(data_idx) = false;
-              have_3d_patch(data_idx) = have_3d_patch(data_idx - 1);
-              titlespec{data_idx} = "title \"\"";
-              usingclause{data_idx} = sprintf ("record=%dx%d using ($1):($2):($3)", ylen, xlen);
-              data{data_idx} = zz;
-              withclause{data_idx} = sprintf ("with %s linestyle %d",
-                                              style{2}, data_idx);
-
-            endif
-            if (length (style) > 2)
-              data_idx++;
-              is_image_data(data_idx) = is_image_data(data_idx - 1);
-              parametric(data_idx) = parametric(data_idx - 1);
-              have_cdata(data_idx) = false;
-              have_3d_patch(data_idx) = have_3d_patch(data_idx - 1);
-              titlespec{data_idx} = "title \"\"";
-              usingclause{data_idx} = sprintf ("record=%dx%d using ($1):($2):($3)", ylen, xlen);
-              data{data_idx} = zz;
-              withclause{data_idx} = sprintf ("with %s linestyle %d",
-                                              style{3}, data_idx);
-            endif
-            if (withpm3d && strncmp (style {1}, "linespoints", 11))
-              if (isempty(zz))
-                len = 3 * xlen;
-                zz = zeros (ylen, len);
-                k = 1;
-                for kk = 1:3:len
-                  zz(:,kk)   = xdat(:,k);
-                  zz(:,kk+1) = ydat(:,k);
-                  zz(:,kk+2) = zdat(:,k);
-                  k++;
-                endfor
-                zz = zz.';
-              endif
-              data_idx++;
-              is_image_data(data_idx) = is_image_data(data_idx - 1);
-              parametric(data_idx) = parametric(data_idx - 1);
-              have_cdata(data_idx) = false;
-              have_3d_patch(data_idx) = have_3d_patch(data_idx - 1);
-              titlespec{data_idx} = "title \"\"";
-              usingclause{data_idx} = sprintf ("record=%dx%d using ($1):($2):($3)", ylen, xlen);
-              data{data_idx} = zz;
-              withclause{data_idx} = sprintf ("with points linestyle %d",
-                                              pm3didx);
-            endif
-          endif
-
-        case "text"
-          [label, f, s] = __maybe_munge_text__ (enhanced, obj, "string");
-          fontspec = create_fontspec (f, s, gnuplot_term);
-          lpos = obj.position;
-          halign = obj.horizontalalignment;
-          valign = obj.verticalalignment;
-          angle = obj.rotation;
-          units = obj.units;
-          color = obj.color;
-          if (strcmpi (units, "normalized"))
-            units = "graph";
-          elseif (strcmp (axis_obj.yaxislocation, "right")
-                  && strcmp (units, "data"))
-            units = "second";
-          else
-            units = "";
-          endif
-
-          if (isnumeric (color))
-            colorspec = get_text_colorspec (color, mono);
-          endif
-
-          switch valign
-            ## Text offset in characters. This relies on gnuplot for font metrics.
-            case "top"
-              dy = -0.5;
-            case "cap"
-              dy = -0.5;
-            case "middle"
-              dy = 0;
-            case "baseline"
-              dy = 0.5;
-            case "bottom"
-              dy = 0.5;
-          endswitch
-          ## Gnuplot's Character units are different for x/y and vary with fontsize. The aspect ratio
-          ## of 1:1.7 was determined by experiment to work for eps/ps/etc. For the MacOS aqua terminal
-          ## a value of 2.5 is needed. However, the difference is barely noticable.
-          dx_and_dy = [(-dy * sind (angle)), (dy * cosd(angle))] .* [1.7 1];
-
-          if (nd == 3)
-            ## This produces the desired vertical alignment in 3D.
-            fprintf (plot_stream,
-                     "set label \"%s\" at %s %.15e,%.15e,%.15e %s rotate by %f offset character %f,%f %s %s front %s;\n",
-                     undo_string_escapes (label), units, lpos(1),
-                     lpos(2), lpos(3), halign, angle, dx_and_dy, fontspec,
-                     __do_enhanced_option__ (enhanced, obj), colorspec);
-          else
-            fprintf (plot_stream,
-                     "set label \"%s\" at %s %.15e,%.15e %s rotate by %f offset character %f,%f %s %s front %s;\n",
-                     undo_string_escapes (label), units,
-                     lpos(1), lpos(2), halign, angle, dx_and_dy, fontspec,
-                     __do_enhanced_option__ (enhanced, obj), colorspec);
-          endif
-
-        case "hggroup"
-          ## Push group children into the kid list.
-          if (isempty (kids))
-            kids = obj.children;
-          elseif (! isempty (obj.children))
-            kids = [kids; obj.children];
-          endif
-
-        otherwise
-          error ("__go_draw_axes__: unknown object class, %s",
-                 obj.type);
-      endswitch
-
-    endwhile
-
-    ## This is need to prevent warnings for rotations in 3D plots, while
-    ## allowing colorbars with contours.
-    if (nd == 2 || (data_idx > 1 && !view_map))
-      fputs (plot_stream, "set pm3d implicit;\n");
-    else
-      fputs (plot_stream, "set pm3d explicit;\n");
-    endif
-
-    if (isnan(hidden_removal) || hidden_removal)
-      fputs (plot_stream, "set hidden3d;\n");
-    else
-      fputs (plot_stream, "unset hidden3d;\n");
-    endif
-
-    have_data = (! (isempty (data) || all (cellfun (@isempty, data))));
-
-    ## Note we don't use the [xy]2range of gnuplot as we don't use the
-    ## dual axis plotting features of gnuplot.
-    if (isempty (xlim))
-      return;
-    endif
-    if (strcmpi (axis_obj.xdir, "reverse"))
-      xdir = "reverse";
-    else
-      xdir = "noreverse";
-    endif
-    fprintf (plot_stream, "set xrange [%.15e:%.15e] %s;\n", xlim, xdir);
-    if (strcmpi (axis_obj.xaxislocation, "top"))
-      fprintf (plot_stream, "set x2range [%.15e:%.15e] %s;\n", xlim, xdir);
-    endif
-
-    if (isempty (ylim))
-      return;
-    endif
-    if (strcmpi (axis_obj.ydir, "reverse"))
-      ydir = "reverse";
-    else
-      ydir = "noreverse";
-    endif
-    fprintf (plot_stream, "set yrange [%.15e:%.15e] %s;\n", ylim, ydir);
-    if (strcmpi (axis_obj.yaxislocation, "right"))
-      fprintf (plot_stream, "set y2range [%.15e:%.15e] %s;\n", ylim, ydir);
-    endif
-
-    if (nd == 3)
-      if (isempty (zlim))
-        return;
-      endif
-      if (strcmpi (axis_obj.zdir, "reverse"))
-        zdir = "reverse";
-      else
-        zdir = "noreverse";
-      endif
-      fprintf (plot_stream, "set zrange [%.15e:%.15e] %s;\n", zlim, zdir);
-    endif
-
-    cmap = parent_figure_obj.colormap;
-    cmap_sz = rows(cmap);
-    if (! any (isinf (clim)))
-      if (truecolor || ! cdatadirect)
-        if (rows(addedcmap) > 0)
-          for i = 1:data_idx
-            if (have_3d_patch(i))
-              data{i}(end,:) = clim(2) * (data{i}(end, :) - 0.5) / cmap_sz;
-             endif
-          endfor
-          fprintf (plot_stream, "set cbrange [%g:%g];\n", clim(1), clim(2) *
-                   (cmap_sz + rows(addedcmap)) / cmap_sz);
-        else
-          fprintf (plot_stream, "set cbrange [%g:%g];\n", clim);
-        endif
-      else
-        fprintf (plot_stream, "set cbrange [1:%d];\n", cmap_sz +
-                 rows (addedcmap));
-      endif
-    endif
-
-    if (strcmpi (axis_obj.box, "on"))
-      if (nd == 3)
-        fputs (plot_stream, "set border 4095;\n");
-      else
-        fputs (plot_stream, "set border 431;\n");
-      endif
-    else
-      if (nd == 3)
-        fputs (plot_stream, "set border 895;\n");
-      elseif (! isempty (axis_obj.ytick))
-        if (strcmpi (axis_obj.yaxislocation, "right"))
-          fprintf (plot_stream, "unset ytics; set y2tics %s nomirror\n",
-                   axis_obj.tickdir);
-          if (strcmpi (axis_obj.xaxislocation, "top"))
-            fprintf (plot_stream, "unset xtics; set x2tics %s nomirror\n",
-                     axis_obj.tickdir);
-            fputs (plot_stream, "set border 12;\n");
-          else
-            fprintf (plot_stream, "unset x2tics; set xtics %s nomirror\n",
-                     axis_obj.tickdir);
-            fputs (plot_stream, "set border 9;\n");
-          endif
-        else
-          fprintf (plot_stream, "unset y2tics; set ytics %s nomirror\n",
-                   axis_obj.tickdir);
-          if (strcmpi (axis_obj.xaxislocation, "top"))
-            fprintf (plot_stream, "unset xtics; set x2tics %s nomirror\n",
-                     axis_obj.tickdir);
-            fputs (plot_stream, "set border 6;\n");
-          else
-            fprintf (plot_stream, "unset x2tics; set xtics %s nomirror\n",
-                     axis_obj.tickdir);
-            fputs (plot_stream, "set border 3;\n");
-          endif
-        endif
-      endif
-    endif
-
-    if (strcmpi (axis_obj.visible, "off"))
-      fputs (plot_stream, "unset border; unset tics\n");
-    else
-      fprintf (plot_stream, "set border lw %f;\n", axis_obj.linewidth);
-    endif
-
-    if (! isempty (hlgnd) && ! isempty (hlgnd.children)
-        && any (strcmpi (get (hlgnd.children, "visible"), "on")))
-      if (strcmpi (hlgnd.box, "on"))
-        box = "box";
-      else
-        box = "nobox";
-      endif
-      if (strcmpi (hlgnd.orientation, "vertical"))
-        horzvert = "vertical";
-      else
-        horzvert = "horizontal";
-      endif
-      if (strcmpi (hlgnd.textposition, "right"))
-        reverse = "reverse";
-      else
-        reverse = "noreverse";
-      endif
-      inout = "inside";
-      keypos = hlgnd.location;
-      if (ischar (keypos))
-        keypos = lower (keypos);
-        keyout = findstr (keypos, "outside");
-        if (! isempty (keyout))
-          inout = "outside";
-          keypos = keypos(1:keyout-1);
-        endif
-      endif
-      switch (keypos)
-        case "north"
-          pos = "center top";
-        case "south"
-          pos = "center bottom";
-        case "east"
-          pos = "right center";
-        case "west"
-          pos = "left center";
-        case "northeast"
-          pos = "right top";
-        case "northwest"
-          pos = "left top";
-        case "southeast"
-          pos = "right bottom";
-        case "southwest"
-          pos = "left bottom";
-        case "best"
-          pos = "";
-          warning ("legend: 'Best' not yet implemented for location specifier.\n");
-          ## Least conflict with data in plot.
-          ## Least unused space outside plot.
-        otherwise
-          pos = "";
-      endswitch
-      if (__gnuplot_has_feature__ ("key_has_font_properties"))
-        [fontname, fontsize] = get_fontname_and_size (hlgnd);
-        fontspec = create_fontspec (fontname, fontsize, gnuplot_term);
-      else
-        fontspec = "";
-      endif
-      fprintf (plot_stream, "set key %s %s;\nset key %s %s %s %s;\n",
-               inout, pos, box, reverse, horzvert, fontspec);
-    else
-      fputs (plot_stream, "unset key;\n");
-    endif
-    fputs (plot_stream, "set style data lines;\n");
-
-    cmap = [cmap; addedcmap];
-    cmap_sz = cmap_sz + rows(addedcmap);
-    if (length(cmap) > 0)
-      fprintf (plot_stream,
-               "set palette positive color model RGB maxcolors %i;\n",
-               cmap_sz);
-      fprintf (plot_stream,
-               "set palette file \"-\" binary record=%d using 1:2:3:4;\n",
-               cmap_sz);
-      fwrite (plot_stream, [1:cmap_sz; cmap.'], "float32");
-      fwrite (plot_stream, "\n");
-    endif
-
-    fputs (plot_stream, "unset colorbox;\n");
-
-    if (have_data)
-      if (nd == 2)
-        plot_cmd = "plot";
-      else
-        plot_cmd = "splot";
-        rot_x = 90 - axis_obj.view(2);
-        rot_z = axis_obj.view(1);
-        while (rot_z < 0)
-          rot_z += 360;
-        endwhile
-        fputs (plot_stream, "set ticslevel 0;\n");
-        if (view_map && rot_x == 0 && rot_z == 0)
-          fputs (plot_stream, "set view map;\n");
-        else
-          fprintf (plot_stream, "set view %.15g, %.15g;\n", rot_x, rot_z);
-        endif
-      endif
-      if (have_3d_patch (1))
-        fputs (plot_stream, "set pm3d depthorder\n");
-        fprintf (plot_stream, "%s \"-\" %s %s %s \\\n", plot_cmd,
-                 usingclause{1}, titlespec{1}, withclause{1});
-      elseif (is_image_data (1))
-        if (numel (is_image_data) > 1 && is_image_data(2))
-          ## Remove terminating semicolon
-          n = max (strfind (withclause{1}, ";"));
-          if (! isempty(n))
-            withclause{1} = withclause{1}(1:n-1);
-          endif
-        endif
-        fprintf (plot_stream, "%s \"-\" %s %s %s \\\n", plot_cmd,
-                 usingclause{1}, titlespec{1}, withclause{1});
-      else
-        fprintf (plot_stream, "%s \"-\" binary format='%%float64' %s %s %s \\\n", plot_cmd,
-                 usingclause{1}, titlespec{1}, withclause{1});
-      endif
-      for i = 2:data_idx
-        if (have_3d_patch (i))
-          fprintf (plot_stream, ", \"-\" %s %s %s \\\n",
-                   usingclause{i}, titlespec{i}, withclause{i});
-        elseif (is_image_data (i))
-          if (! is_image_data (i-1))
-            fputs (plot_stream, "; ");
-            if (bg_is_set)
-              fputs (plot_stream, "unset obj 1; \\\n");
-              bg_is_set = false;
-            endif
-            if (fg_is_set)
-              fputs (plot_stream, "unset obj 2; \\\n");
-              fg_is_set = false;
-            endif
-            if (numel (is_image_data) > i && is_image_data(i+1))
-              ## Remove terminating semicolon
-              n = max (strfind (withclause{i}, ";"));
-              if (! isempty(n))
-                withclause{i} = withclause{i}(1:n-1);
-              endif
-            endif
-            fprintf (plot_stream, "%s \"-\" %s %s %s \\\n", plot_cmd,
-                     usingclause{i}, titlespec{i}, withclause{i});
-          else
-            ## For consecutive images continue with the same plot command
-            fprintf (plot_stream, "%s \"-\" %s %s %s \\\n", ",",
-                     usingclause{i}, titlespec{i}, withclause{i});
-          endif
-        elseif (is_image_data (i-1))
-          if (bg_is_set)
-            fputs (plot_stream, "unset obj 1; \\\n");
-            bg_is_set = false;
-          endif
-          if (fg_is_set)
-            fputs (plot_stream, "unset obj 2; \\\n");
-            fg_is_set = false;
-          endif
-          fprintf (plot_stream, "%s \"-\" binary format='%%float64' %s %s %s \\\n", plot_cmd,
-                   usingclause{i}, titlespec{i}, withclause{i});
-        else
-          fprintf (plot_stream, ", \"-\" binary format='%%float64' %s %s %s \\\n",
-                   usingclause{i}, titlespec{i}, withclause{i});
-        endif
-      endfor
-      fputs (plot_stream, ";\n");
-      for i = 1:data_idx
-        if (have_3d_patch (i))
-          ## Can't write 3d patch data as binary as can't plot more than
-          ## a single patch at a time and have to plot all patches together
-          ## so that the gnuplot depth ordering is done correctly
-          for j = 1 : 4 : columns(data{i})
-            if (j != 1)
-              fputs (plot_stream, "\n\n");
-            endif
-            fprintf (plot_stream, "%.15g %.15g %.15g %.15g\n", data{i}(:,j).');
-            fprintf (plot_stream, "%.15g %.15g %.15g %.15g\n\n", data{i}(:,j+1).');
-            fprintf (plot_stream, "%.15g %.15g %.15g %.15g\n", data{i}(:,j+2).');
-            fprintf (plot_stream, "%.15g %.15g %.15g %.15g\n", data{i}(:,j+3).');
-          endfor
-          fputs (plot_stream, "e\n");
-        elseif (is_image_data(i))
-          fwrite (plot_stream, data{i}, "float32");
-        else
-          __gnuplot_write_data__ (plot_stream, data{i}, nd, parametric(i),
-                                  have_cdata(i));
-        endif
-      endfor
-    else
-      fputs (plot_stream, "plot \"-\";\nInf Inf\ne\n");
-    endif
-
-    ## Needed to allow mouse rotation with pcolor.
-    if (view_map)
-      fputs (plot_stream, "unset view;\n");
-    endif
-
-    if (bg_is_set)
-      fputs (plot_stream, "unset obj 1;\n");
-      bg_is_set = false;
-    endif
-
-    fflush (plot_stream);
-
-  else
-    print_usage ();
-  endif
-
-endfunction
-
-function fontspec = create_fontspec (f, s, gp_term)
-  if (strcmp (f, "*") || strcmp (gp_term, "tikz"))
-    fontspec = sprintf ("font \",%d\"", s);
-  else
-    fontspec = sprintf ("font \"%s,%d\"", f, s);
-  endif
-endfunction
-
-function style = do_linestyle_command (obj, linecolor, idx, mono,
-                                       plot_stream, errbars = "")
-  style = {};
-
-  fprintf (plot_stream, "set style line %d default;\n", idx);
-  fprintf (plot_stream, "set style line %d", idx);
-
-  found_style = false;
-  if (isnumeric (linecolor))
-    color = linecolor;
-    if (! mono)
-      fprintf (plot_stream, " linecolor rgb \"#%02x%02x%02x\"",
-               round (255*color));
-    endif
-  else
-    color = [0, 0, 0];
-  endif
-
-  if (isfield (obj, "linestyle"))
-    switch (obj.linestyle)
-      case "-"
-        lt = "1";
-      case "--"
-        lt = "2";
-      case ":"
-        lt = "3";
-      case "-."
-        lt = "6";
-      case "none"
-        lt = "";
-      otherwise
-        lt = "";
-    endswitch
-
-    if (! isempty (lt))
-      fprintf (plot_stream, " linetype %s", lt);
-    endif
-
-  else
-    lt = "";
-  endif
-  if (! isempty (errbars))
-    found_style = true;
-  endif
-
-  if (isfield (obj, "linewidth"))
-    fprintf (plot_stream, " linewidth %f", obj.linewidth);
-    found_style = true;
-  endif
-
-  [pt, pt2, obj] = gnuplot_pointtype (obj);
-
-  if (! isempty (pt))
-    found_style = true;
-  endif
-
-  sidx = 1;
-  if (isempty (errbars))
-    if (isempty (lt))
-      style {sidx} = "";
-    else
-      style {sidx} = "lines";
-    endif
-
-    facesame = true;
-    if (! isequal (pt, pt2) && isfield (obj, "markerfacecolor")
-        && !strncmp (obj.markerfacecolor, "none", 4))
-      if (strncmp (obj.markerfacecolor, "auto", 4)
-          || ! isnumeric (obj.markerfacecolor)
-          || (isnumeric (obj.markerfacecolor)
-              && isequal (color, obj.markerfacecolor)))
-        if (! isempty (pt2))
-          fprintf (plot_stream, " pointtype %s", pt2);
-          style {sidx} = strcat (style{sidx}, "points");
-        endif
-        if (isfield (obj, "markersize"))
-          fprintf (plot_stream, " pointsize %f", obj.markersize / 3);
-        endif
-      else
-        facesame = false;
-        if (! found_style)
-          fputs (plot_stream, " default");
-        endif
-        fputs (plot_stream, ";\n");
-        if (! isempty (style {sidx}))
-          sidx ++;
-          idx ++;
-        else
-          fputs (plot_stream, ";\n");
-        endif
-        fprintf (plot_stream, "set style line %d default;\n", idx);
-        fprintf (plot_stream, "set style line %d", idx);
-        if (isnumeric (obj.markerfacecolor) && ! mono)
-          fprintf (plot_stream, " linecolor rgb \"#%02x%02x%02x\"",
-                   round (255*obj.markerfacecolor));
-        endif
-        if (! isempty (pt2))
-          style {sidx} = "points";
-          fprintf (plot_stream, " pointtype %s", pt2);
-        endif
-        if (isfield (obj, "markersize"))
-          fprintf (plot_stream, " pointsize %f", obj.markersize / 3);
-        endif
-      endif
-    endif
-    if (isfield (obj, "markeredgecolor")
-        && !strncmp (obj.markeredgecolor, "none", 4))
-      if (facesame && !isempty (pt)
-          && (strncmp (obj.markeredgecolor, "auto", 4)
-              || ! isnumeric (obj.markeredgecolor)
-              || (isnumeric (obj.markeredgecolor)
-                  && isequal (color, obj.markeredgecolor))))
-        if (sidx == 1 && ((length (style {sidx}) == 5
-            && strncmp (style {sidx}, "lines", 5)) || isempty (style {sidx})))
-          if (! isempty (pt))
-            style {sidx} = strcat (style{sidx}, "points");
-            fprintf (plot_stream, " pointtype %s", pt);
-          endif
-          if (isfield (obj, "markersize"))
-            fprintf (plot_stream, " pointsize %f", obj.markersize / 3);
-          endif
-        endif
-      else
-        if (! found_style)
-          fputs (plot_stream, " default");
-        endif
-        fputs (plot_stream, ";\n");
-        if (!isempty (style {sidx}))
-          sidx ++;
-          idx ++;
-        else
-          fputs (plot_stream, ";\n");
-        endif
-        fprintf (plot_stream, "set style line %d default;\n", idx);
-        fprintf (plot_stream, "set style line %d", idx);
-        if (! mono)
-          if (strncmp (obj.markeredgecolor, "auto", 4))
-            fprintf (plot_stream, " linecolor rgb \"#%02x%02x%02x\"",
-                     round (255*color));
-          elseif (isnumeric (obj.markeredgecolor) && ! mono)
-            fprintf (plot_stream, " linecolor rgb \"#%02x%02x%02x\"",
-                     round (255*obj.markeredgecolor));
-          endif
-        endif
-        if (! isempty (pt))
-          style {sidx} = "points";
-          fprintf (plot_stream, " pointtype %s", pt);
-        endif
-        if (isfield (obj, "markersize"))
-          fprintf (plot_stream, " pointsize %f", obj.markersize / 3);
-        endif
-      endif
-    endif
-  else
-    style{1} = errbars;
-    fputs (plot_stream, " pointtype 0");
-  endif
-
-  if (! found_style && isempty (style {1}))
-    fputs (plot_stream, " default");
-  endif
-
-  fputs (plot_stream, ";\n");
-
-endfunction
-
-function [pt, pt2, obj] = gnuplot_pointtype (obj)
-  if (isfield (obj, "marker"))
-    switch (obj.marker)
-      case "+"
-        pt = pt2 = "1";
-      case "o"
-        pt = "6";
-        pt2 = "7";
-      case "*"
-        pt = pt2 = "3";
-      case "."
-        pt = "6";
-        pt2 = "7";
-        if (isfield (obj, "markerfacecolor")
-            || strncmp (obj.markerfacecolor, "none", 4))
-          obj.markerfacecolor = "auto";
-        endif
-        if (isfield (obj, "markersize"))
-          obj.markersize /= 3;
-        else
-          obj.markersize = 5;
-        endif
-      case "x"
-        pt = pt2 = "2";
-      case {"square", "s"}
-        pt = "4";
-        pt2 = "5";
-      case {"diamond", "d"}
-        pt = "12";
-        pt2 = "13";
-      case "^"
-        pt = "8";
-        pt2 = "9";
-      case "v"
-        pt = "10";
-        pt2 = "11";
-      case ">"
-        ## FIXME -- should be triangle pointing right, use triangle pointing up
-        pt = "8";
-        pt2 = "9";
-      case "<"
-        ## FIXME -- should be triangle pointing left, use triangle pointing down
-        pt = "10";
-        pt2 = "11";
-      case {"pentagram", "p"}
-        ## FIXME -- should be pentagram, using pentagon
-        pt = "14";
-        pt2 = "15";
-      case {"hexagram", "h"}
-        ## FIXME -- should be 6 pt start, using "*" instead
-        pt = pt2 = "3";
-      case "none"
-        pt = pt2 = "";
-      otherwise
-        pt = pt2 = "";
-    endswitch
-  else
-    pt = pt2 = "";
-  endif
-endfunction
-
-function __gnuplot_write_data__ (plot_stream, data, nd, parametric, cdata)
-
-  ## DATA is already transposed.
-
-  ## FIXME -- this may need to be converted to C++ for speed.
-
-  ## Convert NA elements to normal NaN values because fprintf writes
-  ## "NA" and that confuses gnuplot.
-  idx = find (isna (data));
-  if (any (idx))
-    data(idx) = NaN;
-  endif
-
-  if (nd == 2)
-    fwrite (plot_stream, data, "float64");
-  elseif (nd == 3)
-    if (parametric)
-      fwrite (plot_stream, data, "float64");
-    else
-      nr = rows (data);
-      if (cdata)
-        for j = 1:4:nr
-          fwrite (plot_stream, data(j:j+3,:), "float64");
-        endfor
-      else
-        for j = 1:3:nr
-          fwrite (plot_stream, data(j:j+2,:), "float64");
-        endfor
-      endif
-    endif
-  endif
-
-endfunction
-
-function do_tics (obj, plot_stream, ymirror, mono, gnuplot_term)
-
-  obj.xticklabel = ticklabel_to_cell (obj.xticklabel);
-  obj.yticklabel = ticklabel_to_cell (obj.yticklabel);
-  obj.zticklabel = ticklabel_to_cell (obj.zticklabel);
-
-  if (strcmp (obj.xminorgrid, "on"))
-    obj.xminortick = "on";
-  endif
-  if (strcmp (obj.yminorgrid, "on"))
-    obj.yminortick = "on";
-  endif
-  if (strcmp (obj.zminorgrid, "on"))
-    obj.zminortick = "on";
-  endif
-
-  [fontname, fontsize] = get_fontname_and_size (obj);
-  fontspec = create_fontspec (fontname, fontsize, gnuplot_term);
-
-  ## A Gnuplot tic scale of 69 is equivalent to Octave's 0.5.
-  ticklength = sprintf ("scale %4.1f", (69/0.5)*obj.ticklength(1));
-
-  if (strcmpi (obj.xaxislocation, "top"))
-    do_tics_1 (obj.xtickmode, obj.xtick, obj.xminortick, obj.xticklabelmode,
-               obj.xticklabel, obj.xcolor, "x2", plot_stream, true, mono,
-               "border", obj.tickdir, ticklength, fontname, fontspec,
-               obj.interpreter, obj.xscale, gnuplot_term);
-    do_tics_1 ("manual", [], "off", obj.xticklabelmode, obj.xticklabel,
-               obj.xcolor, "x", plot_stream, true, mono, "border",
-               "", "", fontname, fontspec, obj.interpreter, obj.xscale,
-               gnuplot_term);
-  elseif (strcmpi (obj.xaxislocation, "zero"))
-    do_tics_1 (obj.xtickmode, obj.xtick, obj.xminortick, obj.xticklabelmode,
-               obj.xticklabel, obj.xcolor, "x", plot_stream, true, mono,
-               "axis", obj.tickdir, ticklength, fontname, fontspec,
-               obj.interpreter, obj.xscale, gnuplot_term);
-    do_tics_1 ("manual", [], "off", obj.xticklabelmode, obj.xticklabel,
-               obj.xcolor, "x2", plot_stream, true, mono, "axis",
-               "", "", fontname, fontspec, obj.interpreter, obj.xscale,
-               gnuplot_term);
-  else
-    do_tics_1 (obj.xtickmode, obj.xtick, obj.xminortick, obj.xticklabelmode,
-               obj.xticklabel, obj.xcolor, "x", plot_stream, true, mono,
-               "border", obj.tickdir, ticklength, fontname, fontspec,
-               obj.interpreter, obj.xscale, gnuplot_term);
-    do_tics_1 ("manual", [], "off", obj.xticklabelmode, obj.xticklabel,
-               obj.xcolor, "x2", plot_stream, true, mono, "border",
-               "", "", fontname, fontspec, obj.interpreter, obj.xscale,
-               gnuplot_term);
-  endif
-  if (strcmpi (obj.yaxislocation, "right"))
-    do_tics_1 (obj.ytickmode, obj.ytick, obj.yminortick, obj.yticklabelmode,
-               obj.yticklabel, obj.ycolor, "y2", plot_stream, ymirror, mono,
-               "border", obj.tickdir, ticklength, fontname, fontspec,
-               obj.interpreter, obj.yscale, gnuplot_term);
-    do_tics_1 ("manual", [], "off", obj.yticklabelmode, obj.yticklabel,
-               obj.ycolor, "y", plot_stream, ymirror, mono, "border",
-               "", "", fontname, fontspec, obj.interpreter, obj.yscale,
-               gnuplot_term);
-  elseif (strcmpi (obj.yaxislocation, "zero"))
-    do_tics_1 (obj.ytickmode, obj.ytick, obj.yminortick, obj.yticklabelmode,
-               obj.yticklabel, obj.ycolor, "y", plot_stream, ymirror, mono,
-               "axis", obj.tickdir, ticklength, fontname, fontspec,
-               obj.interpreter, obj.yscale, gnuplot_term);
-    do_tics_1 ("manual", [], "off", obj.yticklabelmode, obj.yticklabel,
-               obj.ycolor, "y2", plot_stream, ymirror, mono, "axis",
-               "", "", fontname, fontspec, obj.interpreter, obj.yscale,
-               gnuplot_term);
-  else
-    do_tics_1 (obj.ytickmode, obj.ytick, obj.yminortick, obj.yticklabelmode,
-               obj.yticklabel, obj.ycolor, "y", plot_stream, ymirror, mono,
-               "border", obj.tickdir, ticklength, fontname, fontspec,
-               obj.interpreter, obj.yscale, gnuplot_term);
-    do_tics_1 ("manual", [], "off", obj.yticklabelmode, obj.yticklabel,
-               obj.ycolor, "y2", plot_stream, ymirror, mono, "border",
-               "", "", fontname, fontspec, obj.interpreter, obj.yscale,
-               gnuplot_term);
-  endif
-  do_tics_1 (obj.ztickmode, obj.ztick, obj.zminortick, obj.zticklabelmode,
-             obj.zticklabel, obj.zcolor, "z", plot_stream, true, mono,
-             "border", obj.tickdir, ticklength, fontname, fontspec,
-             obj.interpreter, obj.zscale, gnuplot_term);
-endfunction
-
-function do_tics_1 (ticmode, tics, mtics, labelmode, labels, color, ax,
-                    plot_stream, mirror, mono, axispos, tickdir, ticklength,
-                    fontname, fontspec, interpreter, scale, gnuplot_term)
-  persistent warned_latex = false;
-  if (strcmpi (interpreter, "tex"))
-    for n = 1 : numel(labels)
-      labels{n} = __tex2enhanced__ (labels{n}, fontname, false, false);
-    endfor
-  elseif (strcmpi (interpreter, "latex"))
-    if (! warned_latex)
-      warning ("latex markup not supported for tick marks");
-      warned_latex = true;
-    endif
-  endif
-  if (strcmp (scale, "log"))
-    num_mtics = 10;
-    if (any (strcmp (gnuplot_term, {"tikz", "pstex", "pslatex", "epslatex"})))
-      fmt = "$10^{%T}$";
-    else
-      fmt = "10^{%T}";
-    endif
-  else
-    fmt = "%g";
-    num_mtics = 5;
-  endif
-  colorspec = get_text_colorspec (color, mono);
-  if (strcmpi (ticmode, "manual") || strcmpi (labelmode, "manual"))
-    if (isempty (tics))
-      fprintf (plot_stream, "unset %stics;\nunset m%stics;\n", ax, ax);
-    elseif (strcmpi (labelmode, "manual"))
-      if (ischar (labels))
-        labels = cellstr (labels);
-      endif
-      if (isnumeric (labels))
-        labels = num2str (real (labels(:)));
-      endif
-      if (ischar (labels))
-        labels = permute (cellstr (labels), [2, 1]);
-      endif
-      if (iscellstr (labels))
-        k = 1;
-        ntics = numel (tics);
-        nlabels = numel (labels);
-        fprintf (plot_stream, "set format %s \"%%s\";\n", ax);
-        if (mirror)
-          fprintf (plot_stream, "set %stics %s %s %s mirror (", ax,
-                   tickdir, ticklength, axispos);
-        else
-          fprintf (plot_stream, "set %stics %s %s %s nomirror (", ax,
-                   tickdir, ticklength, axispos);
-        endif
-
-        labels = regexprep(labels, '%', "%%");
-        for i = 1:ntics
-          fprintf (plot_stream, " \"%s\" %.15g", labels{k++}, tics(i));
-          if (i < ntics)
-            fputs (plot_stream, ", ");
-          endif
-          if (k > nlabels)
-            k = 1;
-          endif
-        endfor
-        fprintf (plot_stream, ") %s %s;\n", colorspec, fontspec);
-        if (strcmp (mtics, "on"))
-          fprintf (plot_stream, "set m%stics %d;\n", ax, num_mtics);
-        else
-          fprintf (plot_stream, "unset m%stics;\n", ax);
-        endif
-     else
-        error ("__go_draw_axes__: unsupported type of ticklabel");
-      endif
-    else
-      fprintf (plot_stream, "set format %s \"%s\";\n", ax, fmt);
-      if (mirror)
-        fprintf (plot_stream, "set %stics %s %s %s mirror (", ax, tickdir,
-                 ticklength, axispos);
-      else
-        fprintf (plot_stream, "set %stics %s %s %s nomirror (", ax, tickdir,
-                 ticklength, axispos);
-      endif
-      fprintf (plot_stream, " %.15g,", tics(1:end-1));
-      fprintf (plot_stream, " %.15g) %s;\n", tics(end), fontspec);
-      if (strcmp (mtics, "on"))
-        fprintf (plot_stream, "set m%stics %d;\n", ax, num_mtics);
-      else
-        fprintf (plot_stream, "unset m%stics;\n", ax);
-      endif
-    endif
-  else
-    fprintf (plot_stream, "set format %s \"%s\";\n", ax, fmt);
-    if (mirror)
-      fprintf (plot_stream, "set %stics %s %s %s mirror %s %s;\n", ax,
-               axispos, tickdir, ticklength, colorspec, fontspec);
-    else
-      fprintf (plot_stream, "set %stics %s %s %s nomirror %s %s;\n", ax,
-               tickdir, ticklength, axispos, colorspec, fontspec);
-    endif
-    if (strcmp (mtics, "on"))
-      fprintf (plot_stream, "set m%stics %d;\n", ax, num_mtics);
-    else
-      fprintf (plot_stream, "unset m%stics;\n", ax);
-    endif
-  endif
-endfunction
-
-function ticklabel = ticklabel_to_cell (ticklabel)
-  if (isnumeric (ticklabel))
-    ## Use upto 5 significant digits
-    ticklabel = num2str (ticklabel(:), 5);
-  endif
-  if (ischar (ticklabel))
-    if (size (ticklabel, 1) == 1 && any (ticklabel == "|"))
-      n = setdiff (findstr (ticklabel, "|"), findstr (ticklabel, '\|'));
-      ticklabel = strsplit (ticklabel, "|");
-    else
-      ticklabel = cellstr (ticklabel);
-    endif
-  elseif (isempty (ticklabel))
-    ticklabel = {""};
-  else
-    ticklabel = ticklabel;
-  endif
-endfunction
-
-function colorspec = get_text_colorspec (color, mono)
-  if (mono)
-    colorspec = "";
-  else
-    colorspec = sprintf ("textcolor rgb \"#%02x%02x%02x\"",
-                         round (255*color));
-  endif
-endfunction
-
-function [f, s, fnt, it, bld] = get_fontname_and_size (t)
-  if (isempty (t.fontname) || strcmp (t.fontname, "*"))
-    fnt = "{}";
-  else
-    fnt = t.fontname;
-  endif
-  f = fnt;
-  it = false;
-  bld = false;
-  if (! isempty (t.fontweight) && strcmpi (t.fontweight, "bold"))
-    if (! isempty(t.fontangle)
-        && (strcmpi (t.fontangle, "italic")
-            || strcmpi (t.fontangle, "oblique")))
-      f = cstrcat (f, "-bolditalic");
-      it = true;
-      bld = true;
-    else
-      f = cstrcat (f, "-bold");
-      bld = true;
-    endif
-  elseif (! isempty(t.fontangle)
-          && (strcmpi (t.fontangle, "italic")
-              || strcmpi (t.fontangle, "oblique")))
-    f = cstrcat (f, "-italic");
-    it = true;
-  endif
-  if (isempty (t.fontsize))
-    s = 10;
-  else
-    s = t.fontsize;
-  endif
-endfunction
-
-function [str, f, s] = __maybe_munge_text__ (enhanced, obj, fld)
-
-  persistent warned_latex = false;
-
-  if (strcmp (fld, "string"))
-    [f, s, fnt, it, bld] = get_fontname_and_size (obj);
-  else
-    f = "Helvetica";
-    s = 10;
-    fnt = f;
-    it = false;
-    bld = false;
-  endif
-
-  str = getfield (obj, fld);
-  if (enhanced)
-    if (strcmpi (obj.interpreter, "tex"))
-      str = __tex2enhanced__ (str, fnt, it, bld);
-    elseif (strcmpi (obj.interpreter, "latex"))
-      if (! warned_latex)
-        warning ("latex markup not supported for text objects");
-        warned_latex = true;
-      endif
-    endif
-  endif
-endfunction
-
-function str = __tex2enhanced__ (str, fnt, it, bld)
-  persistent sym = __setup_sym_table__ ();
-  persistent flds = fieldnames (sym);
-
-  [s, e, m] = regexp(str,'\\([a-zA-Z]+|0)','start','end','matches');
-
-  for i = length (s) : -1 : 1
-    ## special case for "\0"  and replace with "{/Symbol \306}'
-    if (strncmp (m{i}, '\0', 2))
-      str = cstrcat (str(1:s(i) - 1), '{/Symbol \306}', str(s(i) + 2:end));
-    else
-      f = m{i}(2:end);
-      if (isfield (sym, f))
-        g = getfield(sym, f);
-        ## FIXME The symbol font doesn't seem to support bold or italic
-        ##if (bld)
-        ##  if (it)
-        ##    g = regexprep (g, '/Symbol', '/Symbol-bolditalic');
-        ##  else
-        ##    g = regexprep (g, '/Symbol', '/Symbol-bold');
-        ##  endif
-        ##elseif (it)
-        ##  g = regexprep (g, '/Symbol', '/Symbol-italic');
-        ##endif
-        str = cstrcat (str(1:s(i) - 1), g, str(e(i) + 1:end));
-      elseif (strncmp (f, "rm", 2))
-        bld = false;
-        it = false;
-        str = cstrcat (str(1:s(i) - 1), '/', fnt, ' ', str(s(i) + 3:end));
-      elseif (strncmp (f, "it", 2) || strncmp (f, "sl", 2))
-        it = true;
-        if (bld)
-          str = cstrcat (str(1:s(i) - 1), '/', fnt, '-bolditalic ',
-                        str(s(i) + 3:end));
-        else
-          str = cstrcat (str(1:s(i) - 1), '/', fnt, '-italic ',
-                        str(s(i) + 3:end));
-        endif
-      elseif (strncmp (f, "bf", 2))
-        bld = true;
-        if (it)
-          str = cstrcat (str(1:s(i) - 1), '/', fnt, '-bolditalic ',
-                        str(2(i) + 3:end));
-        else
-          str = cstrcat (str(1:s(i) - 1), '/', fnt, '-bold ',
-                        str(s(i) + 3:end));
-        endif
-      elseif (strcmpi (f, "color"))
-        ## FIXME Ignore \color but remove trailing {} block as well
-        d = strfind(str(e(i) + 1:end),'}');
-        if (isempty (d))
-          warning ('syntax error in \color argument');
-        else
-          str = cstrcat (str(1:s(i) - 1), str(e(i) + d + 1:end));
-        endif
-      elseif(strcmpi (f, "fontname"))
-        b1 = strfind(str(e(i) + 1:end),'{');
-        b2 = strfind(str(e(i) + 1:end),'}');
-        if (isempty(b1) || isempty(b2))
-          warning ('syntax error in \fontname argument');
-        else
-          str = cstrcat (str(1:s(i) - 1), '/',
-                        str(e(i)+b1(1) + 1:e(i)+b2(1)-1), '{}',
-                        str(e(i) + b2(1) + 1:end));
-        endif
-      elseif(strcmpi (f, "fontsize"))
-        b1 = strfind(str(e(i) + 1:end),'{');
-        b2 = strfind(str(e(i) + 1:end),'}');
-        if (isempty(b1) || isempty(b2))
-          warning ('syntax error in \fontname argument');
-        else
-          str = cstrcat (str(1:s(i) - 1), '/=',
-                        str(e(i)+b1(1) + 1:e(i)+b2(1)-1), '{}',
-                        str(e(i) + b2(1) + 1:end));
-        endif
-      else
-        ## Last desperate attempt to treat the symbol. Look for things
-        ## like \pix, that should be translated to the symbol Pi and x
-        for j = 1 : length (flds)
-          if (strncmp (flds{j}, f, length (flds{j})))
-            g = getfield(sym, flds{j});
-            ## FIXME The symbol font doesn't seem to support bold or italic
-            ##if (bld)
-            ##  if (it)
-            ##    g = regexprep (g, '/Symbol', '/Symbol-bolditalic');
-            ##  else
-            ##    g = regexprep (g, '/Symbol', '/Symbol-bold');
-            ##  endif
-            ##elseif (it)
-            ##  g = regexprep (g, '/Symbol', '/Symbol-italic');
-            ##endif
-            str = cstrcat (str(1:s(i) - 1), g,
-                          str(s(i) + length (flds{j}) + 1:end));
-            break;
-          endif
-        endfor
-      endif
-    endif
-  endfor
-
-  ## Prepend @ to things  things like _0^x or _{-100}^{100} for
-  ## alignment But need to put the shorter of the two arguments first.
-  ## Carful of nested {} and unprinted characters when defining
-  ## shortest.. Don't have to worry about things like ^\theta as they
-  ## are already converted to ^{/Symbol q}.
-
-  ## FIXME -- This is a mess... Is it worth it just for a "@" character?
-
-  [s, m] = regexp(str,'[_\^]','start','matches');
-  i = 1;
-  p = 0;
-  while (i < length (s))
-    if (i < length(s))
-      if (str(s(i) + p + 1) == "{")
-        s1 = strfind(str(s(i) + p + 2:end),'{');
-        si = 1;
-        l1 = strfind(str(s(i) + p + 1:end),'}');
-        li = 1;
-        while (li <= length (l1) && si <= length (s1))
-          if (l1(li) < s1(si))
-            if (li == si)
-              break;
-            endif
-            li++;
-          else
-            si++;
-          endif
-        endwhile
-        l1 = l1 (min (length(l1), si));
-        if (s(i) + l1 + 1 == s(i+1))
-          if (str(s(i + 1) + p + 1) == "{")
-            s2 = strfind(str(s(i + 1) + p + 2:end),'{');
-            si = 1;
-            l2 = strfind(str(s(i + 1) + p + 1:end),'}');
-            li = 1;
-            while (li <= length (l2) && si <= length (s2))
-              if (l2(li) < s2(si))
-                if (li == si)
-                  break;
-                endif
-                li++;
-              else
-                si++;
-              endif
-            endwhile
-            l2 = l2 (min (length(l2), si));
-            if (length_string (str(s(i)+p+2:s(i)+p+l1-1)) <=
-                length_string(str(s(i+1)+p+2:s(i+1)+p+l2-1)))
-              ## Shortest already first!
-              str = cstrcat (str(1:s(i)+p-1), "@", str(s(i)+p:end));
-            else
-              ## Have to swap sub/super-script to get shortest first.
-              str = cstrcat (str(1:s(i)+p-1), "@", str(s(i+1)+p:s(i+1)+p+l2),
-                            str(s(i)+p:s(i)+p+l1), str(s(i+1)+p+l2+1:end));
-            endif
-          else
-            ## Have to swap sub/super-script to get shortest first.
-            str = cstrcat (str(1:s(i)+p-1), "@", str(s(i+1)+p:s(i+1)+p+1),
-                          str(s(i)+p:s(i)+p+l1), str(s(i+1)+p+2:end));
-          endif
-          i += 2;
-          p ++;
-        else
-          i++;
-        endif
-      else
-        if (s(i+1) == s(i) + 2)
-          ## Shortest already first!
-          str = cstrcat (str(1:s(i)+p-1), "@", str(s(i)+p:end));
-          p ++;
-          i += 2;
-        else
-          i ++;
-        endif
-      endif
-    else
-      i ++;
-    endif
-  endwhile
-
-endfunction
-
-function l = length_string (s)
-  l = length (s) - length (strfind(s,'{')) - length (strfind(s,'}'));
-  m = regexp (s, '/([\w-]+|[\w-]+=\d+)', 'matches');
-  if (!isempty (m))
-    l = l - sum (cellfun (@length, m));
-  endif
-endfunction
-
-function sym = __setup_sym_table__ ()
-  ## Setup the translation table for TeX to gnuplot enhanced mode.
-  sym.forall = '{/Symbol \042}';
-  sym.exists = '{/Symbol \044}';
-  sym.ni = '{/Symbol \047}';
-  sym.cong = '{/Symbol \100}';
-  sym.Delta = '{/Symbol D}';
-  sym.Phi = '{/Symbol F}';
-  sym.Gamma = '{/Symbol G}';
-  sym.vartheta = '{/Symbol J}';
-  sym.Lambda = '{/Symbol L}';
-  sym.Pi = '{/Symbol P}';
-  sym.Theta = '{/Symbol Q}';
-  sym.Sigma = '{/Symbol S}';
-  sym.varsigma = '{/Symbol V}';
-  sym.Omega = '{/Symbol W}';
-  sym.Xi = '{/Symbol X}';
-  sym.Psi = '{/Symbol Y}';
-  sym.perp = '{/Symbol \136}';
-  sym.alpha = '{/Symbol a}';
-  sym.beta = '{/Symbol b}';
-  sym.chi = '{/Symbol c}';
-  sym.delta = '{/Symbol d}';
-  sym.epsilon = '{/Symbol e}';
-  sym.phi = '{/Symbol f}';
-  sym.gamma = '{/Symbol g}';
-  sym.eta = '{/Symbol h}';
-  sym.iota = '{/Symbol i}';
-  sym.varphi = '{/Symbol j}';
-  sym.kappa = '{/Symbol k}';
-  sym.lambda = '{/Symbol l}';
-  sym.mu = '{/Symbol m}';
-  sym.nu = '{/Symbol n}';
-  sym.o =  '{/Symbol o}';
-  sym.pi = '{/Symbol p}';
-  sym.theta = '{/Symbol q}';
-  sym.rho = '{/Symbol r}';
-  sym.sigma = '{/Symbol s}';
-  sym.tau = '{/Symbol t}';
-  sym.upsilon = '{/Symbol u}';
-  sym.varpi = '{/Symbol v}';
-  sym.omega = '{/Symbol w}';
-  sym.xi = '{/Symbol x}';
-  sym.psi = '{/Symbol y}';
-  sym.zeta = '{/Symbol z}';
-  sym.sim = '{/Symbol \176}';
-  sym.Upsilon = '{/Symbol \241}';
-  sym.prime = '{/Symbol \242}';
-  sym.leq = '{/Symbol \243}';
-  sym.infty = '{/Symbol \245}';
-  sym.clubsuit = '{/Symbol \247}';
-  sym.diamondsuit = '{/Symbol \250}';
-  sym.heartsuit = '{/Symbol \251}';
-  sym.spadesuit = '{/Symbol \252}';
-  sym.leftrightarrow = '{/Symbol \253}';
-  sym.leftarrow = '{/Symbol \254}';
-  sym.uparrow = '{/Symbol \255}';
-  sym.rightarrow = '{/Symbol \256}';
-  sym.downarrow = '{/Symbol \257}';
-  sym.circ = '{/Symbol \260}';
-  sym.pm = '{/Symbol \261}';
-  sym.geq = '{/Symbol \263}';
-  sym.times = '{/Symbol \264}';
-  sym.propto = '{/Symbol \265}';
-  sym.partial = '{/Symbol \266}';
-  sym.bullet = '{/Symbol \267}';
-  sym.div = '{/Symbol \270}';
-  sym.neq = '{/Symbol \271}';
-  sym.equiv = '{/Symbol \272}';
-  sym.approx = '{/Symbol \273}';
-  sym.ldots = '{/Symbol \274}';
-  sym.mid = '{/Symbol \275}';
-  sym.aleph = '{/Symbol \300}';
-  sym.Im = '{/Symbol \301}';
-  sym.Re = '{/Symbol \302}';
-  sym.wp = '{/Symbol \303}';
-  sym.otimes = '{/Symbol \304}';
-  sym.oplus = '{/Symbol \305}';
-  sym.oslash = '{/Symbol \306}';
-  sym.cap = '{/Symbol \307}';
-  sym.cup = '{/Symbol \310}';
-  sym.supset = '{/Symbol \311}';
-  sym.supseteq = '{/Symbol \312}';
-  sym.subset = '{/Symbol \314}';
-  sym.subseteq = '{/Symbol \315}';
-  sym.in = '{/Symbol \316}';
-  sym.notin = '{/Symbol \317}';
-  sym.angle = '{/Symbol \320}';
-  sym.bigtriangledown = '{/Symbol \321}';
-  sym.langle = '{/Symbol \341}';
-  sym.rangle = '{/Symbol \361}';
-  sym.nabla = '{/Symbol \321}';
-  sym.prod = '{/Symbol \325}';
-  sym.surd = '{/Symbol \326}';
-  sym.cdot = '{/Symbol \327}';
-  sym.neg = '{/Symbol \330}';
-  sym.wedge = '{/Symbol \331}';
-  sym.vee = '{/Symbol \332}';
-  sym.Leftrightarrow = '{/Symbol \333}';
-  sym.Leftarrow = '{/Symbol \334}';
-  sym.Uparrow = '{/Symbol \335}';
-  sym.Rightarrow = '{/Symbol \336}';
-  sym.Downarrow = '{/Symbol \337}';
-  sym.diamond = '{/Symbol \340}';
-  sym.copyright = '{/Symbol \343}';
-  sym.lfloor = '{/Symbol \353}';
-  sym.lceil  = '{/Symbol \351}';
-  sym.rfloor = '{/Symbol \373}';
-  sym.rceil  = '{/Symbol \371}';
-  sym.int = '{/Symbol \362}';
-endfunction
-
-function retval = __do_enhanced_option__ (enhanced, obj)
-  retval = "";
-  if (enhanced)
-    if (strcmpi (obj.interpreter, "none"))
-      retval = "noenhanced";
-    else
-      retval = "enhanced";
-    endif
-  endif
-endfunction
--- a/scripts/plot/__go_draw_figure__.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,198 +0,0 @@
-## Copyright (C) 2005-2011 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} {} __go_draw_figure__ (@var{h}, @var{plot_stream}, @var{enhanced}, @var{mono})
-## Undocumented internal function.
-## @end deftypefn
-
-## Author: jwe
-
-function __go_draw_figure__ (h, plot_stream, enhanced, mono)
-
-  if (nargin == 4)
-    htype = get (h, "type");
-    if (strcmp (htype, "figure"))
-      ## Get complete list of children.
-      kids = allchild (h);
-      nkids = length (kids);
-
-      if (nkids > 0)
-        fputs (plot_stream, "\nreset;\n");
-        fputs (plot_stream, "set autoscale keepfix;\n");
-        fputs (plot_stream, "set origin 0, 0\n");
-        fputs (plot_stream, "set size 1, 1\n");
-        bg = get (h, "color");
-        if (isnumeric (bg))
-          fprintf (plot_stream, "set obj 1 rectangle from screen 0,0 to screen 1,1 behind fc rgb \"#%02x%02x%02x\"\n", 255 * bg);
-          bg_is_set = true;
-        else
-          bg_is_set = false;
-        endif
-
-        for i = nkids:-1:1
-          type = get (kids(i), "type");
-          switch (type)
-            case "axes"
-              if (strcmpi (get (kids (i), "tag"), "legend"))
-                ## This is so ugly. If there was a way of getting
-                ## gnuplot to give us the text extents of strings
-                ## then we could get rid of this mess.
-                lh = getfield (get (kids(i), "userdata"), "handle");
-                if (isscalar (lh))
-                  ## We have a legend with a single parent. It'll be handled
-                  ## below as a gnuplot key to the axis it corresponds to
-                  continue;
-                else
-                  ca = lh(1);
-                  ## Rely upon listener to convert axes position
-                  ## to "normalized" units.
-                  legend_axes_units = get (kids(i), "units");
-                  legend_axes_position = get (kids(i), "position");
-                  legend_axes_outerposition = get (kids(i), "outerposition");
-                  legend_axes_box = get (kids(i), "box");
-                  legend_axes_ylim = get (kids(i), "ylim");
-                  orig_axes_units = get (ca, "units");
-                  hlgnd = get (kids(i));
-
-                  unwind_protect
-                    set (ca, "units", "normalized");
-                    set (kids(i), "units", "normalized", "box", "off",
-                         "ylim", [-2, -1], "position", get (ca(1), "position"),
-                         "outerposition", get (ca(1), "outerposition"));
-
-                    ## Create a new set of lines with the appropriate
-                    ## displaynames, etc
-                    toberm = [];
-                    hobj = get (kids(i), "children");
-                    for j = numel (hobj) : -1 : 1
-                      if (! strcmp (get (hobj(j), "type"), "text"))
-                        continue;
-                      endif
-                      displayname = get (hobj(j), "string");
-                      ll = [];
-                      lm = [];
-                      for k = numel (hobj) : -1 : 1
-                        if (! strcmp (get (hobj(k), "type"), "line"))
-                          continue;
-                        endif
-                        if (get (hobj(j), "userdata")
-                            != get (hobj(k), "userdata"))
-                          continue;
-                        endif
-                        if (! strcmp (get (hobj(k), "linestyle"), "none"))
-                          ll = hobj(k);
-                        endif
-                        if (! strcmp (get (hobj(k), "marker"), "none"))
-                          lm = hobj(k);
-                        endif
-                      endfor
-
-                      if (! isempty (ll))
-                        if (!isempty (lm))
-                          toberm = [toberm, line("xdata",[0,0],"ydata",[0,0], "color", get(lm,"color"), "linestyle", get(ll,"linestyle"), "marker", get(lm,"marker"), "markeredgecolor", get(lm,"markeredgecolor"), "markerfacecolor", get(lm,"markerfacecolor"), "markersize", get (lm, "markersize"), "displayname", displayname, "parent", kids(i))];
-                        else
-                          toberm = [toberm, line("xdata",[0,0],"ydata",[0,0], "color", get(ll,"color"), "linestyle", get(ll,"linestyle"), "marker", "none", "displayname", displayname, "parent", kids(i))];
-                        endif
-                      elseif (! isempty (lm))
-                        toberm = [toberm, line("xdata",[0,0],"ydata",[0,0], "color", get(lm,"color"), "linestyle", "none", "marker", get(lm,"marker"), "markeredgecolor", get(lm,"markeredgecolor"), "markerfacecolor", get(lm,"markerfacecolor"), "markersize", get (lm, "markersize"), "displayname", displayname, "parent", kids(i))];
-                      endif
-                    endfor
-                    if (bg_is_set)
-                      fprintf (plot_stream, "set border linecolor rgb \"#%02x%02x%02x\"\n", 255 * (1 - bg));
-                    endif
-                    __go_draw_axes__ (kids(i), plot_stream, enhanced, mono,
-                                      bg_is_set, false, hlgnd);
-                  unwind_protect_cleanup
-                    ## Return axes "units" and "position" back to
-                    ## their original values.
-                    set (ca, "units", orig_axes_units);
-                    set (kids(i), "units", legend_axes_units,
-                         "box", legend_axes_box,
-                         "ylim", legend_axes_ylim,
-                         "position", legend_axes_position,
-                         "outerposition", legend_axes_outerposition);
-                    delete (toberm);
-                    bg_is_set = false;
-                  end_unwind_protect
-                endif
-              else
-                ## Rely upon listener to convert axes position
-                ## to "normalized" units.
-                orig_axes_units = get (kids(i), "units");
-                orig_axes_position = get (kids(i), "position");
-                unwind_protect
-                  set (kids(i), "units", "normalized");
-                  fg = get (kids(i), "color");
-                  if (isnumeric (fg) && strcmp (get (kids(i), "visible"), "on"))
-                    fprintf (plot_stream, "set obj 2 rectangle from graph 0,0 to graph 1,1 behind fc rgb \"#%02x%02x%02x\"\n", 255 * fg);
-                    fg_is_set = true;
-                  else
-                    fg_is_set = false;
-                  endif
-                  if (bg_is_set)
-                    fprintf (plot_stream, "set border linecolor rgb \"#%02x%02x%02x\"\n", 255 * (1 - bg));
-                  endif
-                  ## Find if this axes has an associated legend axes and pass it
-                  ## to __go_draw_axes__
-                  hlegend = [];
-                  fkids = get (h, "children");
-                  for j = 1 : numel(fkids)
-                    if (ishandle (fkids (j))
-                        && strcmp (get (fkids (j), "type"), "axes")
-                        && (strcmp (get (fkids (j), "tag"), "legend")))
-                      udata = get (fkids (j), "userdata");
-                      if (isscalar(udata.handle)
-                          && ! isempty (intersect (udata.handle, kids (i))))
-                        hlegend = get (fkids (j));
-                        break;
-                      endif
-                    endif
-                  endfor
-                  __go_draw_axes__ (kids(i), plot_stream, enhanced, mono,
-                                    bg_is_set, fg_is_set, hlegend);
-                unwind_protect_cleanup
-                  ## Return axes "units" and "position" back to
-                  ## their original values.
-                  set (kids(i), "units", orig_axes_units);
-                  set (kids(i), "position", orig_axes_position);
-                  bg_is_set = false;
-                  fg_is_set = false;
-                end_unwind_protect
-              endif
-            case "uimenu"
-              ## ignore uimenu objects
-            otherwise
-              error ("__go_draw_figure__: unknown object class, %s", type);
-          endswitch
-        endfor
-        fputs (plot_stream, "\nunset multiplot;\n");
-      else
-        fputs (plot_stream, "\nreset; clear;\n");
-        fflush (plot_stream);
-      endif
-    else
-      error ("__go_draw_figure__: expecting figure object, found `%s'",
-             htype);
-    endif
-  else
-    print_usage ();
-  endif
-
-endfunction
-
--- a/scripts/plot/__marching_cube__.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,530 +0,0 @@
-## Copyright (C) 2009-2011 Martin Helm
-##
-## 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn  {Function File} {[@var{t}, @var{p}] =} __marching_cube__ (@var{x}, @var{y}, @var{z}, @var{val}, @var{iso})
-## @deftypefnx {Function File} {[@var{t}, @var{p}, @var{c}] =} __marching_cube__ (@var{x}, @var{y}, @var{z}, @var{val}, @var{iso}, @var{col})
-## Undocumented internal function.
-## @end deftypefn
-
-## -*- texinfo -*-
-## @deftypefn  {Function File} {[@var{t}, @var{p}] =} __marching_cube__ (@var{x}, @var{y}, @var{z}, @var{val}, @var{iso})
-## @deftypefnx {Function File} {[@var{t}, @var{p}, @var{c}] =} __marching_cube__ (@var{x}, @var{y}, @var{z}, @var{val}, @var{iso}, @var{col})
-##
-## Return the triangulation information @var{t} at points @var{p} for
-## the isosurface values resp. the volume data @var{val} and the iso
-## level @var{iso}.  It is considered that the volume data @var{val} is
-## given at the points @var{x}, @var{y} and @var{z} which are of type
-## three--dimensional numeric arrays.  The orientation of the triangles
-## is choosen such that the normals point from the higher values to the
-## lower values.
-##
-## Optionally the color data @var{col} can be passed to this function
-## whereas computed vertices color data @var{c} is returned as third
-## argument.
-##
-## The marching cube algorithm is well known and described, for example, at
-## Wikipedia.  The triangulation lookup table and the edge table used
-## here are based on Cory Gene Bloyd's implementation and can be found
-## beyond other surface and geometry stuff at Paul Bourke's website
-## @uref{http://local.wasp.uwa.edu.au/~pbourke/geometry/polygonise}.
-##
-## For example:
-##
-## @example
-## @group
-## N = 20;
-## lin = linspace(0, 2, N);
-## [x, y, z] = meshgrid (lin, lin, lin);
-##
-## c = (x-.5).^2 + (y-.5).^2 + (z-.5).^2;
-## [t, p] = __marching_cube__ (x, y, z, c, .5);
-##
-## figure ();
-## trimesh (t, p(:,1), p(:,2), p(:,3));
-## @end group
-## @end example
-##
-## Instead of the @command{trimesh} function the @command{patch}
-## function can be used to visualize the geometry.  For example:
-##
-## @example
-## @group
-## figure (); view (-38, 20);
-## pa = patch ("Faces", t, "Vertices", p, "FaceVertexCData", p, \
-##             "FaceColor", "interp", "EdgeColor", "none");
-##
-## ## Revert normals
-## set (pa, "VertexNormals", -get(pa, "VertexNormals"));
-##
-## ## Set lightning (available with the JHandles package)
-## # set (pa, "FaceLighting", "gouraud");
-## # light( "Position", [1 1 5]);
-## @end group
-## @end example
-##
-## @end deftypefn
-
-## Author: Martin Helm <martin@mhelm.de>
-
-function [T, p, col] = __marching_cube__ (xx, yy, zz, c, iso, colors)
-
-  persistent edge_table=[];
-  persistent tri_table=[];
-
-  calc_cols = false;
-  lindex = 4;
-
-  if (isempty (tri_table) || isempty (edge_table))
-    [edge_table, tri_table] = init_mc ();
-  endif
-
-  if ((nargin != 5 && nargin != 6) || (nargout != 2 && nargout != 3))
-    print_usage ();
-  endif
-
-  if (!ismatrix (xx) || !ismatrix (yy) || !ismatrix (zz) || !ismatrix (c) || ...
-    ndims (xx) != 3 || ndims (yy) != 3 || ndims (zz) != 3 || ndims (c) != 3)
-    error ("__marching_cube__: XX, YY, ZZ, C must be matrices of dim 3");
-  endif
-
-  if (!size_equal (xx, yy, zz, c))
-    error ("__marching_cube__: XX, YY, ZZ, C must be of equal size");
-  endif
-
-  if (any (size (xx) < [2 2 2]))
-    error ("__marching_cube__: grid size must be at least 2x2x2");
-  endif
-
-  if (!isscalar (iso))
-    error ("__marching_cube__: ISO must be scalar value");
-  endif
-
-  if (nargin == 6)
-    if ( !ismatrix (colors) || ndims (colors) != 3 || size (colors) != size (c) )
-      error ( "COLORS must be a matrix of dim 3 and of same size as C" );
-    endif
-    calc_cols = true;
-    lindex = 5;
-  endif
-
-  n = size (c) - 1;
-
-  ## phase I: assign information to each voxel which edges are intersected by
-  ## the isosurface
-  cc = zeros (n(1), n(2), n(3), "uint16");
-  cedge = zeros (size (cc), "uint16");
-
-  vertex_idx = {1:n(1), 1:n(2), 1:n(3); ...
-    2:n(1)+1, 1:n(2), 1:n(3); ...
-    2:n(1)+1, 2:n(2)+1, 1:n(3); ...
-    1:n(1), 2:n(2)+1, 1:n(3); ...
-    1:n(1), 1:n(2), 2:n(3)+1; ...
-    2:n(1)+1, 1:n(2), 2:n(3)+1; ...
-    2:n(1)+1, 2:n(2)+1, 2:n(3)+1; ...
-    1:n(1), 2:n(2)+1, 2:n(3)+1 };
-
-  ## calculate which vertices have values higher than iso
-  for ii=1:8
-    idx = c(vertex_idx{ii, :}) > iso;
-    cc(idx) = bitset (cc(idx), ii);
-  endfor
-
-  cedge = edge_table(cc+1); # assign the info about intersected edges
-  id =  find (cedge); # select only voxels which are intersected
-  if (isempty (id))
-    T = p = col = [];
-    return
-  endif
-
-  ## phase II: calculate the list of intersection points
-  xyz_off = [1, 1, 1; 2, 1, 1; 2, 2, 1; 1, 2, 1; 1, 1, 2;  2, 1, 2; 2, 2, 2; 1, 2, 2];
-  edges = [1 2; 2 3; 3 4; 4 1; 5 6; 6 7; 7 8; 8 5; 1 5; 2 6; 3 7; 4 8];
-  offset = sub2ind (size (c), xyz_off(:, 1), xyz_off(:, 2), xyz_off(:, 3)) -1;
-  pp = zeros (length (id), lindex, 12);
-  ccedge = [vec(cedge(id)), id];
-  ix_offset=0;
-  for jj=1:12
-    id__ = bitget (ccedge(:, 1), jj);
-    id_ = ccedge(id__, 2);
-    [ix iy iz] = ind2sub (size (cc), id_);
-    id_c = sub2ind (size (c), ix, iy, iz);
-    id1 = id_c + offset(edges(jj, 1));
-    id2 = id_c + offset(edges(jj, 2));
-    if (calc_cols)
-      pp(id__, 1:5, jj) = [vertex_interp(iso, xx(id1), yy(id1), zz(id1), ...
-        xx(id2), yy(id2), zz(id2), c(id1), c(id2), colors(id1), colors(id2)), ...
-        (1:size (id_, 1))' + ix_offset ];
-    else
-      pp(id__, 1:4, jj) = [vertex_interp(iso, xx(id1), yy(id1), zz(id1), ...
-        xx(id2), yy(id2), zz(id2), c(id1), c(id2)), ...
-        (1:size (id_, 1))' + ix_offset ];
-    endif
-    ix_offset += size (id_, 1);
-  endfor
-
-  ## phase III: calculate the triangulation from the point list
-  T = [];
-  tri = tri_table(cc(id)+1, :);
-  for jj=1:3:15
-    id_ = find (tri(:, jj)>0);
-    p = [id_, lindex*ones(size (id_, 1), 1),tri(id_, jj:jj+2)];
-    if (!isempty (p))
-      p1 = sub2ind (size (pp), p(:,1), p(:,2), p(:,3));
-      p2 = sub2ind (size (pp), p(:,1), p(:,2), p(:,4));
-      p3 = sub2ind (size (pp), p(:,1), p(:,2), p(:,5));
-      T = [T; pp(p1), pp(p2), pp(p3)];
-    endif
-  endfor
-
-  p = [];
-  col = [];
-  for jj = 1:12
-    idp = pp(:, lindex, jj) > 0;
-    if (any (idp))
-      p(pp(idp, lindex, jj), 1:3) = pp(idp, 1:3, jj);
-      if (calc_cols)
-        col(pp(idp, lindex, jj),1) = pp(idp, 4, jj);
-      endif
-    endif
-  endfor
-endfunction
-
-function p = vertex_interp(isolevel,p1x, p1y, p1z,...
-  p2x, p2y, p2z,valp1,valp2, col1, col2)
-
-  if (nargin == 9)
-    p = zeros (length (p1x), 3);
-  elseif (nargin == 11)
-    p = zeros (length (p1x), 4);
-  else
-    error ("__marching_cube__: wrong number of arguments");
-  endif
-  mu = zeros (length (p1x), 1);
-  id = abs (valp1-valp2) < (10*eps) .* (abs (valp1) .+ abs (valp2));
-  if (any (id))
-    p(id, 1:3) = [ p1x(id), p1y(id), p1z(id) ];
-    if (nargin == 11)
-      p(id, 4) = col1(id);
-    endif
-  endif
-  nid = !id;
-  if (any (nid))
-    mu(nid) = (isolevel - valp1(nid)) ./ (valp2(nid) - valp1(nid));
-    p(nid, 1:3) = [p1x(nid) + mu(nid) .* (p2x(nid) - p1x(nid)), ...
-      p1y(nid) + mu(nid) .* (p2y(nid) - p1y(nid)), ...
-      p1z(nid) + mu(nid) .* (p2z(nid) - p1z(nid))];
-    if (nargin == 11)
-      p(nid, 4) = col1(nid) + mu(nid) .* (col2(nid) - col1(nid));
-    endif
-  endif
-endfunction
-
-function [edge_table, tri_table] = init_mc()
-  edge_table = [
-  0x0  , 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c, ...
-  0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00, ...
-  0x190, 0x99 , 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c, ...
-  0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90, ...
-  0x230, 0x339, 0x33 , 0x13a, 0x636, 0x73f, 0x435, 0x53c, ...
-  0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30, ...
-  0x3a0, 0x2a9, 0x1a3, 0xaa , 0x7a6, 0x6af, 0x5a5, 0x4ac, ...
-  0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0, ...
-  0x460, 0x569, 0x663, 0x76a, 0x66 , 0x16f, 0x265, 0x36c, ...
-  0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60, ...
-  0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff , 0x3f5, 0x2fc, ...
-  0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0, ...
-  0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55 , 0x15c, ...
-  0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950, ...
-  0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc , ...
-  0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0, ...
-  0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc, ...
-  0xcc , 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0, ...
-  0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c, ...
-  0x15c, 0x55 , 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650, ...
-  0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc, ...
-  0x2fc, 0x3f5, 0xff , 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0, ...
-  0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c, ...
-  0x36c, 0x265, 0x16f, 0x66 , 0x76a, 0x663, 0x569, 0x460, ...
-  0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac, ...
-  0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa , 0x1a3, 0x2a9, 0x3a0, ...
-  0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c, ...
-  0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x33 , 0x339, 0x230, ...
-  0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c, ...
-  0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99 , 0x190, ...
-  0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c, ...
-  0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x0   ];
-
-  tri_table =[
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1;
-  3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1;
-  3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1;
-  3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1;
-  9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1;
-  1, 2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1;
-  9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1;
-  2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1;
-  8, 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1;
-  9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1;
-  4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1;
-  3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1;
-  1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1;
-  4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1;
-  4, 7, 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1;
-  9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1;
-  1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1;
-  5, 2, 10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1;
-  2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1;
-  9, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  0, 11, 2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1;
-  0, 5, 4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1;
-  2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1;
-  10, 3, 11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1;
-  4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1;
-  5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1;
-  5, 4, 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1;
-  9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1;
-  0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1;
-  1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1;
-  10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1;
-  8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1;
-  2, 10, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1;
-  7, 9, 5, 7, 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1;
-  9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1;
-  2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1;
-  11, 2, 1, 11, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1;
-  9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, -1, -1, -1, -1;
-  5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, -1;
-  11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, -1;
-  11, 10, 5, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  1, 8, 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1;
-  1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  1, 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1;
-  9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1;
-  5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1;
-  2, 3, 11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1;
-  0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1;
-  5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1;
-  6, 3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1;
-  0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1;
-  3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1;
-  6, 5, 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1;
-  5, 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1;
-  1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1;
-  10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1;
-  6, 1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1;
-  1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1;
-  8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1;
-  7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1;
-  3, 11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1;
-  5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1;
-  0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1;
-  9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, -1;
-  8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, -1, -1, -1, -1;
-  5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, -1;
-  0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, -1;
-  6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, -1, -1, -1, -1;
-  10, 4, 9, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  4, 10, 6, 4, 9, 10, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1;
-  10, 0, 1, 10, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1;
-  8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, -1, -1, -1, -1;
-  1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1;
-  3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, -1, -1, -1, -1;
-  0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1;
-  10, 4, 9, 10, 6, 4, 11, 2, 3, -1, -1, -1, -1, -1, -1, -1;
-  0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, -1, -1, -1, -1;
-  3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, -1, -1, -1, -1;
-  6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, -1;
-  9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, -1, -1, -1, -1;
-  8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, -1;
-  3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1;
-  6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1;
-  0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, -1, -1, -1, -1;
-  10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1;
-  10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1;
-  1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1;
-  2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, -1;
-  7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1;
-  7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, -1, -1, -1;
-  2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, -1;
-  1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, -1;
-  11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, -1;
-  8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1;
-  0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1;
-  7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  8, 1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1;
-  10, 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1;
-  2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1;
-  6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1;
-  7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1;
-  2, 7, 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1;
-  1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1;
-  10, 7, 6, 10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1;
-  10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1;
-  0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1;
-  7, 6, 10, 7, 10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1;
-  6, 8, 4, 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  3, 6, 11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1;
-  8, 6, 11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1;
-  9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1;
-  6, 8, 4, 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1;
-  1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1;
-  4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1;
-  10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1;
-  8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1;
-  0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1;
-  1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1;
-  8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1;
-  10, 1, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1;
-  4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1;
-  10, 9, 4, 6, 10, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1;
-  5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1;
-  11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1;
-  9, 5, 4, 10, 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1;
-  6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1;
-  7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1;
-  3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, -1;
-  7, 2, 3, 7, 6, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1;
-  9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, -1, -1, -1, -1;
-  3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, -1, -1, -1, -1;
-  6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, -1;
-  9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, -1, -1, -1, -1;
-  1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, -1;
-  4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, -1;
-  7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1, -1, -1;
-  6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1;
-  3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1;
-  0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1, -1;
-  6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1;
-  1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1, -1;
-  0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1;
-  11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1;
-  6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1;
-  5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1;
-  9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1;
-  1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, -1;
-  1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, -1;
-  10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, -1, -1, -1, -1;
-  0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  11, 5, 10, 7, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  11, 5, 10, 11, 7, 5, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1;
-  5, 11, 7, 5, 10, 11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1;
-  10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1;
-  11, 1, 2, 11, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1;
-  0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1;
-  9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1;
-  7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, -1;
-  2, 5, 10, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1;
-  8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, -1, -1, -1, -1;
-  9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, -1, -1, -1, -1;
-  9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, -1;
-  1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1;
-  9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1;
-  9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  5, 8, 4, 5, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1;
-  5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, -1, -1, -1, -1;
-  0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, -1, -1, -1, -1;
-  10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, -1;
-  2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, -1, -1, -1, -1;
-  0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, -1;
-  0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, -1;
-  9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1;
-  5, 10, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1;
-  3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, -1;
-  5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, -1, -1, -1, -1;
-  8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1;
-  0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, -1, -1, -1, -1;
-  9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  4, 11, 7, 4, 9, 11, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1;
-  0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, -1, -1, -1, -1;
-  1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, -1, -1, -1, -1;
-  3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, -1;
-  4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, -1, -1, -1, -1;
-  9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, -1;
-  11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1;
-  11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, -1, -1, -1, -1;
-  2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1;
-  9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, -1;
-  3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, -1;
-  1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1;
-  4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, -1;
-  4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1;
-  0, 1, 10, 0, 10, 8, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1;
-  3, 1, 10, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  1, 2, 11, 1, 11, 9, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1;
-  3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, -1, -1, -1, -1;
-  0, 2, 11, 8, 0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  2, 3, 8, 2, 8, 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1;
-  9, 10, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1;
-  1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ] + 1;
-endfunction
--- a/scripts/plot/__next_line_color__.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-## Copyright (C) 2007-2011 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} {@var{rgb} =} __next_line_color__ (@var{reset})
-## Undocumented internal function.
-## @end deftypefn
-
-## Return the next line color in the rotation.
-
-## Author: jwe
-
-function rgb = __next_line_color__ (reset)
-
-  persistent color_rotation;
-  persistent num_colors;
-  persistent color_index;
-
-  if (nargin < 2)
-    if (nargin == 1)
-      if (reset || isempty (color_rotation))
-        color_rotation = get (gca (), "colororder");
-        num_colors = rows (color_rotation);
-        color_index = 1;
-      endif
-    elseif (! isempty (color_rotation))
-      rgb = color_rotation(color_index,:);
-      if (++color_index > num_colors)
-        color_index = 1;
-        __next_line_style__ ("incr");
-      endif
-    else
-      error ("__next_line_color__: color_rotation not initialized");
-    endif
-  else
-    print_usage ();
-  endif
-
-endfunction
--- a/scripts/plot/__next_line_style__.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-## Copyright (C) 2010-2011 David Bateman
-##
-## 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} {@var{style} =} __next_line_style__ (@var{reset})
-## Undocumented internal function.
-## @end deftypefn
-
-## Return the next line style in the rotation.
-
-
-function [linestyle, marker] = __next_line_style__ (reset)
-
-  persistent style_rotation;
-  persistent num_styles;
-  persistent style_index;
-
-  if (nargin < 2)
-    if (nargin == 1)
-      if (ischar (reset) && strncmp (reset, "incr", 4))
-        if (isempty (style_rotation))
-          error ("__next_line_style__: style_rotation not initialized");
-        elseif (++style_index > num_styles)
-          style_index = 1;
-        endif
-      elseif (reset || isempty (style_rotation))
-        style_rotation = strsplit (get (gca (), "linestyleorder"), "|");
-        num_styles = length (style_rotation);
-        style_index = 1;
-      endif
-    elseif (! isempty (style_rotation))
-      options = __pltopt__ ("__next_line_style__",
-                            style_rotation (style_index));
-      linestyle = options.linestyle;
-      marker = options.marker;
-    else
-      error ("__next_line_style__: style_rotation not initialized");
-    endif
-  else
-    print_usage ();
-  endif
-
-endfunction
--- a/scripts/plot/__plt_get_axis_arg__.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/__plt_get_axis_arg__.m	Tue Sep 20 15:38:24 2011 -0400
@@ -76,3 +76,7 @@
   narg = length (varargin);
 
 endfunction
+
+
+## No test needed for internal helper function.
+%!assert (1)
--- a/scripts/plot/__print_parse_opts__.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,609 +0,0 @@
-## Copyright (C) 2008-2011 David Bateman
-##
-## 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} {[@var{x}, @var{y}, @var{buttons}] =} ginput (@var{n})
-## Return which mouse buttons were pressed and keys were hit on the current
-## figure.  If @var{n} is defined, then wait for @var{n} mouse clicks
-## before returning.  If @var{n} is not defined, then @code{ginput} will
-## loop until the return key is pressed.
-## @end deftypefn
-
-function arg_st = __print_parse_opts__ (varargin)
-
-  persistent warn_on_missing_binary = true
-
-  arg_st.append_to_file = false;
-  arg_st.canvas_size = [];
-  arg_st.debug = false;
-  arg_st.debug_file = "octave-print-commands.log";
-  arg_st.devopt = "";
-  arg_st.epstool_binary = __quote_path__ (__find_binary__ ("epstool"));
-  arg_st.figure = get (0, "currentfigure");
-  arg_st.fig2dev_binary = __quote_path__ (__find_binary__ ("fig2dev"));
-  arg_st.fontsize = "";
-  arg_st.font = "";
-  arg_st.force_solid = 0; # 0=default, -1=dashed, +1=solid
-  arg_st.formatted_for_printing = false;
-  arg_st.ghostscript.binary = __quote_path__ (__ghostscript_binary__ ());
-  arg_st.ghostscript.debug = false;
-  arg_st.ghostscript.device = "";
-  arg_st.ghostscript.epscrop = true;
-  arg_st.ghostscript.level = [];
-  arg_st.ghostscript.output = "";
-  arg_st.ghostscript.papersize = "";
-  arg_st.ghostscript.pageoffset = [];
-  arg_st.ghostscript.resolution = 150;
-  arg_st.ghostscript.antialiasing = false;
-  arg_st.loose = false;
-  arg_st.lpr_binary = __quote_path__ (__find_binary__ ("lpr"));
-  arg_st.name = "";
-  arg_st.orientation = "";
-  arg_st.pstoedit_binary = __quote_path__ (__find_binary__ ("pstoedit"));
-  arg_st.preview = "";
-  arg_st.printer = "";
-  arg_st.send_to_printer = false;
-  arg_st.special_flag = "textnormal";
-  arg_st.tight_flag = false;
-  arg_st.use_color = 0; # 0=default, -1=mono, +1=color
-
-  if (isunix ())
-    arg_st.lpr_options = "-l";
-  elseif (ispc ())
-    arg_st.lpr_options = "-o l";
-  else
-    arg_st.lpr_options = "";
-  endif
-  arg_st.unlink = {};
-
-  if (nargin > 0 && isfigure (varargin{1}))
-    arg_st.figure = varargin{1};
-    varargin(1) = [];
-  endif
-
-  for i = 1:numel(varargin)
-    arg = strtrim (varargin{i});
-    if (ischar (arg))
-      if (strcmp (arg, "-color"))
-        arg_st.use_color = 1;
-      elseif (strcmp (arg, "-append"))
-        arg_st.append_to_file = true;
-      elseif (strcmp (arg, "-mono"))
-        arg_st.use_color = -1;
-      elseif (strcmp (arg, "-solid"))
-        arg_st.force_solid = 1;
-      elseif (strcmp (arg, "-dashed"))
-        arg_st.force_solid = -1;
-      elseif (strncmp (arg, "-portrait", numel (arg)))
-        arg_st.orientation = "portrait";
-      elseif (strncmp (arg, "-landscape", numel (arg)))
-        arg_st.orientation = "landscape";
-      elseif (strcmp (arg, "-loose"))
-        arg_st.loose = true;
-        arg_st.tight_flag = false;
-      elseif (strcmp (arg, "-tight"))
-        arg_st.loose = false;
-        arg_st.tight_flag = true;
-      elseif (strcmp (arg, "-textspecial"))
-        arg_st.special_flag = "textspecial";
-      elseif (any (strcmp (arg, {"-interchange", "-metafile", "-pict", "-tiff"})))
-        arg_st.preview = arg(2:end);
-      elseif (strncmp (arg, "-debug", 6))
-        arg_st.debug = true;
-        arg_st.ghostscript.debug = true;
-        if (length (arg) > 7)
-          arg_st.debug_file = arg(8:end);
-        endif
-      elseif (length (arg) > 2 && arg(1:2) == "-d")
-        arg_st.devopt = tolower (arg(3:end));
-      elseif (length (arg) > 2 && arg(1:2) == "-P")
-        arg_st.printer = arg;
-      elseif (strncmp (arg, "-EPSTOOL:", 9))
-        arg_st.epstool_binary = arg{10:end};
-      elseif (strncmp (arg, "-FIG2DEV:", 9))
-        arg_st.fig2dev_binary = arg{10:end};
-      elseif (strncmp (arg, "-PSTOEDIT:", 9))
-        arg_st.pstoedit_binary = arg{10:end};
-      elseif ((length (arg) > 2) && arg(1:2) == "-G")
-        arg_st.ghostscript.binary = file_in_path (getenv ("PATH"), arg(3:end));
-        if (isempty (arg_st.ghostscript.binary))
-          error ("print: Ghostscript binary ""%s"" could not be located",
-                 arg(3:end));
-        else
-          arg_st.ghostscript_binary = __quote_path__ (arg_st.ghostscript_binary);
-        endif
-      elseif (length (arg) > 2 && arg(1:2) == "-F")
-        idx = rindex (arg, ":");
-        if (idx)
-          arg_st.font = arg(3:idx-1);
-          arg_st.fontsize = str2num (arg(idx+1:end));
-        else
-          arg_st.font = arg(3:end);
-        endif
-      elseif (length (arg) > 2 && arg(1:2) == "-S")
-        arg_st.canvas_size = str2num (arg(3:end));
-      elseif (length (arg) > 2 && arg(1:2) == "-r")
-        arg_st.ghostscript.resolution = str2double (arg(3:end));
-      elseif (length (arg) > 2 && arg(1:2) == "-f")
-        arg_st.figure = str2num (arg(3:end));
-      elseif (length (arg) >= 1 && arg(1) == "-")
-        error ("print: unknown option `%s'", arg);
-      elseif (length (arg) > 0)
-        arg_st.name = arg;
-      endif
-    elseif (isfigure (arg))
-      arg_st.figure = arg;
-    else
-      error ("print: expecting inputs to be character string options or a figure handle");
-    endif
-  endfor
-
-  if (arg_st.ghostscript.resolution == 0)
-    ## Do as Matlab does.
-    arg_st.ghostscript.resolution = num2str (get (0, "screenpixelsperinch"));
-  endif
-
-  if (isempty (arg_st.orientation))
-    if (isfigure (arg_st.figure))
-      arg_st.orientation = get (arg_st.figure, "paperorientation");
-    else
-      ## Allows tests to be run without error.
-      arg_st.orientation = "portrait";
-    endif
-  endif
-
-  if (isempty (arg_st.ghostscript.binary))
-    arg_st.ghostscript.binary = __ghostscript_binary__ ();
-  endif
-
-  dot = rindex (arg_st.name, ".");
-  if (isempty (arg_st.devopt))
-    if (dot == 0)
-      arg_st.devopt = "psc";
-    else
-      arg_st.devopt = tolower (arg_st.name(dot+1:end));
-    endif
-  endif
-
-  if (arg_st.use_color == 0)
-    if (any (strcmp ({"ps", "ps2", "eps", "eps2"}, arg_st.devopt)))
-      arg_st.use_color = -1;
-    else
-      arg_st.use_color = 1;
-    endif
-  endif
-
-  if (strcmp (arg_st.devopt, "tex"))
-    arg_st.devopt = "epslatex";
-  elseif (strcmp (arg_st.devopt, "ill"))
-    arg_st.devopt = "aifm";
-  elseif (strcmp (arg_st.devopt, "cdr"))
-    arg_st.devopt = "corel";
-  elseif (strcmp (arg_st.devopt, "meta"))
-    arg_st.devopt = "emf";
-  elseif (strcmp (arg_st.devopt, "jpg"))
-    arg_st.devopt = "jpeg";
-  endif
-
-  dev_list = {"aifm", "corel", "fig", "png", "jpeg", ...
-              "gif", "pbm", "pbmraw", "dxf", "mf", ...
-              "svg", "hpgl", "ps", "ps2", "psc", ...
-              "psc2", "eps", "eps2", "epsc", "epsc2", ...
-              "emf", "pdf", "pslatex", "epslatex", "epslatexstandalone", ...
-              "pslatexstandalone", "pdflatexstandalone", ...
-              "pstex", "tiff", "tiffn" "tikz", "pcxmono", ...
-              "pcx24b", "pcx256", "pcx16", "pgm", "pgmraw", ...
-              "ppm", "ppmraw", "pdflatex", "texdraw", ...
-              "pdfcairo", "pngcairo", "pstricks", ...
-              "epswrite", "pswrite", "ps2write", "pdfwrite"};
-
-  suffixes = {"ai", "cdr", "fig", "png", "jpg", ...
-              "gif", "pbm", "pbm", "dxf", "mf", ...
-              "svg", "hpgl", "ps", "ps", "ps", ...
-              "ps", "eps", "eps", "eps", "eps", ...
-              "emf", "pdf", "tex", "tex", "tex", ...
-              "tex", "tex", ...
-              "ps", "tiff", "tiff", "tikz", "pcx", ...
-              "pcx", "pcx", "pcx", "pgm", "pgm", ...
-              "ppm", "ppm", "tex", "tex", ...
-              "pdf", "png", "tex", ...
-              "eps", "ps", "ps", "pdf"};
-
-  if (isfigure (arg_st.figure))
-    __graphics_toolkit__ = get (arg_st.figure, "__graphics_toolkit__");
-  else
-    ## Allow tests when no figures are present.
-    __graphics_toolkit__ = get (0, "defaultfigure__graphics_toolkit__");
-  endif
-
-  if (strcmp (__graphics_toolkit__, "gnuplot")
-      && __gnuplot_has_feature__ ("epslatex_implies_eps_filesuffix"))
-    suffixes(strncmp (dev_list, "epslatex", 8)) = {"eps"};
-  endif
-
-  match = strcmpi (dev_list, arg_st.devopt);
-  if (any (match))
-    default_suffix = suffixes {match};
-  else
-    default_suffix = arg_st.devopt;
-  endif
-
-  if (dot == 0 && ! isempty (arg_st.name))
-    arg_st.name = strcat (arg_st.name, ".", default_suffix);
-  endif
-
-  if (arg_st.append_to_file)
-    if (isempty (arg_st.name))
-      arg_st.append_to_file = false;
-    elseif (any (strcmpi (arg_st.devopt, {"eps", "eps2", "epsc", "epsc2", ...
-                                          "ps", "ps2", "psc", "psc2", "pdf"})))
-      have_ghostscript = ! isempty (__ghostscript_binary__ ());
-      if (have_ghostscript)
-        file_exists = ((numel (dir (arg_st.name)) == 1)
-                       && (! isdir (arg_st.name)));
-        if (! file_exists)
-          arg_st.append_to_file = false;
-        endif
-      else
-        arg_st.append_to_file = false;
-        warning ("print.m: appended output requires ghostscript to be installed");
-      endif
-    else
-      warning ("print.m: appended output is not supported for device '%s'",
-               arg_st.devopt);
-      arg_st.append_to_file = false;
-    endif
-  endif
-
-  if (! isempty (arg_st.printer) || isempty (arg_st.name))
-    arg_st.send_to_printer = true;
-  endif
-
-  if (any (strcmp (arg_st.devopt, {"ps", "ps2", "psc", "psc2", "pdf"})))
-    arg_st.formatted_for_printing = true;
-  endif
-
-  aliases = gs_aliases ();
-  if (any (strcmp (arg_st.devopt, fieldnames (aliases))))
-    arg_st.devopt = aliases.(arg_st.devopt);
-  endif
-
-  ## FIXME - eps2 & epsc2 needs to be handled
-  if (strcmp (arg_st.devopt, "pswrite"))
-    arg_st.ghostscript.level = 1;
-  elseif (strcmp (arg_st.devopt, "ps2write"))
-    arg_st.ghostscript.level = 2;
-  endif
-
-  if ((any (strcmp (arg_st.devopt, gs_device_list))
-       && ! arg_st.formatted_for_printing)
-      || any (strcmp (arg_st.devopt, {"pswrite", "ps2write", "pdfwrite"})))
-    ## Use ghostscript for graphic formats
-    arg_st.ghostscript.device = arg_st.devopt;
-    arg_st.ghostscript.output = arg_st.name;
-    arg_st.ghostscript.antialiasing = true;
-    if (arg_st.formatted_for_printing)
-      arg_st.ghostscript.epscrop = ! arg_st.loose;
-    else
-      ## pstoedit throws errors if the EPS file isn't cropped
-      arg_st.ghostscript.epscrop = true;
-    endif
-  elseif (all (! strcmp (arg_st.devopt, dev_list)))
-    ## Assume we are formating output for a printer
-    arg_st.formatted_for_printing = true;
-    arg_st.ghostscript.device = arg_st.devopt;
-    arg_st.ghostscript.output = arg_st.name;
-    arg_st.ghostscript.antialiasing = false;
-    arg_st.ghostscript.epscrop = ! arg_st.loose;
-  endif
-
-  if (isempty (arg_st.canvas_size))
-    if (isfigure (arg_st.figure))
-      [arg_st.ghostscript.papersize, paperposition] = ...
-                           gs_papersize (arg_st.figure, arg_st.orientation);
-    else
-      ## allows tests to be run
-      arg_st.ghostscript.papersize = "letter";
-      paperposition = [0.25, 2.50, 8.00, 6.00] * 72;
-    endif
-    arg_st.canvas_size = paperposition(3:4);
-    if (strcmp (__graphics_toolkit__, "gnuplot") && ! arg_st.ghostscript.epscrop)
-      arg_st.ghostscript.pageoffset = paperposition(1:2) - 50;
-    else
-      arg_st.ghostscript.pageoffset = paperposition(1:2);
-    endif
-  else
-    ## Convert canvas size to points from pixles.
-    arg_st.canvas_size = arg_st.canvas_size * 72 / arg_st.ghostscript.resolution;
-    arg_st.ghostscript.papersize = arg_st.canvas_size;
-    arg_st.ghostscript.epscrop = true;
-    arg_st.ghostscript.pageoffset = [0, 0];
-  endif
-
-  if (arg_st.formatted_for_printing)
-    arg_st.ghostscript.resolution = [];
-  else
-    arg_st.ghostscript.papersize = "";
-    arg_st.ghostscript.pageoffset = [0, 0];
-  endif
-
-  if (warn_on_missing_binary)
-    if (isempty (arg_st.ghostscript.binary))
-      warning ("print:missing_gs", "print.m: Ghostscript binary is not available.\nOnly eps output is available.");
-    else
-      if (isempty (arg_st.epstool_binary))
-        warning ("print:missing_epstool", "print.m: epstool binary is not available.\nSome output formats are not available.");
-      endif
-      if (isempty (arg_st.fig2dev_binary))
-        warning ("print:missing_fig2dev", "print.m: fig2dev binary is not available.\nSome output formats are not available.");
-      endif
-      if (isempty (arg_st.pstoedit_binary))
-        warning ("print:missing_pstoedit", "print.m: pstoedit binary is not available.\nSome output formats are not available.");
-      endif
-    endif
-    warn_on_missing_binary = false;
-  endif
-
-endfunction
-
-%!test
-%! opts = __print_parse_opts__ ();
-%! assert (opts.devopt, "pswrite");
-%! assert (opts.use_color, 1);
-%! assert (opts.send_to_printer, true);
-%! assert (opts.canvas_size, [576, 432]);
-%! assert (opts.ghostscript.device, "pswrite")
-
-%!test
-%! opts = __print_parse_opts__ ("test.pdf", "-S640,480");
-%! assert (opts.canvas_size, [307.2, 230.4], 0.1);
-
-%!test
-%! opts = __print_parse_opts__ ("-dpsc", "-append", "-loose");
-%! assert (opts.devopt, "pswrite");
-%! assert (opts.send_to_printer, true);
-%! assert (opts.use_color, 1);
-%! assert (opts.append_to_file, false);
-%! assert (opts.ghostscript.device, "pswrite")
-%! assert (opts.ghostscript.epscrop, false);
-
-%!test
-%! opts = __print_parse_opts__ ("-deps", "-tight");
-%! assert (opts.tight_flag, true);
-%! assert (opts.send_to_printer, true);
-%! assert (opts.use_color, -1);
-%! assert (opts.ghostscript.device, "")
-
-%!test
-%! opts = __print_parse_opts__ ("-djpg", "foobar", "-mono", "-loose");
-%! assert (opts.devopt, "jpeg")
-%! assert (opts.name, "foobar.jpg")
-%! assert (opts.ghostscript.device, "jpeg")
-%! assert (opts.ghostscript.epscrop, true);
-%! assert (opts.ghostscript.papersize, "");
-%! assert (opts.ghostscript.pageoffset, [0, 0]);
-%! assert (opts.send_to_printer, false);
-%! assert (opts.printer, "");
-%! assert (opts.use_color, -1);
-
-%!test
-%! opts = __print_parse_opts__ ("-ddeskjet", "foobar", "-mono", "-Pmyprinter");
-%! assert (opts.ghostscript.output, "foobar.deskjet")
-%! assert (opts.ghostscript.device, "deskjet")
-%! assert (opts.devopt, "deskjet")
-%! assert (opts.send_to_printer, true);
-%! assert (opts.printer, "-Pmyprinter");
-%! assert (opts.use_color, -1);
-
-%!test
-%! opts = __print_parse_opts__ ("-f5", "-dljet3");
-%! assert (opts.ghostscript.device, "ljet3")
-%! assert (strfind (opts.ghostscript.output, ".ljet3"))
-%! assert (opts.devopt, "ljet3")
-%! assert (opts.send_to_printer, true);
-%! assert (opts.figure, 5)
-
-function cmd = __quote_path__ (cmd)
-  if (any (cmd == " ") && ! (cmd(1) == """" && cmd(end) == """"))
-    cmd = strcat ("""", strrep (cmd, """", """"""), """");
-  endif
-endfunction
-
-function gs = __ghostscript_binary__ ()
-
-  persistent ghostscript_binary = ""
-  persistent warn_on_no_ghostscript = true
-  persistent warn_on_bad_gsc = true
-
-  if (isempty (ghostscript_binary))
-    GSC = getenv ("GSC");
-    if (exist (GSC, "file")
-        || (! isempty (GSC) && file_in_path (getenv ("PATH"), GSC)))
-      gs_binaries = {GSC};
-    elseif (! isempty (GSC) && warn_on_bad_gsc)
-      warning ("print:badgscenv",
-               "print.m: GSC environment variable not set properly");
-      warn_on_bad_gsc = false;
-      gs_binaries = {};
-    else
-      gs_binaries = {};
-    endif
-    if (isunix ())
-      ## Unix - Includes Mac OSX and Cygwin.
-      gs_binaries = horzcat (gs_binaries, {"gs", "gs.exe"});
-    else
-      ## pc - Includes Win32 and mingw.
-      gs_binaries = horzcat (gs_binaries, {"gs.exe", "gswin32c.exe"});
-    endif
-    n = 0;
-    while (n < numel (gs_binaries) && isempty (ghostscript_binary))
-      n = n + 1;
-      ghostscript_binary = file_in_path (getenv ("PATH"), gs_binaries{n});
-    endwhile
-    if (warn_on_no_ghostscript && isempty (ghostscript_binary))
-      warning ("print:noghostscript",
-               "print.m: ghostscript not found in PATH");
-      warn_on_no_ghostscript = false;
-    endif
-  endif
-
-  gs = ghostscript_binary;
-
-endfunction
-
-function bin = __find_binary__ (binary)
-
-  persistent data = struct ()
-
-  if (! isfield (data, binary))
-    ## Reinitialize when `user_binaries' is present.
-    data.(binary).bin = "";
-    data.(binary).warn_on_absence = false;
-  endif
-
-  if (isempty (data.(binary).bin))
-    if (isunix ())
-      ## Unix - Includes Mac OSX and Cygwin.
-      binaries = strcat (binary, {"", ".exe"});
-    else
-      ## pc - Includes Win32 and mingw.
-      binaries = strcat (binary, {".exe"});
-    endif
-    n = 0;
-    while (n < numel (binaries) && isempty (data.(binary).bin))
-      n = n + 1;
-      data.(binary).bin = file_in_path (getenv ("PATH"), binaries{n});
-    endwhile
-    if (isempty (data.(binary).bin) && data.(binary).warn_on_absence)
-      warning (sprintf ("print:no%s", binary),
-               "print.m: '%s' not found in PATH", binary);
-      data.(binary).warn_on_absence = false;
-    endif
-  endif
-
-  bin = data.(binary).bin;
-
-endfunction
-
-function [papersize, paperposition] = gs_papersize (hfig, paperorientation)
-  persistent papertypes papersizes
-
-  if (isempty (papertypes))
-    papertypes = {"usletter", "uslegal",     "a0",     "a1", ...
-                        "a2",      "a3",     "a4",     "a5", ...
-                        "b0",      "b1",     "b2",     "b3", ...
-                        "b4",      "b5", "arch-a", "arch-b", ...
-                    "arch-c",  "arch-d", "arch-e",      "a", ...
-                         "b",       "c",      "d",      "e", ...
-                   "tabloid"};
-    papersizes = [ 8.5, 11.0;  8.5, 14.0; 33.1, 46.8; 23.4, 33.1;
-                  16.5, 23.4; 11.7, 16.5;  8.3, 11.7;  5.8,  8.3;
-                  39.4, 55.7; 27.8, 39.4; 19.7, 27.8; 13.9, 19.7;
-                   9.8, 13.9;  6.9,  9.8;  9.0, 12.0; 12.0, 18.0;
-                  18.0, 24.0; 24.0, 36.0; 36.0, 48.0;  8.5, 11.0;
-                  11.0, 17.0; 18.0, 24.0; 24.0, 36.0; 36.0, 48.0;
-                  11.0, 17.0] * 72;
-  endif
-
-  papertype = get (hfig, "papertype");
-  paperunits = get (hfig, "paperunits");
-  paperposition = get (hfig, "paperposition");
-  if (strcmp (papertype, "<custom>"))
-    papersize = get (hfig, "papersize");
-    papersize = convert2points (papersize , paperunits);
-  else
-    papersize = papersizes (strcmp (papertypes, papertype), :);
-  endif
-
-  if (strcmp (paperunits, "normalized"))
-    paperposition = paperposition .* papersize([1,2,1,2]);
-  else
-    paperposition = convert2points (paperposition, paperunits);
-  endif
-
-  ## FIXME - This will be obsoleted by listeners for paper properties.
-  ##         Papersize is tall when portrait,and wide when landscape.
-  if ((papersize(1) > papersize(2) && strcmpi (paperorientation, "portrait"))
-      || (papersize(1) < papersize(2) && strcmpi (paperorientation, "landscape")))
-    papersize = papersize ([2,1]);
-    paperposition = paperposition([2,1,4,3]);
-  endif
-
-  if ((! strcmp (papertype, "<custom>")) && (strcmp (paperorientation, "portrait")))
-    ## For portrait use the ghostscript name
-    papersize = papertype;
-    papersize(papersize=="-") = "";
-    papersize = strrep (papersize, "us", "");
-    switch (papersize)
-    case "a"
-      papersize = "letter";
-    case {"b", "tabloid"}
-      papersize = "11x17";
-    case {"c", "d", "e"}
-      papersize = strcat ("arch", papersize);
-    endswitch
-    if (strncmp (papersize, "arch", 4))
-      papersize(end) = upper (papersize(end));
-    endif
-  endif
-
-endfunction
-
-function value = convert2points (value, units)
-    switch (units)
-    case "inches"
-      value = value * 72;
-    case "centimeters"
-      value = value * 72 / 2.54;
-    case "normalized"
-      error ("print:customnormalized",
-             "print.m: papersize=='<custom>' and paperunits='normalized' may not be combined");
-    endswitch
-endfunction
-
-function device_list = gs_device_list ();
-  ## Graphics formats/languages, not priners.
-  device_list = {"bmp16"; "bmp16m"; "bmp256"; "bmp32b"; "bmpgray"; ...
-                 "epswrite"; "jpeg"; "jpegcymk"; "jpeggray"; "pbm"; ...
-                 "pbmraw"; "pcx16"; "pcx24b"; "pcx256"; "pcx2up"; ...
-                 "pcxcmyk"; "pcxgray"; "pcxmono"; "pdfwrite"; "pgm"; ...
-                 "pgmraw"; "pgnm"; "pgnmraw"; "png16"; "png16m"; ...
-                 "png256"; "png48"; "pngalpha"; "pnggray"; "pngmono"; ...
-                 "pnm"; "pnmraw"; "ppm"; "ppmraw"; "ps2write"; ...
-                 "pswrite"; "tiff12nc"; "tiff24nc"; "tiff32nc"; ...
-                 "tiffcrle"; "tiffg3"; "tiffg32d"; "tiffg4"; ...
-                 "tiffgray"; "tifflzw"; "tiffpack"; "tiffsep"};
-endfunction
-
-function aliases = gs_aliases ();
-  ## Aliases for other devices: "bmp", "png", "tiff", "tiffn", "pdf",
-  ##                            "ps", "ps2", "psc", "psc2"
-  ##
-  ## eps, epsc, eps2, epsc2 are not included here because those are
-  ## are generated by the graphics toolkit.
-  aliases.bmp = "bmp32b";
-  aliases.pdf = "pdfwrite";
-  aliases.png = "png16m";
-  aliases.ps = "pswrite";
-  aliases.ps2 = "ps2write";
-  aliases.psc = "pswrite";
-  aliases.psc2 = "ps2write";
-  aliases.tiff = "tiff24nc";
-  aliases.tiffn = "tiff24nc";
-endfunction
-
--- a/scripts/plot/allchild.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/allchild.m	Tue Sep 20 15:38:24 2011 -0400
@@ -48,3 +48,12 @@
   end_unwind_protect
 
 endfunction
+
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   l = line;
+%!   assert(get(allchild(hf),'type'),{'axes'; 'uimenu'; 'uimenu'; 'uimenu'})
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
--- a/scripts/plot/ancestor.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/ancestor.m	Tue Sep 20 15:38:24 2011 -0400
@@ -74,3 +74,13 @@
   endif
 
 endfunction
+
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   l = line;
+%!   assert (ancestor (l, "axes"), gca);
+%!   assert (ancestor (l, "figure"), hf);
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
--- a/scripts/plot/axis.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/axis.m	Tue Sep 20 15:38:24 2011 -0400
@@ -319,20 +319,14 @@
   else
     data = get (kids, strcat (ax, "data"));
     scale = get (ca, strcat (ax, "scale"));
-    if (strcmp (scale, "log"))
-      if (iscell (data))
-        for i = 1:length(data)
-          data{i}(data{i}<=0) = NaN;
-        endfor
-      else
-        data(data<=0) = NaN;
-      endif
+    if (strcmp (scale, "log") && any (data > 0))
+      data(data<=0) = NaN;
     endif
     if (iscell (data))
-      data = data (find (! cellfun (@isempty, data)));
+      data = data (find (! cellfun ("isempty", data)));
       if (! isempty (data))
-        lims_min = min (cellfun (@min, cellfun (@min, data, 'uniformoutput', false)(:)));
-        lims_max = max (cellfun (@max, cellfun (@max, data, 'uniformoutput', false)(:)));
+        lims_min = min (cellfun ("min", cellfun ("min", data, 'uniformoutput', false)(:)));
+        lims_max = max (cellfun ("max", cellfun ("max", data, 'uniformoutput', false)(:)));
         lims = [lims_min, lims_max];
       else
         lims = [0, 1];
--- a/scripts/plot/cla.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/cla.m	Tue Sep 20 15:38:24 2011 -0400
@@ -90,9 +90,8 @@
 endfunction
 
 %!test
-%! hf = figure (1, "visible", "off");
+%! hf = figure ("visible", "off");
 %! unwind_protect
-%!   clf
 %!   plot (1:10)
 %!   cla ()
 %!   kids = get (gca, "children");
--- a/scripts/plot/clf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/clf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -75,3 +75,21 @@
   delete (hc);
 
 endfunction
+
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   l = line;
+%!   assert (!isempty (get (gcf, "children")));
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   clf;
+%!   assert (isempty (get (gcf, "children")));
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
--- a/scripts/plot/close.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/close.m	Tue Sep 20 15:38:24 2011 -0400
@@ -79,3 +79,15 @@
   endwhile
 
 endfunction
+
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   close (hf);
+%!   objs = findobj ("type", "figure");
+%!   assert (isempty (intersect (objs, hf)));
+%! unwind_protect_cleanup
+%!   if (isfigure (hf))
+%!     close (hf);
+%!   endif
+%! end_unwind_protect
--- a/scripts/plot/findall.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/findall.m	Tue Sep 20 15:38:24 2011 -0400
@@ -42,3 +42,13 @@
   end_unwind_protect
 
 endfunction
+
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   h = findall (hf);
+%!   all_handles = {"uimenu"; "uimenu"; "uimenu"; "uimenu"; "uimenu"; "uimenu"; "uimenu"; "uimenu"; "uimenu"; "uimenu"; "uimenu"; "uimenu"; "uimenu"; "figure"};
+%!   assert (get (h, 'type'), all_handles)
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
--- a/scripts/plot/findobj.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/findobj.m	Tue Sep 20 15:38:24 2011 -0400
@@ -242,3 +242,16 @@
   h = h (keepers != 0);
   h = reshape (h, [numel(h), 1]);
 endfunction
+
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   l = line;
+%!   obj = findobj (hf, "type", "line");
+%!   assert (l, obj);
+%!   assert (gca, findobj (hf, "type", "axes"));
+%!   assert (hf, findobj (hf, "type", "figure"));
+%!   assert (isempty (findobj (hf, "type", "xyzxyz")));
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
--- a/scripts/plot/gca.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/gca.m	Tue Sep 20 15:38:24 2011 -0400
@@ -49,3 +49,12 @@
   endif
 
 endfunction
+
+%!test
+%! hf = figure ("visible", "off");
+%! ax = axes;
+%! unwind_protect
+%!   assert (gca, ax);
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
--- a/scripts/plot/gcbf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/gcbf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -31,3 +31,6 @@
   [dummy, fig] = gcbo ();
 
 endfunction
+
+%!test
+%! assert (isempty (gcbf ));
--- a/scripts/plot/gcbo.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/gcbo.m	Tue Sep 20 15:38:24 2011 -0400
@@ -41,3 +41,6 @@
   endif
 
 endfunction
+
+%!test
+%! assert (isempty (gcbo ));
--- a/scripts/plot/gcf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/gcf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -53,3 +53,11 @@
   endif
 
 endfunction
+
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   assert (gcf, hf);
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
--- a/scripts/plot/ginput.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/ginput.m	Tue Sep 20 15:38:24 2011 -0400
@@ -42,3 +42,7 @@
   endif
 
 endfunction
+
+## Remove from test statistics.  No real tests possible.
+%!test
+%! assert (1);
--- a/scripts/plot/gtext.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/gtext.m	Tue Sep 20 15:38:24 2011 -0400
@@ -51,3 +51,6 @@
 
 endfunction
 
+## Remove from test statistics.  No real tests possible.
+%!test
+%! assert (1);
--- a/scripts/plot/hggroup.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/hggroup.m	Tue Sep 20 15:38:24 2011 -0400
@@ -41,3 +41,13 @@
   endif
 
 endfunction
+
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   h = hggroup;
+%!   assert (findobj (hf, "type", "hggroup"), h);
+%!   assert (get (h, "type"), "hggroup");
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
--- a/scripts/plot/isfigure.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/isfigure.m	Tue Sep 20 15:38:24 2011 -0400
@@ -34,3 +34,12 @@
   endif
 
 endfunction
+
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   assert (isfigure (hf));
+%!   assert (!isfigure (-hf));
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
--- a/scripts/plot/ishghandle.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/ishghandle.m	Tue Sep 20 15:38:24 2011 -0400
@@ -26,3 +26,34 @@
   ## no simulink equivalent.
   retval = ishandle (h);
 endfunction
+
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   assert (ishghandle (hf));
+%!   assert (!ishghandle (-hf));
+%!   l = line;
+%!   ax = gca();
+%!   assert (ishghandle (ax));
+%!   assert (!ishghandle (-ax));
+%!   assert (ishghandle (l));
+%!   assert (!ishghandle (-l));
+%!   p = patch;
+%!   assert (ishghandle (p));
+%!   assert (!ishghandle (-p));
+%!   s = surface;
+%!   assert (ishghandle (s));
+%!   assert (!ishghandle (-s));
+%!   t = text;
+%!   assert (ishghandle (t));
+%!   assert (!ishghandle (-t));
+%!   i = image;
+%!   assert (ishghandle (i));
+%!   assert (!ishghandle (-i));
+%!   hg = hggroup;
+%!   assert (ishghandle (hg));
+%!   assert (!ishghandle (-hg));
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
--- a/scripts/plot/isonormals.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/isonormals.m	Tue Sep 20 15:38:24 2011 -0400
@@ -46,47 +46,49 @@
 ##
 ## For example:
 ##
-## @example
+## @c Set example in small font to prevent overfull line
+## @smallexample
 ## function [] = isofinish (p)
-##   set (gca, "PlotBoxAspectRatioMode","manual","PlotBoxAspectRatio",[1 1 1]);
-##   set (p, "VertexNormals", -get(p,"VertexNormals")); ## Revert normals
+##   set (gca, "PlotBoxAspectRatioMode", "manual", ...
+##             "PlotBoxAspectRatio",[1 1 1]);
+##   set (p, "VertexNormals", -get(p,"VertexNormals")); # Revert normals
 ##   set (p, "FaceColor", "interp");
 ##   ## set (p, "FaceLighting", "phong");
-##   ## light ("Position", [1 1 5]); ## Available with JHandles
+##   ## light ("Position", [1 1 5]); # Available with JHandles
 ## endfunction
 ##
-## N = 15;    ## Increase number of vertices in each direction
-## iso = .4;  ## Change isovalue to .1 to display a sphere
+## N = 15;    # Increase number of vertices in each direction
+## iso = .4;  # Change isovalue to .1 to display a sphere
 ## lin = linspace (0, 2, N);
 ## [x, y, z] = meshgrid (lin, lin, lin);
 ## c = abs ((x-.5).^2 + (y-.5).^2 + (z-.5).^2);
-## figure (); ## Open another figure window
+## figure (); # Open another figure window
 ##
 ## subplot (2, 2, 1); view (-38, 20);
 ## [f, v, cdat] = isosurface (x, y, z, c, iso, y);
 ## p = patch ("Faces", f, "Vertices", v, "FaceVertexCData", cdat, \
-##         "FaceColor", "interp", "EdgeColor", "none");
+##            "FaceColor", "interp", "EdgeColor", "none");
 ## isofinish (p); ## Call user function isofinish
 ##
 ## subplot (2, 2, 2); view (-38, 20);
 ## p = patch ("Faces", f, "Vertices", v, "FaceVertexCData", cdat, \
-##         "FaceColor", "interp", "EdgeColor", "none");
-## isonormals (x, y, z, c, p); ## Directly modify patch
+##            "FaceColor", "interp", "EdgeColor", "none");
+## isonormals (x, y, z, c, p); # Directly modify patch
 ## isofinish (p);
 ##
 ## subplot (2, 2, 3); view (-38, 20);
 ## p = patch ("Faces", f, "Vertices", v, "FaceVertexCData", cdat, \
-##         "FaceColor", "interp", "EdgeColor", "none");
-## n = isonormals (x, y, z, c, v); ## Compute normals of isosurface
-## set (p, "VertexNormals", n);    ## Manually set vertex normals
+##            "FaceColor", "interp", "EdgeColor", "none");
+## n = isonormals (x, y, z, c, v); # Compute normals of isosurface
+## set (p, "VertexNormals", n);    # Manually set vertex normals
 ## isofinish (p);
 ##
 ## subplot (2, 2, 4); view (-38, 20);
 ## p = patch ("Faces", f, "Vertices", v, "FaceVertexCData", cdat, \
-##         "FaceColor", "interp", "EdgeColor", "none");
-## isonormals (x, y, z, c, v, "negate"); ## Use reverse directly
+##            "FaceColor", "interp", "EdgeColor", "none");
+## isonormals (x, y, z, c, v, "negate"); # Use reverse directly
 ## isofinish (p);
-## @end example
+## @end smallexample
 ##
 ## @seealso{isosurface, isocolors}
 ## @end deftypefn
--- a/scripts/plot/isosurface.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/isosurface.m	Tue Sep 20 15:38:24 2011 -0400
@@ -71,24 +71,27 @@
 ## Another example for an isosurface geometry with different additional
 ## coloring
 ##
-## @example
-## N = 15;    ## Increase number of vertices in each direction
-## iso = .4;  ## Change isovalue to .1 to display a sphere
+## @c Set example in small font to prevent overfull line
+## @smallexample
+## N = 15;    # Increase number of vertices in each direction
+## iso = .4;  # Change isovalue to .1 to display a sphere
 ## lin = linspace (0, 2, N);
 ## [x, y, z] = meshgrid (lin, lin, lin);
 ## c = abs ((x-.5).^2 + (y-.5).^2 + (z-.5).^2);
-## figure (); ## Open another figure window
+## figure (); # Open another figure window
 ##
 ## subplot (2, 2, 1); view (-38, 20);
 ## [f, v] = isosurface (x, y, z, c, iso);
 ## p = patch ("Faces", f, "Vertices", v, "EdgeColor", "none");
-## set (gca, "PlotBoxAspectRatioMode","manual", "PlotBoxAspectRatio", [1 1 1]);
+## set (gca, "PlotBoxAspectRatioMode","manual", ...
+##           "PlotBoxAspectRatio", [1 1 1]);
 ## # set (p, "FaceColor", "green", "FaceLighting", "phong");
-## # light ("Position", [1 1 5]); ## Available with the JHandles package
+## # light ("Position", [1 1 5]); # Available with the JHandles package
 ##
 ## subplot (2, 2, 2); view (-38, 20);
 ## p = patch ("Faces", f, "Vertices", v, "EdgeColor", "blue");
-## set (gca, "PlotBoxAspectRatioMode","manual", "PlotBoxAspectRatio", [1 1 1]);
+## set (gca, "PlotBoxAspectRatioMode","manual", ...
+##           "PlotBoxAspectRatio", [1 1 1]);
 ## # set (p, "FaceColor", "none", "FaceLighting", "phong");
 ## # light ("Position", [1 1 5]);
 ##
@@ -96,17 +99,19 @@
 ## [f, v, c] = isosurface (x, y, z, c, iso, y);
 ## p = patch ("Faces", f, "Vertices", v, "FaceVertexCData", c, \
 ##            "FaceColor", "interp", "EdgeColor", "none");
-## set (gca, "PlotBoxAspectRatioMode","manual", "PlotBoxAspectRatio", [1 1 1]);
+## set (gca, "PlotBoxAspectRatioMode","manual", ...
+##           "PlotBoxAspectRatio", [1 1 1]);
 ## # set (p, "FaceLighting", "phong");
 ## # light ("Position", [1 1 5]);
 ##
 ## subplot (2, 2, 4); view (-38, 20);
 ## p = patch ("Faces", f, "Vertices", v, "FaceVertexCData", c, \
 ##            "FaceColor", "interp", "EdgeColor", "blue");
-## set (gca, "PlotBoxAspectRatioMode","manual", "PlotBoxAspectRatio", [1 1 1]);
+## set (gca, "PlotBoxAspectRatioMode","manual", ...
+##           "PlotBoxAspectRatio", [1 1 1]);
 ## # set (p, "FaceLighting", "phong");
 ## # light ("Position", [1 1 5]);
-## @end example
+## @end smallexample
 ##
 ## @seealso{isonormals, isocolors}
 ## @end deftypefn
--- a/scripts/plot/legend.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/legend.m	Tue Sep 20 15:38:24 2011 -0400
@@ -288,7 +288,7 @@
     if (! isempty (hlegend))
       set (hlegend, "box", "off", "visible", "off");
     endif
-  elseif (nargs == 0 && !(strcmp (position, "default") && 
+  elseif (nargs == 0 && !(strcmp (position, "default") &&
                           strcmp (orientation, "default")))
     if (! isempty (hlegend))
       hax = getfield (get (hlegend, "userdata"), "handle");
@@ -298,14 +298,14 @@
         h = legend (hax, hplots, text_strings, "orientation", orientation);
       elseif (strcmp (orientation, "default"))
         if (outside)
-          h = legend (hax, hplots, text_strings, "location", 
+          h = legend (hax, hplots, text_strings, "location",
                       strcat (position, "outside"));
         else
           h = legend (hax, hplots, text_strings, "location", position);
         endif
       else
         if (outside)
-          h = legend (hax, hplots, text_strings, "location", 
+          h = legend (hax, hplots, text_strings, "location",
                       strcat (position, "outside"), "orientation", orientation);
         else
           h = legend (hax, hplots, text_strings, "location", position,
--- a/scripts/plot/line.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/line.m	Tue Sep 20 15:38:24 2011 -0400
@@ -42,3 +42,18 @@
   endif
 
 endfunction
+
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   h = line;
+%!   assert (findobj (hf, "type", "line"), h);
+%!   assert (get (h, "xdata"), [0 1], eps);
+%!   assert (get (h, "ydata"), [0 1], eps);
+%!   assert (get (h, "type"), "line");
+%!   assert (get (h, "color"), get (0, "defaultlinecolor"));
+%!   assert (get (h, "linestyle"), get (0, "defaultlinelinestyle"));
+%!   assert (get (h, "linewidth"), get (0, "defaultlinelinewidth"), eps);
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
--- a/scripts/plot/loglog.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/loglog.m	Tue Sep 20 15:38:24 2011 -0400
@@ -60,3 +60,48 @@
 
 endfunction
 
+%!demo
+%! clf ();
+%! t = 1:0.01:10;
+%! x = sort ((t .* (1 + rand (size (t)))) .^ 2);
+%! y = ((t .* (1 + rand (size (t)))) .^ 2);
+%! loglog (x, y);
+
+%!demo
+%! clf ();
+%! a = logspace (-5, 1, 10);
+%! b =-logspace (-5, 1, 10);
+%!
+%! subplot (1, 2, 1)
+%! loglog (a, b)
+%! xlabel ('loglog (a, b)')
+%!
+%! subplot (1, 2, 2)
+%! loglog (a, abs (b))
+%! set (gca, 'ydir', 'reverse')
+%! xlabel ('loglog (a, abs (b))')
+
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   a = logspace (-5, 1, 10);
+%!   b = logspace (-5, 1, 10);
+%!   loglog (a, b)
+%!   assert (get (gca, "yscale"), "log");
+%!   assert (get (gca, "xscale"), "log");
+%! unwind_protect_cleanup
+%! close (hf);
+%! end_unwind_protect
+
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   a = logspace (-5, 1, 10);
+%!   b =-logspace (-5, 1, 10);
+%!   loglog (a, b)
+%!   axis tight
+%!   assert (all (get (gca, "ytick") < 0));
+%! unwind_protect_cleanup
+%! close (hf);
+%! end_unwind_protect
+
--- a/scripts/plot/module.mk	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/module.mk	Tue Sep 20 15:38:24 2011 -0400
@@ -20,38 +20,38 @@
   plot/private/__errplot__.m \
   plot/private/__ezplot__.m \
   plot/private/__fltk_file_filter__.m \
-  plot/private/__ghostscript__.m \
+  plot/private/__fltk_ginput__.m \
+  plot/private/__fltk_print__.m \
   plot/private/__getlegenddata__.m \
+  plot/private/__ghostscript__.m \
+  plot/private/__gnuplot_get_var__.m \
+  plot/private/__gnuplot_ginput__.m \
+  plot/private/__gnuplot_has_feature__.m \
   plot/private/__gnuplot_has_terminal__.m\
+  plot/private/__gnuplot_open_stream__.m \
+  plot/private/__gnuplot_print__.m \
+  plot/private/__gnuplot_version__.m \
+  plot/private/__go_draw_axes__.m \
+  plot/private/__go_draw_figure__.m \
   plot/private/__interp_cube__.m \
   plot/private/__line__.m \
+  plot/private/__marching_cube__.m \
+  plot/private/__next_line_color__.m \
+  plot/private/__next_line_style__.m \
   plot/private/__patch__.m \
   plot/private/__pie__.m \
   plot/private/__plt__.m \
   plot/private/__pltopt__.m \
+  plot/private/__print_parse_opts__.m \
   plot/private/__quiver__.m \
   plot/private/__scatter__.m \
   plot/private/__stem__.m \
   plot/private/__tight_eps_bbox__.m
 
 plot_FCN_FILES = \
-  plot/__fltk_ginput__.m \
-  plot/__fltk_print__.m \
   plot/__gnuplot_drawnow__.m \
-  plot/__gnuplot_get_var__.m \
-  plot/__gnuplot_ginput__.m \
-  plot/__gnuplot_has_feature__.m \
-  plot/__gnuplot_open_stream__.m \
-  plot/__gnuplot_print__.m \
-  plot/__gnuplot_version__.m \
   plot/__go_close_all__.m \
-  plot/__go_draw_axes__.m \
-  plot/__go_draw_figure__.m \
-  plot/__marching_cube__.m \
-  plot/__next_line_color__.m \
-  plot/__next_line_style__.m \
   plot/__plt_get_axis_arg__.m \
-  plot/__print_parse_opts__.m \
   plot/allchild.m \
   plot/ancestor.m \
   plot/area.m \
@@ -171,6 +171,9 @@
   plot/surfnorm.m \
   plot/text.m \
   plot/title.m \
+  plot/trimesh.m \
+  plot/triplot.m \
+  plot/trisurf.m \
   plot/uigetdir.m \
   plot/uigetfile.m \
   plot/uimenu.m \
--- a/scripts/plot/pareto.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/pareto.m	Tue Sep 20 15:38:24 2011 -0400
@@ -66,11 +66,11 @@
       if (ischar (y))
         y = cellstr (y);
       else
-        y = cellfun (@num2str, num2cell (y), "uniformoutput", false);
+        y = cellfun ("num2str", num2cell (y), "uniformoutput", false);
       endif
     endif
   else
-    y = cellfun (@int2str, num2cell (1 : numel(x)),
+    y = cellfun ("int2str", num2cell (1 : numel(x)),
                  "uniformoutput", false);
   endif
 
--- a/scripts/plot/patch.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/patch.m	Tue Sep 20 15:38:24 2011 -0400
@@ -152,3 +152,23 @@
 %!       'FaceVertexCData', jet(5), 'FaceColor', 'interp')
 %! view (-37.5, 30)
 
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   h = patch;
+%!   assert (findobj (hf, "type", "patch"), h);
+%!   assert (get (h, "xdata"), [0; 1; 1], eps);
+%!   assert (get (h, "ydata"), [0; 0; 1], eps);
+%!   assert (isempty(get (h, "zdata")));
+%!   assert (isempty(get (h, "cdata")));
+%!   assert (get (h, "faces"), [1, 2, 3], eps);
+%!   assert (get (h, "vertices"), [0 0; 1 0; 1 1], eps);
+%!   assert (get (h, "type"), "patch");
+%!   assert (get (h, "facecolor"), [0 0 1]);
+%!   assert (get (h, "linestyle"), get (0, "defaultpatchlinestyle"));
+%!   assert (get (h, "linewidth"), get (0, "defaultpatchlinewidth"), eps);
+%!   assert (get (h, "marker"), get (0, "defaultpatchmarker"));
+%!   assert (get (h, "markersize"), get (0, "defaultpatchmarkersize"));
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
--- a/scripts/plot/pcolor.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/pcolor.m	Tue Sep 20 15:38:24 2011 -0400
@@ -80,3 +80,14 @@
   endif
 
 endfunction
+
+%!demo
+%! clf
+%! [~,~,Z]=peaks;
+%! pcolor(Z);
+
+%!demo
+%! [X,Y,Z]=sombrero;
+%! [Fx,Fy] = gradient(Z);
+%! pcolor(X,Y,Fx+Fy);
+%! shading interp;
--- a/scripts/plot/plotyy.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/plotyy.m	Tue Sep 20 15:38:24 2011 -0400
@@ -79,7 +79,7 @@
     ca = get (f, "currentaxes");
     if (isempty (ca))
       ax = [];
-    elseif (strcmp (get (ca, "tag"), "plotyy"));
+    elseif (strcmp (get (ca, "tag"), "plotyy"))
       ax = get (ca, "__plotyy_axes__");
     else
       ax = ca;
@@ -115,8 +115,6 @@
     endif
   end_unwind_protect
 
-  set (ax, "activepositionproperty", "position");
-
   if (nargout > 0)
     Ax = ax;
     H1 = h1;
@@ -164,10 +162,24 @@
   colors = get (ax(1), "colororder");
   set (ax(2), "colororder", [colors(2:end,:); colors(1,:)]);
 
+  if (strcmp (get (ax(1), "autopos_tag"), "subplot"))
+    set (ax(2), "autopos_tag", "subplot");
+  else
+    set (ax, "activepositionproperty", "position");
+  endif
+
   h2 = feval (fun2, x2, y2);
   set (ax(2), "yaxislocation", "right");
   set (ax(2), "ycolor", getcolor (h2(1)));
-  set (ax(2), "position", get (ax(1), "position"));
+
+
+  if (strcmp (get(ax(1), "activepositionproperty"), "position"))
+    set (ax(2), "position", get (ax(1), "position"));
+  else
+    set (ax(2), "outerposition", get (ax(1), "outerposition"));
+    set (ax(2), "looseinset", get (ax(1), "looseinset"));
+  endif
+
   set (ax(2), "xlim", xlim);
   set (ax(2), "color", "none");
   set (ax(2), "box", "off");
@@ -186,6 +198,10 @@
 
   addlistener (ax(1), "position", {@update_position, ax(2)});
   addlistener (ax(2), "position", {@update_position, ax(1)});
+  addlistener (ax(1), "outerposition", {@update_position, ax(2)});
+  addlistener (ax(2), "outerposition", {@update_position, ax(1)});
+  addlistener (ax(1), "looseinset", {@update_position, ax(2)});
+  addlistener (ax(2), "looseinset", {@update_position, ax(1)});
   addlistener (ax(1), "view", {@update_position, ax(2)});
   addlistener (ax(2), "view", {@update_position, ax(1)});
   addlistener (ax(1), "plotboxaspectratio", {@update_position, ax(2)});
@@ -268,17 +284,27 @@
   if (! recursion)
     unwind_protect
       recursion = true;
-      position = get (h, "position");
       view = get (h, "view");
-      plotboxaspectratio = get (h, "plotboxaspectratio");
-      plotboxaspectratiomode = get (h, "plotboxaspectratiomode");
-      oldposition = get (ax2, "position");
       oldview = get (ax2, "view");
+      plotboxaspectratio = get (h, "plotboxaspectratio");
       oldplotboxaspectratio = get (ax2, "plotboxaspectratio");
+      plotboxaspectratiomode = get (h, "plotboxaspectratiomode");
       oldplotboxaspectratiomode = get (ax2, "plotboxaspectratiomode");
-      if (! (isequal (position, oldposition) && isequal (view, oldview)))
-        set (ax2, "position", position, "view", view);
+
+      if (strcmp (get(h, "activepositionproperty"), "position"))
+        position = get (h, "position");
+        oldposition = get (ax2, "position");
+        if (! (isequal (position, oldposition) && isequal (view, oldview)))
+          set (ax2, "position", position, "view", view);
+        endif
+      else
+        outerposition = get (h, "outerposition");
+        oldouterposition = get (ax2, "outerposition");
+        if (! (isequal (outerposition, oldouterposition) && isequal (view, oldview)))
+          set (ax2, "outerposition", outerposition, "view", view);
+        endif
       endif
+
       if (! (isequal (plotboxaspectratio, oldplotboxaspectratio)
              && isequal (plotboxaspectratiomode, oldplotboxaspectratiomode)))
         set (ax2, "plotboxaspectratio", plotboxaspectratio);
--- a/scripts/plot/polar.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/polar.m	Tue Sep 20 15:38:24 2011 -0400
@@ -211,3 +211,15 @@
   endif
 
 endfunction
+
+
+%!demo
+%! theta = linspace (0, 2*pi, 1000);
+%! rho = sin (7*theta);
+%! polar (theta, rho);
+
+%!demo
+%! theta = linspace (0, 10*pi, 1000);
+%! rho = sin (5/4*theta);
+%! polar (theta, rho);
+
--- a/scripts/plot/print.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/print.m	Tue Sep 20 15:38:24 2011 -0400
@@ -611,7 +611,7 @@
              "print.m: error closing file '%s'", latexfile);
     endif
     ## TODO - should this be fixed in GL2PS?
-    latex = strrep (latex, "\\includegraphics{}", 
+    latex = strrep (latex, "\\includegraphics{}",
                     sprintf ("\\includegraphics{%s}", graphicsfile));
   else
     error ("print:erroropeningfile",
--- a/scripts/plot/private/__axis_label__.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/private/__axis_label__.m	Tue Sep 20 15:38:24 2011 -0400
@@ -25,24 +25,20 @@
 
 function retval = __axis_label__ (caller, txt, varargin)
 
-  if (ischar (txt))
-    ca = gca ();
+  ca = gca ();
 
-    h = get (gca (), caller);
+  h = get (gca (), caller);
 
-    set (h, "fontangle", get (ca, "fontangle"),
-         "fontname", get (ca, "fontname"),
-         "fontsize", get (ca, "fontsize"),
-         "fontunits", get (ca, "fontunits"),
-         "fontweight", get (ca, "fontweight"),
-         "string", txt,
-         varargin{:});
+  set (h, "fontangle", get (ca, "fontangle"),
+       "fontname", get (ca, "fontname"),
+       "fontsize", get (ca, "fontsize"),
+       "fontunits", get (ca, "fontunits"),
+       "fontweight", get (ca, "fontweight"),
+       "string", txt,
+       varargin{:});
 
-    if (nargout > 0)
-      retval = h;
-    endif
-  else
-    error ("%s: expecting first argument to be character string", caller);
+  if (nargout > 0)
+    retval = h;
   endif
 
 endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/private/__fltk_ginput__.m	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,105 @@
+## Copyright (C) 2010-2011 Shai Ayal
+##
+## 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 3 of the License, 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, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {[@var{x}, @var{y}, @var{buttons}] =} __fltk_ginput__ (@var{f}, @var{n})
+## Undocumented internal function.
+## @end deftypefn
+
+## This is ginput.m implementation for fltk.
+
+## FIXME -- Key presses cannot toggle menu items nor hotkey functionality
+## (grid, autoscale) during ginput!
+
+function [x, y, button] = __fltk_ginput__ (f, n = -1)
+
+  if (isempty (get (f, "currentaxes")))
+    error ("ginput: must have at least one axes");
+  endif
+
+  x = y = button = [];
+  ginput_aggregator (0, 0, 0, 0);
+
+  unwind_protect
+
+    orig_windowbuttondownfcn = get (f, "windowbuttondownfcn");
+    set (f, "windowbuttondownfcn", @ginput_windowbuttondownfcn);
+
+    orig_ginput_keypressfcn = get (f, "keypressfcn");
+    set (f, "keypressfcn", @ginput_keypressfcn);
+
+    while (true)
+      __fltk_redraw__ ();
+
+      ## Release CPU.
+      sleep (0.01);
+
+      [x, y, n0, button] = ginput_aggregator (-1, 0, 0, 0);
+      if (n0 == n || n0 < 0)
+        break;
+      endif
+    endwhile
+
+  unwind_protect_cleanup
+    set (f, "windowbuttondownfcn", orig_windowbuttondownfcn);
+    set (f, "keypressfcn", orig_ginput_keypressfcn);
+  end_unwind_protect
+
+endfunction
+
+function [x, y, n, button] = ginput_aggregator (mode, xn, yn, btn)
+  persistent x y n button;
+
+  if (mode == 0)
+    ## Initialize.
+    x = [];
+    y = [];
+    button = [];
+    n = 0;
+  elseif (mode == 1)
+    ## Accept mouse button or key press.
+    x = [x; xn];
+    y = [y; yn];
+    button = [button; btn];
+    n += 1;
+  elseif (mode == 2)
+    ## The end due to Enter.
+    n = -1;
+ endif
+endfunction
+
+function ginput_windowbuttondownfcn (src, data)
+  point = get (get (src,"currentaxes"), "currentpoint");
+  ## FIXME -- How to get the actual mouse button pressed (1,2,3) into
+  ## "button"?
+  button = 1;
+  ginput_aggregator (1, point(1,1), point(2,1), button);
+endfunction
+
+function ginput_keypressfcn (src, evt)
+  point = get (get (src, "currentaxes"), "currentpoint");
+  ## FIXME -- use evt.Key or evt.Character?
+  key = evt.Key;
+  if (key == 10)
+    ## Enter key.
+    ginput_aggregator (2, point(1,1), point(2,1), key);
+  else
+    ginput_aggregator (1, point(1,1), point(2,1), key);
+  endif
+endfunction
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/private/__fltk_print__.m	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,161 @@
+## Copyright (C) 2010-2011 Shai Ayal
+##
+## 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 3 of the License, 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, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {} __fltk_print__ (@var{@dots{}})
+## Undocumented internal function.
+## @end deftypefn
+
+function opts = __fltk_print__ (opts)
+
+  dos_shell = (ispc () && ! isunix ());
+
+  figure (opts.figure);
+  drawnow ("expose");
+  __fltk_redraw__ ();
+
+  if (! isempty (opts.fig2dev_binary))
+    ## fig2dev is prefered for conversion to emf
+    fig2dev_devices = {"pstex", "mf", "emf"};
+  else
+    fig2dev_devices = {"pstex", "mf"};
+  endif
+
+  gl2ps_device = {};
+  pipeline = {};
+  switch (lower (opts.devopt))
+  case {"eps", "eps2", "epsc", "epsc2"}
+    ## format GL2PS_EPS
+    gl2ps_device = {"eps"};
+    ## FIXME - use epstool to tighten bbox and provide preview.
+    pipeline = {opts.epstool_cmd(opts, "-", opts.name)};
+  case {"epslatex", "pslatex", "pdflatex", "epslatexstandalone", ...
+        "pslatexstandalone", "pdflatexstandalone"}
+    ## format GL2PS_TEX
+    n = find (opts.devopt == "l", 1);
+    suffix = opts.devopt(1:n-1);
+    dot = find (opts.name == ".", 1, "last");
+    if ((! isempty (dot))
+        && any (strcmpi (opts.name(dot:end), ...
+                {".eps", ".ps", ".pdf", ".tex", "."})))
+      name = opts.name(1:dot-1);
+      if (dot < numel (opts.name)
+          && any (strcmpi (opts.name(dot+1:end), {"eps", "ps", "pdf"})))
+        ## If user provides eps/ps/pdf suffix, use it.
+        suffix = opts.name(dot+1:end);
+      endif
+    elseif (dot == numel (opts.name))
+      name = opts.name;
+    endif
+    gl2ps_device = {sprintf("%snotxt", lower (suffix))};
+    gl2ps_device{2} = "tex";
+    if (dos_shell)
+      ## FIXME - this will only work on MinGW with the MSYS shell
+      pipeline = {sprintf("cat > %s-inc.%s", name, suffix)};
+      pipeline{2} = sprintf ("cat > %s.tex", name);
+    else
+      pipeline = {sprintf("cat > %s-inc.%s", name, suffix)};
+      pipeline{2} = sprintf ("cat > %s.tex", name);
+    endif
+  case "tikz"
+    ## format GL2PS_PGF
+    gl2ps_device = {"pgf"};
+    pipeline = {sprintf("cat > %s", opts.name)};
+  case "svg"
+    ## format GL2PS_SVG
+    gl2ps_device = {"svg"};
+    pipeline = {sprintf("cat > %s", opts.name)};
+  case fig2dev_devices
+    cmd_pstoedit = opts.pstoedit_cmd (opts, "fig");
+    cmd_fig2dev = opts.fig2dev_cmd (opts, opts.devopt);
+    if (strcmp (opts.devopt, "pstex"))
+      [~, ~, ext] = fileparts (opts.name);
+      if (any (strcmpi (ext, {".ps", ".tex", "."})))
+        opts.name = opts.name(1:end-numel(ext));
+      endif
+      opts.name = strcat (opts.name, ".ps");
+      cmd = sprintf ("%s | %s > %s", cmd_pstoedit, cmd_fig2dev, opts.name);
+      gl2ps_device = {"eps"};
+      pipeline = {cmd};
+      cmd_fig2dev = opts.fig2dev_cmd (opts, "pstex_t");
+      gl2ps_device{2} = "eps";
+      pipeline{2} = sprintf ("%s | %s > %s", cmd_pstoedit,
+                             cmd_fig2dev, strrep(opts.name, ".ps", ".tex"));
+    else
+      cmd = sprintf ("%s | %s > %s", cmd_pstoedit, cmd_fig2dev, opts.name);
+      gl2ps_device = {"eps"};
+      pipeline = {cmd};
+    endif
+  case "aifm"
+    cmd = opts.pstoedit_cmd (opts, "ps2ai");
+    gl2ps_device = {"eps"};
+    pipeline = {sprintf("%s > %s", cmd, opts.name)};
+  case {"dxf", "emf", "fig", "hpgl"}
+    cmd = opts.pstoedit_cmd (opts);
+    gl2ps_device = {"eps"};
+    pipeline = {sprintf("%s > %s", cmd, opts.name)};
+  case {"corel", "gif"}
+    error ("print:unsupporteddevice",
+           "print.m: %s output is not available for the FLTK graphics toolkit",
+           upper (opts.devopt));
+  case opts.ghostscript.device
+    opts.ghostscript.source = "-";
+    opts.ghostscript.output = opts.name;
+    if (opts.send_to_printer)
+      opts.unlink(strcmp (opts.unlink, opts.ghostscript.output)) = [];
+      opts.ghostscript.output = "-";
+    endif
+    [cmd_gs, cmd_cleanup] = __ghostscript__ (opts.ghostscript);
+    if (opts.send_to_printer || isempty (opts.name))
+      cmd_lpr = opts.lpr_cmd (opts);
+      cmd = sprintf("%s | %s", cmd_gs, cmd_lpr);
+    else
+      cmd = sprintf("%s", cmd_gs);
+    endif
+    if (! isempty (cmd_cleanup))
+      gl2ps_device = {"eps"};
+      if (dos_shell)
+        pipeline = {sprintf("%s & %s", cmd, cmd_cleanup)};
+      else
+        pipeline = {sprintf("%s ; %s", cmd, cmd_cleanup)};
+      endif
+    else
+      gl2ps_device = {"eps"};
+      pipeline = {cmd};
+    endif
+  otherwise
+    error (sprintf ("print:no%soutput", opts.devopt),
+           "print.m: %s output is not available for GL2PS output",
+           upper (opts.devopt));
+  endswitch
+
+  opts.pipeline = pipeline;
+
+  for n = 1:numel(pipeline)
+    if (opts.debug)
+      fprintf ("fltk-pipeline: '%s'\n", pipeline{n});
+    endif
+    drawnow (gl2ps_device{n}, strcat('|',pipeline{n}));
+  endfor
+
+  if (! isempty (strfind (opts.devopt, "standalone")))
+    opts.latex_standalone (opts);
+  endif
+
+endfunction
+
--- a/scripts/plot/private/__ghostscript__.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/private/__ghostscript__.m	Tue Sep 20 15:38:24 2011 -0400
@@ -44,7 +44,7 @@
   cleanup_cmd = "";
 
   args = varargin;
-  n = find (cellfun (@isstruct, args));
+  n = find (cellfun ("isclass", args, "struct"));
   if (! isempty (n))
     f = fieldnames (args{n});
     for m = 1:numel(f)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/private/__gnuplot_get_var__.m	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,161 @@
+## Copyright (C) 2009-2011 Ben Abbott
+##
+## 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 3 of the License, 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, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {@var{value} =} __gnuplot_get_var__ (@var{h}, @var{name}, @var{fmt})
+## Undocumented internal function.
+## @end deftypefn
+
+## Author: Ben Abbott <bpabbott@mac.com>
+## Created: 2009-02-07
+
+function gp_var_value = __gnuplot_get_var__ (h, gp_var_name, fmt)
+
+  if (nargin == 0)
+    h = gcf ();
+  endif
+  if (nargin < 2)
+    print_usage ();
+  endif
+  if (nargin < 3)
+    fmt = '';
+  endif
+
+  if (numel (h) == 1 && isfigure (h))
+    if (isempty (get (gcf, "__plot_stream__")))
+      ostream = __gnuplot_open_stream__ (2, h);
+    else
+      ostream = get (h, "__plot_stream__");
+    endif
+  else
+    ostream = h;
+  endif
+  if (numel (ostream) < 1)
+    error ("__gnuplot_get_var__: stream to gnuplot not open");
+  elseif (ispc ())
+    if (numel (ostream) == 1)
+      error ("__gnuplot_get_var__: Need mkfifo that is not implemented under Windows");
+    endif
+    use_mkfifo = false;
+    istream = ostream(2);
+    ostream = ostream(1);
+  else
+    use_mkfifo = true;
+    ostream = ostream(1);
+  endif
+
+  if (use_mkfifo)
+    gpin_name = tmpnam ();
+
+    ## Mode: 6*8*8 ==  0600
+    [err, msg] = mkfifo (gpin_name, 6*8*8);
+
+    if (err != 0)
+      error ("__gnuplot_get_var__: Can not make fifo (%s)", msg);
+    endif
+  endif
+
+  gp_var_name = strtrim (gp_var_name);
+  n = min (strfind (gp_var_name, " "), strfind (gp_var_name, ",")) - 1;
+  if (isempty (n))
+    n = numel (gp_var_name);
+  endif
+
+  unwind_protect
+
+    ## Notes: Variables may be undefined if user closes gnuplot by "q"
+    ## or Alt-F4. Further, this abrupt close also requires the leading
+    ## "\n" on the next line.
+    if (use_mkfifo)
+      fprintf (ostream, "\nset print \"%s\";\n", gpin_name);
+      fflush (ostream);
+      [gpin, err] = fopen (gpin_name, "r");
+      if (err != 0)
+        ## Try a second time, and then give an error.
+        [gpin, err] = fopen (gpin_name, "r");
+      endif
+      if (err != 0)
+        error ("__gnuplot_get_var__: can not open fifo");
+      endif
+      gp_cmd = sprintf ("\nif (exists(\"%s\")) print %s; else print NaN\n",
+                        gp_var_name(1:n), gp_var_name);
+      fputs (ostream, gp_cmd);
+
+      ## Close output file, to force it to be flushed
+      fputs (ostream, "set print;\n");
+      fflush (ostream);
+
+      ## Now read from fifo.
+      reading = true;
+      str = {};
+      while (reading)
+        str{end+1} = fgets (gpin);
+        if (isnumeric (str{end}) && (str{end} == -1))
+          reading = false;
+          str = str(1:(end-1));
+        endif
+      endwhile
+      str = strcat (str{:});
+      fclose (gpin);
+    else
+      ## Direct gnuplot to print to <STDOUT>
+      fprintf (ostream, "set print \"-\";\n");
+      fflush (ostream);
+      gp_cmd = sprintf ("\nif (exists(\"%s\")) print \"OCTAVE: \", %s; else print NaN\n",
+                        gp_var_name(1:n), gp_var_name);
+      fputs (ostream, gp_cmd);
+      fflush (ostream);
+      ## Direct gnuplot to print to <STDERR>
+      fputs (ostream, "set print;\n");
+      fflush (ostream);
+
+      str = {};
+      while (isempty (str))
+        str = char (fread (istream)');
+        if (isempty (str))
+          sleep (0.05);
+        else
+          str = regexp (str, 'OCTAVE:.*', "match");
+          str = str{end}(8:end);
+        endif
+        fclear (istream);
+      endwhile
+    endif
+
+    ## Strip out EOLs and the continuation character "|"
+    str(str=="\n") = "";
+    str(str=="\r") = "";
+    n_continue = strfind (str, " \\ ");
+    if (! isempty (n_continue))
+      str(n_continue+1) = "";
+    endif
+
+    if (isempty (fmt))
+      gp_var_value = strtrim (str);
+    else
+      gp_var_value = sscanf (str, fmt);
+    endif
+
+  unwind_protect_cleanup
+    if (use_mkfifo)
+      unlink (gpin_name);
+    endif
+  end_unwind_protect
+
+endfunction
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/private/__gnuplot_ginput__.m	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,154 @@
+## Copyright (C) 2004-2011 Petr Mikulik
+##
+## 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 3 of the License, 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, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {[@var{x}, @var{y}, @var{buttons}] =} __gnuplot_ginput__ (@var{f}, @var{n})
+## Undocumented internal function.
+## @end deftypefn
+
+## This is ginput.m implementation for gnuplot and X11.
+## It requires gnuplot 4.1 and later.
+
+## This file initially bore the copyright statement
+## Petr Mikulik
+## History: June 2006; August 2005; June 2004; April 2004
+## License: public domain
+
+function [x, y, button] = __gnuplot_ginput__ (f, n)
+
+  ostream = get (f, "__plot_stream__");
+  if (numel (ostream) < 1)
+    error ("ginput: stream to gnuplot not open");
+  elseif (ispc ())
+    if (numel (ostream) == 1)
+      error ("ginput: Need mkfifo that is not implemented under Windows");
+    endif
+    use_mkfifo = false;
+    istream = ostream(2);
+    ostream = ostream(1);
+  else
+    use_mkfifo = true;
+    ostream = ostream(1);
+  endif
+
+  if (compare_versions (__gnuplot_version__ (), "4.0", "<="))
+    error ("ginput: version %s of gnuplot not supported", gnuplot_version ());
+  endif
+
+  if (nargin == 1)
+    x = zeros (100, 1);
+    y = zeros (100, 1);
+    button = zeros (100, 1);
+  else
+    x = zeros (n, 1);
+    y = zeros (n, 1);
+    button = zeros (n, 1);
+  endif
+
+  if (use_mkfifo)
+    gpin_name = tmpnam ();
+
+    ##Mode: 6*8*8 ==  0600
+    [err, msg] = mkfifo (gpin_name, 6*8*8);
+
+    if (err != 0)
+      error ("ginput: Can not open fifo (%s)", msg);
+    endif
+  endif
+
+  unwind_protect
+
+    k = 0;
+    while (true)
+      k++;
+
+      ## Notes: MOUSE_* can be undefined if user closes gnuplot by "q"
+      ## or Alt-F4. Further, this abrupt close also requires the leading
+      ## "\n" on the next line.
+      if (use_mkfifo)
+        fprintf (ostream, "set print \"%s\";\n", gpin_name);
+        fflush (ostream);
+        [gpin, err] = fopen (gpin_name, "r");
+        if (err != 0)
+          error ("ginput: Can not open fifo (%s)", msg);
+        endif
+        fputs (ostream, "pause mouse any;\n\n");
+        fputs (ostream, "\nif (exists(\"MOUSE_KEY\") && exists(\"MOUSE_X\")) print MOUSE_X, MOUSE_Y, MOUSE_KEY; else print \"0 0 -1\"\n");
+
+        ## Close output file, to force it to be flushed
+        fputs (ostream, "set print;\n");
+        fflush (ostream);
+
+        ## Now read from fifo.
+        [x(k), y(k), button(k), count] = fscanf (gpin, "%f %f %d", "C");
+        fclose (gpin);
+      else
+        fprintf (ostream, "set print \"-\";\n");
+        fflush (ostream);
+        fputs (ostream, "pause mouse any;\n\n");
+        fputs (ostream, "\nif (exists(\"MOUSE_KEY\") && exists(\"MOUSE_X\")) print \"OCTAVE: \", MOUSE_X, MOUSE_Y, MOUSE_KEY; else print \"0 0 -1\"\n");
+
+        ## Close output file, to force it to be flushed
+        fputs (ostream, "set print;\n");
+        fflush (ostream);
+
+        str = {};
+        while (isempty (str))
+          str = char (fread (istream)');
+          if (isempty (str))
+            sleep (0.05);
+          else
+            str = regexp (str, 'OCTAVE:\s+[-+.\d]+\s+[-+.\d]+\s+\d*', 'match');
+          endif
+          fclear (istream);
+        endwhile
+        [x(k), y(k), button(k), count] = sscanf (str{end}(8:end), "%f %f %d", "C");
+      endif
+
+      if ([x(k), y(k), button(k)] == [0, 0, -1])
+        ## Mousing not active (no plot yet).
+        break;
+      endif
+
+      if (nargin > 1)
+        ## Input argument n was given => stop when k == n.
+        if (k == n)
+          break;
+        endif
+      else
+        ## Input argument n not given => stop when hitting a return key.
+        ## if (button(k) == 0x0D || button(k) == 0x0A)
+        ##   ## hit Return or Enter
+        if (button(k) == 0x0D)
+          ## hit Return
+          x(k:end) = [];
+          y(k:end) = [];
+          button(k:end) = [];
+          break;
+        endif
+      endif
+    endwhile
+
+  unwind_protect_cleanup
+    if (use_mkfifo)
+      unlink (gpin_name);
+    endif
+  end_unwind_protect
+
+endfunction
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/private/__gnuplot_has_feature__.m	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,61 @@
+## Copyright (C) 2009-2011 Ben Abbott
+##
+## 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 3 of the License, 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, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {@var{has_feature} =} __gnuplot_has_feature__ (@var{feature})
+## Undocumented internal function.
+## @end deftypefn
+
+## Author: Ben Abbott <bpabbott@mac.com>
+## Created: 2009-01-27
+
+function res = __gnuplot_has_feature__ (feature)
+  persistent features has_features
+  features = {"x11_figure_position",
+              "wxt_figure_size",
+              "transparent_patches",
+              "transparent_surface",
+              "epslatex_implies_eps_filesuffix",
+              "epslatexstandalone_terminal",
+              "screen_coordinates_for_{lrtb}margin",
+              "variable_GPVAL_TERMINALS",
+              "key_has_font_properties"};
+
+  if (isempty (has_features))
+    try
+      gnuplot_version = __gnuplot_version__ ();
+    catch
+      ## Don't throw an error if gnuplot isn't installed
+      gnuplot_version = "0.0.0";
+    end_try_catch
+    versions = {"4.2.5", "4.4", "4.4", "4.4", "4.2", "4.2", "4.4", "4.4", "4.4"};
+    operators = {">=", ">=", ">=", ">=", ">=", ">=", ">=", ">=", ">="};
+    have_features = logical (zeros (size (features)));
+    for n = 1 : numel (have_features)
+      has_features(n) = compare_versions (gnuplot_version, versions{n}, operators{n});
+    endfor
+  endif
+
+  n = find (strcmpi (feature, features));
+  if (isempty (n))
+    res = NaN;
+  else
+    res = has_features(n);
+  endif
+endfunction
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/private/__gnuplot_open_stream__.m	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,45 @@
+## Copyright (C) 2009-2011 Ben Abbott
+##
+## 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 3 of the License, 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, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {@var{stream} =} __gnuplot_open_stream__ (@var{npipes}, @var{h})
+## Undocumented internal function.
+## @end deftypefn
+
+## Author: Ben Abbott <bpabbott@mac.com>
+## Created: 2009-04-11
+
+function plot_stream = __gnuplot_open_stream__ (npipes, h)
+  [prog, args] = gnuplot_binary ();
+  if (npipes > 1)
+    [plot_stream(1), plot_stream(2), pid] = popen2 (prog, args{:});
+    if (pid < 0)
+      error ("__gnuplot_open_stream__: failed to open connection to gnuplot");
+    else
+      plot_stream(3) = pid;
+    endif
+  else
+    plot_stream = popen (sprintf ("%s ", prog, args{:}), "w");
+    if (plot_stream < 0)
+      error ("__gnuplot_open_stream__: failed to open connection to gnuplot");
+    endif
+  endif
+  if (nargin > 1)
+    set (h, "__plot_stream__", plot_stream);
+  endif
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/private/__gnuplot_print__.m	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,300 @@
+## Copyright (C) 1999-2011 Daniel Heiserer
+## Copyright (C) 2001 Laurent Mazet
+##
+## 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 3 of the License, 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, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {} __gnuplot_print__ (@var{@dots{}})
+## Undocumented internal function.
+## @end deftypefn
+
+## Author: Daniel Heiserer <Daniel.heiserer@physik.tu-muenchen.de>
+## Adapted-By: jwe
+
+function opts = __gnuplot_print__ (opts)
+
+  dos_shell = (ispc () && ! isunix ());
+
+  if (isempty (opts.fontsize))
+    ## If no fontsize, determine the nominal axes fontsize.
+    defaultfontsize = get (0, "defaultaxesfontsize");
+    axesfontsize = get (findobj (opts.figure, "type", "axes"), "fontsize");
+    if (iscell (axesfontsize))
+      axesfontsize = round (median (cell2mat (axesfontsize)));
+    endif
+    if (isempty (axesfontsize))
+      opts.fontsize = defaultfontsize;
+    else
+      opts.fontsize = axesfontsize;
+    endif
+  endif
+  ## The axes-label and tick-label spacing is determined by
+  ## the font spec given in "set terminal ..."
+  gp_opts = font_spec (opts);
+
+  pipeline = "";
+
+  switch (lower (opts.devopt))
+  case {"eps", "eps2", "epsc", "epsc2"}
+    if (any (strcmp (opts.devopt, {"eps", "epsc"})))
+      gp_opts = sprintf ("%s level1", gp_opts);
+    endif
+    if (opts.tight_flag || ! isempty (opts.preview))
+      tmp_file = strcat (tmpnam (), ".eps");
+      eps_drawnow (opts, tmp_file, gp_opts);
+      if (dos_shell)
+        cleanup = sprintf (" & del %s", strrep (tmp_file, '/', '\'));
+      else
+        cleanup = sprintf (" ; rm %s", tmp_file);
+      endif
+      pipeline = {sprintf("%s %s",
+                          opts.epstool_cmd (opts, tmp_file, opts.name),
+                          cleanup)};
+    else
+      eps_drawnow (opts, opts.name, gp_opts);
+    endif
+  case {"epslatex", "pslatex", "pstex", "epslatexstandalone"}
+    dot = find (opts.name == ".", 1, "last");
+    if ((! isempty (dot))
+        && any (strcmpi (opts.name(dot:end),
+                {".eps", ".ps", ".pdf", ".tex", "."})))
+      name = opts.name(1:dot-1);
+    endif
+    if (strfind (opts.devopt, "standalone"))
+      term = sprintf ("%s ",
+                      strrep (opts.devopt, "standalone", " standalone"));
+    else
+      term = sprintf ("%s ", opts.devopt);
+    endif
+    if (__gnuplot_has_feature__ ("epslatex_implies_eps_filesuffix"))
+      suffix = "tex";
+    else
+      %% Gnuplot 4.0 wants a ".eps" suffix.
+      suffix = "eps";
+    endif
+    local_drawnow (sprintf ("%s %s", term, gp_opts),
+                   strcat (name, ".", suffix), opts);
+  case "tikz"
+    if (__gnuplot_has_terminal__ ("tikz"))
+      local_drawnow (sprintf ("lua tikz %s", gp_opts), opts.name, opts);
+    else
+      error (sprintf ("print:no%soutput", opts.devopt),
+             "print.m: '%s' output is not available for gnuplot-%s",
+             upper (opts.devopt), __gnuplot_version__ ());
+    endif
+  case "svg"
+    local_drawnow (sprintf ("svg dynamic %s", gp_opts), opts.name, opts);
+  case {"aifm", "corel", "eepic", "emf", "fig"}
+    local_drawnow (sprintf ("%s %s", opts.devopt, gp_opts), opts.name, opts);
+  case {"pdfcairo", "pngcairo"}
+    if (__gnuplot_has_terminal__ (opts.devopt))
+      local_drawnow (sprintf ("%s %s", opts.devopt, gp_opts), opts.name, opts);
+    else
+      error (sprintf ("print:no%soutput", opts.devopt),
+             "print.m: '%s' output is not available for gnuplot-%s",
+             upper (opts.devopt), __gnuplot_version__ ());
+    endif
+  case {"canvas", "dxf", "hpgl", "mf", "gif", "pstricks", "texdraw"}
+    local_drawnow (sprintf ("%s %s", opts.devopt, gp_opts), opts.name, opts);
+  case opts.ghostscript.device
+    gp_opts = font_spec (opts, "devopt", "eps");
+    opts.ghostscript.output = opts.name;
+    opts.ghostscript.source = strcat (tmpnam (), ".eps");
+    eps_drawnow (opts, opts.ghostscript.source, gp_opts);
+    [cmd_gs, cmd_cleanup] = __ghostscript__ (opts.ghostscript);
+    if (opts.send_to_printer || isempty (opts.name))
+      cmd_lpr = opts.lpr_cmd (opts);
+      cmd = sprintf ("%s | %s", cmd_gs, cmd_lpr);
+    else
+      cmd = sprintf ("%s", cmd_gs);
+    endif
+    if (dos_shell)
+      cmd = sprintf ("%s & del %s", cmd, strrep (opts.ghostscript.source, '/', '\'));
+    else
+      cmd = sprintf ("%s ; rm %s", cmd, opts.ghostscript.source);
+    endif
+    if (! isempty (cmd_cleanup))
+      if (dos_shell)
+        pipeline = {sprintf("%s & %s", cmd, cmd_cleanup)};
+      else
+        pipeline = {sprintf("%s ; %s", cmd, cmd_cleanup)};
+      endif
+    else
+      pipeline = {cmd};
+    endif
+  otherwise
+    error (sprintf ("print:no%soutput", opts.devopt),
+           "print.m: %s output is not available for the Gnuplot graphics toolkit",
+           upper (opts.devopt));
+  endswitch
+
+
+  opts.pipeline = pipeline;
+
+  for n = 1:numel(pipeline)
+    if (opts.debug)
+      fprintf ("gnuplot-pipeline: '%s'\n", pipeline{n});
+    endif
+    [status, output] = system (pipeline{n});
+    if (status)
+      fprintf ("%s\n%s\n%s\n",
+               "---------- output begin ----------",
+               output,
+               "----------- output end -----------");
+      error ("gnuplot:failedpipe", "print: failed to print");
+    endif
+  endfor
+
+endfunction
+
+function eps_drawnow (opts, epsfile, gp_opts)
+  [h, fontsize] = get_figure_text_objs (opts);
+  unwind_protect
+    for n = 1:numel(h)
+      set (h(n), "fontsize", 2 * fontsize{n});
+    endfor
+    local_drawnow (sprintf ("postscript eps %s", gp_opts), epsfile, opts);
+  unwind_protect_cleanup
+    for n = 1:numel(h)
+      set (h(n), "fontsize", fontsize{n});
+    endfor
+  end_unwind_protect
+endfunction
+
+function local_drawnow (term, file, opts)
+  if (opts.use_color < 0)
+    mono = true;
+  else
+    mono = false;
+  endif
+  figure (opts.figure);
+  if (isempty (opts.debug_file) || ! opts.debug)
+    drawnow (term, file, mono);
+  else
+    drawnow (term, file, mono, opts.debug_file);
+  endif
+endfunction
+
+function f = font_spec (opts, varargin)
+  for n = 1:2:numel(varargin)
+    opts.(varargin{n}) = varargin{n+1};
+  endfor
+  f = "";
+  switch (opts.devopt)
+  case "cgm"
+    if (! isempty (opts.font) && ! isempty (opts.fontsize))
+      f = sprintf ("font ""%s,%d""", opts.font, opts.fontsize);
+    elseif (! isempty (opts.font))
+      f = sprintf ("font ""%s""", opts.font);
+    elseif (! isempty (opts.fontsize))
+      f = sprintf ("%d", opts.fontsize);
+    endif
+  case {"eps", "eps2", "epsc", "epsc2"}
+    ## Gnuplot renders fonts as half their specification, which
+    ## results in a tight spacing for the axes-labels and tick-labels.
+    ## Compensate for the half scale. This will produce the proper
+    ## spacing for the requested fontsize.
+    if (! isempty (opts.font) && ! isempty (opts.fontsize))
+      f = sprintf ("font ""%s,%d""", opts.font, 2 * opts.fontsize);
+    elseif (! isempty (opts.font))
+      f = sprintf ("font ""%s""", opts.font);
+    elseif (! isempty (opts.fontsize))
+      f = sprintf ("%d", 2 * opts.fontsize);
+    endif
+  case "svg"
+    if (! isempty (opts.font) && ! isempty (opts.fontsize))
+      fontsize = round (opts.fontsize * 0.75);
+      f = sprintf ("fname ""%s"" fsize %d", opts.font, fontsize);
+    elseif (! isempty (opts.font))
+      f = sprintf ("fname ""%s""", opts.font);
+    elseif (! isempty (opts.fontsize))
+      fontsize = round (opts.fontsize * 0.75);
+      f = sprintf ("%s fsize %d", f, fontsize);
+    endif
+  case "pdf"
+    if (! isempty (opts.font) && ! isempty (opts.fontsize))
+      f = sprintf ("font ""%s,%d""", opts.font, opts.fontsize);
+    elseif (! isempty (opts.font))
+      f = sprintf ("font ""%s""", opts.font);
+    elseif (! isempty (opts.fontsize))
+      f = sprintf ("fsize %d", f, opts.fontsize);
+    endif
+  case {"pdfcairo", "pngcairo"}
+    if (! isempty (opts.font))
+      f = sprintf ("font ""%s""", opts.font);
+    endif
+  case {"epslatex", "epslatexstandalone"}
+    if (! isempty (opts.font) && ! isempty (opts.fontsize))
+      f = sprintf ("font ""%s,%d""", opts.font, opts.fontsize);
+    elseif (! isempty (opts.font))
+      f = sprintf ("font ""%s""", opts.font);
+    elseif (! isempty (opts.fontsize))
+      f = sprintf ("%d", opts.fontsize);
+    endif
+  case "pslatex"
+    if (! isempty (opts.fontsize))
+      f = sprintf ("%d", opts.fontsize);
+    endif
+  case {"gif", "jpeg", "png"}
+    if (! isempty (opts.font) && ! isempty (opts.fontsize))
+      f = sprintf ("font ""%s ,%d""", opts.font, opts.fontsize);
+    elseif (! isempty (opts.font))
+      f = sprintf ("font ""%s""", opts.font);
+    elseif (! isempty (opts.fontsize))
+      f = sprintf ("font ""%d""", opts.fontsize);
+    endif
+  case "emf"
+    if (! isempty (opts.font) && ! isempty (opts.fontsize))
+      f = sprintf ("""%s"" %d", opts.font, opts.fontsize);
+    elseif (! isempty (opts.font))
+      f = sprintf ("""%s""", opts.font);
+    elseif (! isempty (opts.fontsize))
+      f = sprintf ("%d", opts.fontsize);
+    endif
+  case "canvas"
+    if (! isempty (opts.fontsize))
+      f = sprintf ("fsize %d", opts.fontsize);
+    endif
+  case {"aifm", "corel"}
+    if (! isempty (opts.font) && ! isempty (opts.fontsize))
+      f = sprintf ("%s %d", opts.font, opts.fontsize);
+    elseif (! isempty (opts.font))
+      f = sprintf ("%s", opts.font);
+    elseif (! isempty (opts.fontsize))
+      f = sprintf ("%d", opts.fontsize);
+    endif
+  case "fig"
+    if (! isempty (opts.font) && ! isempty (opts.fontsize))
+      f = sprintf ("font %s fontsize %d", opts.font, opts.fontsize);
+    elseif (! isempty (opts.font))
+      f = sprintf ("font %s", opts.font);
+    elseif (! isempty (opts.fontsize))
+      f = sprintf ("fontsize %d", opts.fontsize);
+    endif
+  endswitch
+endfunction
+
+function [h, fontsize] = get_figure_text_objs (opts)
+  h = findall (opts.figure, "-property", "fontsize");
+  fontsize = get (h, "fontsize");
+  switch (numel (fontsize))
+  case 0
+    fontsize = {};
+  case 1
+    fontsize = {fontsize};
+  endswitch
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/private/__gnuplot_version__.m	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,51 @@
+## Copyright (C) 2006-2011 Daniel Sebald
+##
+## 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 3 of the License, 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, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {@var{version} =} __gnuplot_version__ ()
+## Undocumented internal function.
+## @end deftypefn
+
+## Return the version of gnuplot we are using.  Note that we do not
+## attempt to handle the case of the user switching to different
+## versions of gnuplot during the same session.
+
+function version = __gnuplot_version__ ()
+
+  persistent __version__ = "";
+
+  if (isempty (__version__))
+    [status, output] = system (sprintf ("\"%s\" --version", gnuplot_binary ()));
+    if (status != 0)
+      ## This message ends in a newline so that the traceback messages
+      ## are skipped and people might actually see the message, read it,
+      ## comprehend it, actually take the advice it gives, and stop
+      ## asking us why plotting fails when gnuplot is not found.
+      error ("you must have gnuplot installed to display graphics; if you have gnuplot installed in a non-standard location, see the 'gnuplot_binary' function\n");
+    endif
+    output = strrep (output, "gnuplot", "");
+    output = strrep (output, "patchlevel", ".");
+    output = strrep (output, "\n", "");
+    output = strrep (output, "\r", "");
+    __version__ = strrep (output, " ", "");
+  endif
+
+  version = __version__;
+
+endfunction
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/private/__go_draw_axes__.m	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,2577 @@
+## Copyright (C) 2005-2011 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 3 of the License, 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, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {} __go_draw_axes__ (@var{h}, @var{plot_stream}, @var{enhanced}, @var{mono})
+## Undocumented internal function.
+## @end deftypefn
+
+## Author: jwe
+
+function __go_draw_axes__ (h, plot_stream, enhanced, mono,
+                           bg_is_set, fg_is_set, hlgnd)
+
+  if (nargin >= 4 && nargin <= 7)
+
+    showhiddenhandles = get (0, "showhiddenhandles");
+    unwind_protect
+      set (0, "showhiddenhandles", "on");
+      axis_obj = __get__ (h);
+    unwind_protect_cleanup
+      set (0, "showhiddenhandles", showhiddenhandles);
+    end_unwind_protect
+
+    parent_figure_obj = get (axis_obj.parent);
+    gnuplot_term = __gnuplot_get_var__ (axis_obj.parent, "GPVAL_TERM");
+
+    ## Set to false for plotyy axes.
+    if (strcmp (axis_obj.tag, "plotyy"))
+      ymirror = false;
+    else
+      ymirror = true;
+    endif
+
+    nd = __calc_dimensions__ (h);
+
+    if (strcmp (axis_obj.dataaspectratiomode, "manual")
+        && strcmp (axis_obj.xlimmode, "manual")
+        && strcmp (axis_obj.ylimmode, "manual"))
+      ## All can't be "manual"
+      axis_obj.plotboxaspectratiomode = "auto";
+    endif
+
+    if (strcmp (axis_obj.dataaspectratiomode, "manual")
+        && strcmp (axis_obj.xlimmode, "manual")
+        && strcmp (axis_obj.ylimmode, "manual")
+        && (nd == 2 || all (mod (axis_obj.view, 90) == 0)))
+      ## FIXME - adjust plotboxaspectratio to respect other
+      fpos = get (axis_obj.parent, "position");
+      apos = axis_obj.position;
+    endif
+
+    pos = __actual_axis_position__ (h);
+
+    if (strcmpi (axis_obj.dataaspectratiomode, "manual"))
+      dr = axis_obj.dataaspectratio;
+      if (nd == 2 || all (mod (axis_obj.view, 90) == 0))
+        dr = dr(1) / dr(2);
+      else
+        ## FIXME - need to properly implement 3D
+        dr = mean (dr(1:2)) / dr(3);
+      endif
+    else
+      dr = 1;
+    endif
+
+    if (strcmp (axis_obj.activepositionproperty, "position"))
+      if (__gnuplot_has_feature__ ("screen_coordinates_for_{lrtb}margin"))
+        if (nd == 2 || all (mod (axis_obj.view, 90) == 0))
+          x = [1, 1];
+        else
+          ## 3D plots need to be sized down to fit in the window.
+          x = 1.0 ./ sqrt([2, 2.5]);
+        endif
+        fprintf (plot_stream, "set tmargin screen %.15g;\n",
+                 pos(2)+pos(4)/2+x(2)*pos(4)/2);
+        fprintf (plot_stream, "set bmargin screen %.15g;\n",
+                 pos(2)+pos(4)/2-x(2)*pos(4)/2);
+        fprintf (plot_stream, "set lmargin screen %.15g;\n",
+                 pos(1)+pos(3)/2-x(1)*pos(3)/2);
+        fprintf (plot_stream, "set rmargin screen %.15g;\n",
+                 pos(1)+pos(3)/2+x(1)*pos(3)/2);
+        sz_str = "";
+      else
+        fprintf (plot_stream, "set tmargin 0;\n");
+        fprintf (plot_stream, "set bmargin 0;\n");
+        fprintf (plot_stream, "set lmargin 0;\n");
+        fprintf (plot_stream, "set rmargin 0;\n");
+
+        if (nd == 3 && all (axis_obj.view == [0, 90]))
+          ## FIXME -- Kludge to allow colorbar to be added to a pcolor() plot
+          pos(3:4) = pos(3:4) * 1.4;
+          pos(1:2) = pos(1:2) - pos(3:4) * 0.125;
+        endif
+
+        fprintf (plot_stream, "set origin %.15g, %.15g;\n", pos(1), pos(2));
+
+        if (strcmpi (axis_obj.dataaspectratiomode, "manual"))
+          sz_str = sprintf ("set size ratio %.15g", -dr);
+        else
+          sz_str = "set size noratio";
+        endif
+        sz_str = sprintf ("%s %.15g, %.15g;\n", sz_str, pos(3), pos(4));
+      endif
+    else ## activepositionproperty == outerposition
+      fprintf (plot_stream, "unset tmargin;\n");
+      fprintf (plot_stream, "unset bmargin;\n");
+      fprintf (plot_stream, "unset lmargin;\n");
+      fprintf (plot_stream, "unset rmargin;\n");
+      fprintf (plot_stream, "set origin %g, %g;\n", pos(1:2));
+      sz_str = "";
+      if (strcmpi (axis_obj.dataaspectratiomode, "manual"))
+        sz_str = sprintf ("ratio %g", -dr);
+      else
+        sz_str = "noratio";
+      endif
+      sz_str = sprintf ("set size %s %g, %g;\n", sz_str, pos(3:4));
+    endif
+    if (! isempty (sz_str))
+      fputs (plot_stream, sz_str);
+    endif
+
+    ## Reset all labels, axis-labels, tick-labels, and title
+    ## FIXME - We should have an function to initialize the axis.
+    ##         Presently, this is dispersed in this function.
+    fputs (plot_stream, "unset label;\n");
+    fputs (plot_stream, "unset xtics;\n");
+    fputs (plot_stream, "unset ytics;\n");
+    fputs (plot_stream, "unset ztics;\n");
+    fputs (plot_stream, "unset x2tics;\n");
+    fputs (plot_stream, "unset x2tics;\n");
+
+    if (! isempty (axis_obj.title))
+      t = get (axis_obj.title);
+      if (isempty (t.string))
+        fputs (plot_stream, "unset title;\n");
+      else
+        [tt, f, s] = __maybe_munge_text__ (enhanced, t, "string");
+        fontspec = create_fontspec (f, s, gnuplot_term);
+        fprintf (plot_stream, "set title \"%s\" %s %s;\n",
+                 undo_string_escapes (tt), fontspec,
+                 __do_enhanced_option__ (enhanced, t));
+      endif
+    endif
+
+    if (! isempty (axis_obj.xlabel))
+      t = get (axis_obj.xlabel);
+      angle = t.rotation;
+      colorspec = get_text_colorspec (axis_obj.xcolor, mono);
+      if (isempty (t.string))
+        fprintf (plot_stream, "unset xlabel;\n");
+        fprintf (plot_stream, "unset x2label;\n");
+      else
+        [tt, f, s] = __maybe_munge_text__ (enhanced, t, "string");
+        fontspec = create_fontspec (f, s, gnuplot_term);
+        if (strcmpi (axis_obj.xaxislocation, "top"))
+          fprintf (plot_stream, "set x2label \"%s\" %s %s %s",
+                   undo_string_escapes (tt), colorspec, fontspec,
+                   __do_enhanced_option__ (enhanced, t));
+        else
+          fprintf (plot_stream, "set xlabel \"%s\" %s %s %s",
+                   undo_string_escapes (tt), colorspec, fontspec,
+                   __do_enhanced_option__ (enhanced, t));
+        endif
+        fprintf (plot_stream, " rotate by %f;\n", angle);
+        if (strcmpi (axis_obj.xaxislocation, "top"))
+          fprintf (plot_stream, "unset xlabel;\n");
+        else
+          fprintf (plot_stream, "unset x2label;\n");
+        endif
+      endif
+    endif
+
+    if (! isempty (axis_obj.ylabel))
+      t = get (axis_obj.ylabel);
+      angle = t.rotation;
+      colorspec = get_text_colorspec (axis_obj.ycolor, mono);
+      if (isempty (t.string))
+        fprintf (plot_stream, "unset ylabel;\n");
+        fprintf (plot_stream, "unset y2label;\n");
+      else
+        [tt, f, s] = __maybe_munge_text__ (enhanced, t, "string");
+        fontspec = create_fontspec (f, s, gnuplot_term);
+        if (strcmpi (axis_obj.yaxislocation, "right"))
+          fprintf (plot_stream, "set y2label \"%s\" %s %s %s",
+                   undo_string_escapes (tt), colorspec, fontspec,
+                   __do_enhanced_option__ (enhanced, t));
+        else
+          fprintf (plot_stream, "set ylabel \"%s\" %s %s %s",
+                   undo_string_escapes (tt), colorspec, fontspec,
+                   __do_enhanced_option__ (enhanced, t));
+        endif
+        fprintf (plot_stream, " rotate by %f;\n", angle);
+        if (strcmpi (axis_obj.yaxislocation, "right"))
+          fprintf (plot_stream, "unset ylabel;\n");
+        else
+          fprintf (plot_stream, "unset y2label;\n");
+        endif
+      endif
+    endif
+
+    if (! isempty (axis_obj.zlabel))
+      t = get (axis_obj.zlabel);
+      angle = t.rotation;
+      colorspec = get_text_colorspec (axis_obj.zcolor, mono);
+      if (isempty (t.string))
+        fputs (plot_stream, "unset zlabel;\n");
+      else
+        [tt, f, s] = __maybe_munge_text__ (enhanced, t, "string");
+        fontspec = create_fontspec (f, s, gnuplot_term);
+        fprintf (plot_stream, "set zlabel \"%s\" %s %s %s",
+                 undo_string_escapes (tt), colorspec, fontspec,
+                 __do_enhanced_option__ (enhanced, t));
+        fprintf (plot_stream, " rotate by %f;\n", angle);
+      endif
+    endif
+
+    if (strcmpi (axis_obj.xaxislocation, "top"))
+      xaxisloc = "x2";
+      xaxisloc_using = "x2";
+    else
+      xaxisloc = "x";
+      xaxisloc_using = "x1";
+      if (strcmpi (axis_obj.xaxislocation, "zero"))
+        fputs (plot_stream, "set xzeroaxis;\n");
+      endif
+    endif
+    if (strcmpi (axis_obj.yaxislocation, "right"))
+      yaxisloc = "y2";
+      yaxisloc_using = "y2";
+    else
+      yaxisloc = "y";
+      yaxisloc_using = "y1";
+      if (strcmpi (axis_obj.yaxislocation, "zero"))
+        fputs (plot_stream, "set yzeroaxis;\n");
+      endif
+    endif
+
+    have_grid = false;
+
+    if (strcmpi (axis_obj.xgrid, "on"))
+      have_grid = true;
+      fprintf (plot_stream, "set grid %stics;\n", xaxisloc);
+    else
+      fprintf (plot_stream, "set grid no%stics;\n", xaxisloc);
+    endif
+
+    if (strcmpi (axis_obj.ygrid, "on"))
+      have_grid = true;
+      fprintf (plot_stream, "set grid %stics;\n", yaxisloc);
+    else
+      fprintf (plot_stream, "set grid no%stics;\n", yaxisloc);
+    endif
+
+    if (strcmpi (axis_obj.zgrid, "on"))
+      have_grid = true;
+      fputs (plot_stream, "set grid ztics;\n");
+    else
+      fputs (plot_stream, "set grid noztics;\n");
+    endif
+
+    if (strcmpi (axis_obj.xminorgrid, "on"))
+      have_grid = true;
+      if (strcmp (axis_obj.xscale, "log"))
+        m = 10;
+      else
+        m = 5;
+      endif
+      fprintf (plot_stream, "set m%stics %d;\n", xaxisloc, m);
+      fprintf (plot_stream, "set grid m%stics;\n", xaxisloc);
+    else
+      fprintf (plot_stream, "set grid nom%stics;\n", xaxisloc);
+    endif
+
+    if (strcmpi (axis_obj.yminorgrid, "on"))
+      have_grid = true;
+      if (strcmp (axis_obj.yscale, "log"))
+        m = 10;
+      else
+        m = 5;
+      endif
+      fprintf (plot_stream, "set m%stics %d;\n", yaxisloc, m);
+      fprintf (plot_stream, "set grid m%stics;\n", yaxisloc);
+    else
+      fprintf (plot_stream, "set grid nom%stics;\n", yaxisloc);
+    endif
+
+    if (strcmpi (axis_obj.zminorgrid, "on"))
+      have_grid = true;
+      if (strcmp (axis_obj.zscale, "log"))
+        m = 10;
+      else
+        m = 5;
+      endif
+      fprintf (plot_stream, "set mztics %d;\n", m);
+      fputs (plot_stream, "set grid mztics;\n");
+    else
+      fputs (plot_stream, "set grid nomztics;\n");
+    endif
+
+    ## The grid front/back/layerdefault option also controls the
+    ## appearance of tics, so it is used even if the grid is absent.
+    if (strcmpi (axis_obj.layer, "top"))
+      fputs (plot_stream, "set grid front;\n");
+      fputs (plot_stream, "set border front;\n");
+    else
+      fputs (plot_stream, "set grid layerdefault;\n");
+      ## FIXME -- the gnuplot help says that "layerdefault" should work
+      ## for set border too, but it fails for me with gnuplot 4.2.5.  So
+      ## use "back" instead.
+      fputs (plot_stream, "set border back;\n");
+    endif
+
+    fprintf (plot_stream, "set grid linewidth %f, linewidth %f;\n",
+             axis_obj.linewidth, axis_obj.linewidth);
+
+    if (! have_grid)
+      fputs (plot_stream, "unset grid;\n");
+    endif
+
+    xlogscale = strcmpi (axis_obj.xscale, "log");
+    ylogscale = strcmpi (axis_obj.yscale, "log");
+    zlogscale = strcmpi (axis_obj.zscale, "log");
+
+    ## Detect logscale and negative lims
+    if (xlogscale && all (axis_obj.xlim < 0))
+      xsgn = -1;
+      if (strcmp (axis_obj.xdir, "reverse"))
+        axis_obj.xdir = "normal";
+      else
+        axis_obj.xdir = "reverse";
+      endif
+      axis_obj.xtick = -flip (axis_obj.xtick);
+      axis_obj.xticklabel = flip (axis_obj.xticklabel);
+      axis_obj.xticklabelmode = "manual";
+      axis_obj.xlim = -flip (axis_obj.xlim);
+    else
+      xsgn = 1;
+    endif
+    if (ylogscale && all (axis_obj.ylim < 0))
+      ysgn = -1;
+      if (strcmp (axis_obj.ydir, "reverse"))
+        axis_obj.ydir = "normal";
+      else
+        axis_obj.ydir = "reverse";
+      endif
+      axis_obj.ytick = -flip (axis_obj.ytick);
+      axis_obj.yticklabel = flip (axis_obj.yticklabel);
+      axis_obj.yticklabelmode = "manual";
+      axis_obj.ylim = -flip (axis_obj.ylim);
+    else
+      ysgn = 1;
+    endif
+    if (zlogscale && all (axis_obj.zlim < 0))
+      zsgn = -1;
+      if (strcmp (axis_obj.zdir, "reverse"))
+        axis_obj.zdir = "normal";
+      else
+        axis_obj.zdir = "reverse";
+      endif
+      axis_obj.ztick = -flip (axis_obj.ztick);
+      axis_obj.zticklabel = flip (axis_obj.zticklabel);
+      axis_obj.zticklabelmode = "manual";
+      axis_obj.zlim = -flip (axis_obj.zlim);
+    else
+      zsgn = 1;
+    endif
+
+    if (ylogscale && false)
+      disp ('yscale is "log"')
+      ylim = axis_obj.ylim
+      ytick = axis_obj.ytick
+      yticklabel = axis_obj.yticklabel
+      yticklabelmode = axis_obj.yticklabelmode
+    end
+
+    xlim = axis_obj.xlim;
+    ylim = axis_obj.ylim;
+    zlim = axis_obj.zlim;
+    clim = axis_obj.clim;
+
+    do_tics (axis_obj, plot_stream, ymirror, mono, gnuplot_term);
+
+    fputs (plot_stream, "unset logscale;\n");
+    if (xlogscale)
+      fprintf (plot_stream, "set logscale %s;\n", xaxisloc);
+    endif
+    if (ylogscale)
+      fprintf (plot_stream, "set logscale %s;\n", yaxisloc);
+    endif
+    if (zlogscale)
+      fputs (plot_stream, "set logscale z;\n");
+    endif
+
+    xautoscale = strcmpi (axis_obj.xlimmode, "auto");
+    yautoscale = strcmpi (axis_obj.ylimmode, "auto");
+    zautoscale = strcmpi (axis_obj.zlimmode, "auto");
+    cautoscale = strcmpi (axis_obj.climmode, "auto");
+    cdatadirect = false;
+    truecolor = false;
+
+    fputs (plot_stream, "set clip two;\n");
+
+    kids = axis_obj.children;
+    ## Remove the axis labels and title from the children, and
+    ## preserved the original order.
+    [jnk, k] = setdiff (kids, [axis_obj.xlabel; axis_obj.ylabel; ...
+                               axis_obj.zlabel; axis_obj.title]);
+    kids = kids (sort (k));
+
+    if (nd == 3)
+      fputs (plot_stream, "set parametric;\n");
+      fputs (plot_stream, "set style data lines;\n");
+      fputs (plot_stream, "set surface;\n");
+      fputs (plot_stream, "unset contour;\n");
+    endif
+
+    data_idx = 0;
+    data = cell ();
+    is_image_data = [];
+    hidden_removal = NaN;
+    view_map = false;
+
+    if (! cautoscale && clim(1) == clim(2))
+      clim(2)++;
+    endif
+    addedcmap = [];
+
+    ximg_data = {};
+    ximg_data_idx = 0;
+
+    while (! isempty (kids))
+
+      obj = get (kids(end));
+      if (isfield (obj, "units"))
+        units = obj.units;
+        unwind_protect
+          set (kids(end), "units", "data");
+          obj = get (kids(end));
+        unwind_protect_cleanup
+          set (kids(end), "units", units);
+        end_unwind_protect
+      endif
+      kids = kids(1:(end-1));
+
+      if (strcmpi (obj.visible, "off"))
+        continue;
+      endif
+
+      if (xlogscale && isfield (obj, "xdata"))
+        obj.xdata = xsgn * obj.xdata;
+        obj.xdata(obj.xdata<=0) = NaN;
+      endif
+      if (ylogscale && isfield (obj, "ydata"))
+        obj.ydata = ysgn * obj.ydata;
+        obj.ydata(obj.ydata<=0) = NaN;
+      endif
+      if (zlogscale && isfield (obj, "zdata"))
+        obj.zdata = zsgn * obj.zdata;
+        obj.zdata(obj.zdata<=0) = NaN;
+      endif
+
+      ## Check for facecolor interpolation for surfaces.
+      doing_interp_color = ...
+         isfield (obj, "facecolor") && strncmp (obj.facecolor, "interp", 6);
+
+      switch (obj.type)
+        case "image"
+          img_data = obj.cdata;
+          img_xdata = obj.xdata;
+          img_ydata = obj.ydata;
+
+          if (ndims (img_data) == 3)
+            truecolor = true;
+          elseif (strcmpi (obj.cdatamapping, "direct"))
+            cdatadirect = true;
+          endif
+          data_idx++;
+          is_image_data(data_idx) = true;
+          parametric(data_idx) = false;
+          have_cdata(data_idx) = false;
+          have_3d_patch(data_idx) = false;
+
+          if (img_xdata(2) < img_xdata(1))
+            img_xdata = img_xdata(2:-1:1);
+            img_data = img_data(:,end:-1:1,:);
+          elseif (img_xdata(1) == img_xdata(2))
+            img_xdata = img_xdata(1) + [0, size(img_data,2)-1];
+          endif
+          if (img_ydata(2) < img_ydata(1))
+            img_ydata = img_ydata(2:-1:1);
+            img_data = img_data(end:-1:1,:,:);
+          elseif (img_ydata(1) == img_ydata(2))
+            img_ydata = img_ydata(1) + [0, size(img_data,1)-1];
+          endif
+
+          [y_dim, x_dim] = size (img_data(:,:,1));
+          if (x_dim > 1)
+            dx = abs (img_xdata(2)-img_xdata(1))/(x_dim-1);
+          else
+            x_dim = 2;
+            img_data = [img_data, img_data];
+            dx = abs (img_xdata(2)-img_xdata(1));
+          endif
+          if (y_dim > 1)
+            dy = abs (img_ydata(2)-img_ydata(1))/(y_dim-1);
+          else
+            y_dim = 2;
+            img_data = [img_data; img_data];
+            dy = abs (img_ydata(2)-img_ydata(1));
+          endif
+
+          x_origin = min (img_xdata);
+          y_origin = min (img_ydata);
+
+          if (ndims (img_data) == 3)
+            data{data_idx} = permute (img_data, [3, 1, 2])(:);
+            format = "1:2:3";
+            imagetype = "rgbimage";
+          else
+            data{data_idx} = img_data(:);
+            format = "1";
+            imagetype = "image";
+          endif
+
+          titlespec{data_idx} = "title \"\"";
+          usingclause{data_idx} = sprintf ("binary array=%dx%d scan=yx origin=(%.15g,%.15g) dx=%.15g dy=%.15g using %s",
+              x_dim, y_dim, x_origin, y_origin, dx, dy, format);
+          withclause{data_idx} = sprintf ("with %s;", imagetype);
+
+        case "line"
+          if (strncmp (obj.linestyle, "none", 4)
+              && (! isfield (obj, "marker")
+                  || (isfield (obj, "marker")
+                      && strncmp (obj.marker, "none", 4))))
+            continue;
+          endif
+          data_idx++;
+          is_image_data(data_idx) = false;
+          parametric(data_idx) = true;
+          have_cdata(data_idx) = false;
+          have_3d_patch(data_idx) = false;
+          if (isempty (obj.displayname))
+            titlespec{data_idx} = "title \"\"";
+          else
+            tmp = undo_string_escapes (__maybe_munge_text__ (enhanced, obj, "displayname"));
+            titlespec{data_idx} = cstrcat ("title \"", tmp, "\"");
+          endif
+          usingclause{data_idx} = sprintf ("record=%d", numel (obj.xdata));
+          errbars = "";
+          if (nd == 3)
+            xdat = obj.xdata(:);
+            ydat = obj.ydata(:);
+            if (! isempty (obj.zdata))
+              zdat = obj.zdata(:);
+            else
+              zdat = zeros (size (xdat));
+            endif
+            data{data_idx} = [xdat, ydat, zdat]';
+            usingclause{data_idx} = sprintf ("record=%d using ($1):($2):($3)", numel (xdat));
+            ## fputs (plot_stream, "set parametric;\n");
+          else
+            xdat = obj.xdata(:);
+            ydat = obj.ydata(:);
+            data{data_idx} = [xdat, ydat]';
+            usingclause{data_idx} = sprintf ("record=%d using ($1):($2) axes %s%s",
+                                            rows(xdat), xaxisloc_using, yaxisloc_using);
+          endif
+
+          style = do_linestyle_command (obj, obj.color, data_idx, mono,
+                                        plot_stream, errbars);
+
+          withclause{data_idx} = sprintf ("with %s linestyle %d",
+                                          style{1}, data_idx);
+
+          if (length (style) > 1)
+            data_idx++;
+            is_image_data(data_idx) = is_image_data(data_idx - 1);
+            parametric(data_idx) = parametric(data_idx - 1);
+            have_cdata(data_idx) = have_cdata(data_idx - 1);
+            have_3d_patch(data_idx) = have_3d_patch(data_idx - 1);
+            titlespec{data_idx} = "title \"\"";
+            usingclause{data_idx} = usingclause{data_idx - 1};
+            data{data_idx} = data{data_idx - 1};
+            withclause{data_idx} = sprintf ("with %s linestyle %d",
+                                          style{2}, data_idx);
+          endif
+          if (length (style) > 2)
+            data_idx++;
+            is_image_data(data_idx) = is_image_data(data_idx - 1);
+            parametric(data_idx) = parametric(data_idx - 1);
+            have_cdata(data_idx) = have_cdata(data_idx - 1);
+            have_3d_patch(data_idx) = have_3d_patch(data_idx - 1);
+            titlespec{data_idx} = "title \"\"";
+            usingclause{data_idx} = usingclause{data_idx - 1};
+            data{data_idx} = data{data_idx - 1};
+            withclause{data_idx} = sprintf ("with %s linestyle %d",
+                                          style{3}, data_idx);
+          endif
+
+       case "patch"
+         cmap = parent_figure_obj.colormap;
+         [nr, nc] = size (obj.xdata);
+
+         if (! isempty (obj.cdata))
+           cdat = obj.cdata;
+           if (strcmpi (obj.cdatamapping, "direct"))
+             cdatadirect = true;
+           endif
+         else
+           cdat = [];
+         endif
+
+         data_3d_idx = NaN;
+         for i = 1:nc
+           xcol = obj.xdata(:,i);
+           ycol = obj.ydata(:,i);
+           if (nd == 3)
+             if (! isempty (obj.zdata))
+               zcol = obj.zdata(:,i);
+             else
+               zcol = zeros (size (xcol));
+             endif
+           endif
+
+           if (! isnan (xcol) && ! isnan (ycol))
+             ## Is the patch closed or not
+             if (strncmp (obj.facecolor, "none", 4))
+               hidden_removal = false;
+             else
+
+               if (isnan (hidden_removal))
+                 hidden_removal = true;
+               endif
+               if (nd == 3)
+                 if (numel (xcol) > 3)
+                   error ("__go_draw_axes__: gnuplot (as of v4.2) only supports 3D filled triangular patches");
+                 else
+                   if (isnan (data_3d_idx))
+                     data_idx++;
+                     data_3d_idx = data_idx;
+                     is_image_data(data_idx) = false;
+                     parametric(data_idx) = false;
+                     have_cdata(data_idx) = true;
+                     have_3d_patch(data_idx) = true;
+                     withclause{data_3d_idx} = sprintf ("with pm3d");
+                     usingclause{data_3d_idx} =  "using 1:2:3:4";
+                     data{data_3d_idx} = [];
+                   endif
+                   local_idx = data_3d_idx;
+                   ccdat = NaN;
+                 endif
+               else
+                 data_idx++;
+                 local_idx = data_idx;
+                 is_image_data(data_idx) = false;
+                 parametric(data_idx) = false;
+                 have_cdata(data_idx) = false;
+                 have_3d_patch(data_idx) = false;
+               endif
+
+               if (i > 1 || isempty (obj.displayname))
+                 titlespec{local_idx} = "title \"\"";
+               else
+                 tmp = undo_string_escapes (__maybe_munge_text__ (enhanced, obj, "displayname"));
+                 titlespec{local_idx} = cstrcat ("title \"", tmp, "\"");
+               endif
+               if (isfield (obj, "facecolor"))
+                 if ((strncmp (obj.facecolor, "flat", 4)
+                     || strncmp (obj.facecolor, "interp", 6))
+                     && isfield (obj, "cdata"))
+                   if (ndims (obj.cdata) == 2
+                       && (size (obj.cdata, 2) == nc
+                           && (size (obj.cdata, 1) == 1
+                               || size (obj.cdata, 1) == 3)))
+                     ccol = cdat (:, i);
+                   elseif (ndims (obj.cdata) == 2
+                       && (size (obj.cdata, 1) == nc
+                           && (size (obj.cdata, 2) == 1
+                               || size (obj.cdata, 2) == 3)))
+                     ccol = cdat (i, :);
+                   elseif (ndims (obj.cdata) == 3)
+                     ccol = permute (cdat (:, i, :), [1, 3, 2]);
+                   else
+                     ccol = cdat;
+                   endif
+                   if (strncmp (obj.facecolor, "flat", 4))
+                     if (numel(ccol) == 3)
+                       color = ccol;
+                     elseif (nd == 3 && numel (xcol) == 3)
+                       ccdat = ccol * ones (3,1);
+                     else
+                       r = 1 + round ((size (cmap, 1) - 1)
+                                      * (ccol - clim(1))/(clim(2) - clim(1)));
+                       r = max (1, min (r, size (cmap, 1)));
+                       color = cmap(r, :);
+                     endif
+                   elseif (strncmp (obj.facecolor, "interp", 6))
+                     if (nd == 3 && numel (xcol) == 3)
+                       ccdat = ccol;
+                       if (! isvector (ccdat))
+                         tmp = rows(cmap) + rows(addedcmap) + ...
+                              [1 : rows(ccdat)];
+                         addedcmap = [addedcmap; ccdat];
+                         ccdat = tmp(:);
+                       else
+                         ccdat = ccdat(:);
+                       endif
+                     else
+                       warning ("\"interp\" not supported, using 1st entry of cdata");
+                       r = 1 + round ((size (cmap, 1) - 1) * ccol(1));
+                       r = max (1, min (r, size (cmap, 1)));
+                       color = cmap(r,:);
+                     endif
+                   endif
+                 elseif (isnumeric (obj.facecolor))
+                   color = obj.facecolor;
+                 else
+                   color = [0, 1, 0];
+                 endif
+               else
+                 color = [0, 1, 0];
+               endif
+
+               if (nd == 3 && numel (xcol) == 3)
+                 if (isnan (ccdat))
+                   ccdat = (rows (cmap) + rows(addedcmap) + 1) * ones(3, 1);
+                   addedcmap = [addedcmap; reshape(color, 1, 3)];
+                 endif
+                 data{data_3d_idx} = [data{data_3d_idx}, ...
+                                      [[xcol; xcol(end)], [ycol; ycol(end)], ...
+                                      [zcol; zcol(end)], [ccdat; ccdat(end)]]'];
+               else
+                 if (mono)
+                   colorspec = "";
+                 elseif (__gnuplot_has_feature__ ("transparent_patches")
+                         && isscalar (obj.facealpha))
+                   colorspec = sprintf ("lc rgb \"#%02x%02x%02x\" fillstyle transparent solid %f",
+                                      round (255*color), obj.facealpha);
+                 else
+                   colorspec = sprintf ("lc rgb \"#%02x%02x%02x\"",
+                                        round (255*color));
+                 endif
+
+                 withclause{data_idx} = sprintf ("with filledcurve %s",
+                                               colorspec);
+                 data{data_idx} = [xcol, ycol]';
+                 usingclause{data_idx} = sprintf ("record=%d using ($1):($2)",
+                                                  numel (xcol));
+               endif
+             endif
+           endif
+
+           ## patch outline
+           if (!(strncmp (obj.edgecolor, "none", 4)
+                  && (strncmp (obj.marker, "none", 4)
+                      || (strncmp (obj.markeredgecolor, "none", 4)
+                          && strncmp (obj.markerfacecolor, "none", 4)))))
+
+             data_idx++;
+             is_image_data(data_idx) = false;
+             parametric(data_idx) = false;
+             have_cdata(data_idx) = false;
+             have_3d_patch(data_idx) = false;
+             titlespec{data_idx} = "title \"\"";
+             usingclause{data_idx} = sprintf ("record=%d", numel (obj.xdata));
+
+             if (isfield (obj, "markersize"))
+               mdat = obj.markersize / 3;
+             endif
+
+             if (isfield (obj, "edgecolor"))
+               ## FIXME
+               ## This is the wrong thing to do as edgecolor, markeredgecolor
+               ## and markerfacecolor can have different values and we should
+               ## treat them seperately. However, the below allow the scatter
+               ## functions to work as expected, where only one of these values
+               ## is set
+               if (strncmp (obj.edgecolor, "none", 4))
+                 if (strncmp (obj.markeredgecolor, "none", 4))
+                   ec = obj.markerfacecolor;
+                 else
+                   ec = obj.markeredgecolor;
+                 endif
+               else
+                 ec = obj.edgecolor;
+               endif
+
+               if ((strncmp (ec, "flat", 4)
+                    || strncmp (ec, "interp", 6))
+                   && isfield (obj, "cdata"))
+                 if (ndims (obj.cdata) == 2
+                     && (size (obj.cdata, 2) == nc
+                         && (size (obj.cdata, 1) == 1
+                             || size (obj.cdata, 1) == 3)))
+                   ccol = cdat (:, i);
+                 elseif (ndims (obj.cdata) == 2
+                         && (size (obj.cdata, 1) == nc
+                             && (size (obj.cdata, 2) == 1
+                                 || size (obj.cdata, 2) == 3)))
+                   ccol = cdat (i, :);
+                 elseif (ndims (obj.cdata) == 3)
+                   ccol = permute (cdat (:, i, :), [1, 3, 2]);
+                 else
+                   ccol = cdat;
+                 endif
+                 if (strncmp (ec, "flat", 4))
+                   if (numel(ccol) == 3)
+                     color = ccol;
+                   else
+                     if (isscalar (ccol))
+                       ccol = repmat(ccol, numel (xcol), 1);
+                     endif
+                     color = "flat";
+                     have_cdata(data_idx) = true;
+                   endif
+                 elseif (strncmp (ec, "interp", 6))
+                   if (numel(ccol) == 3)
+                     warning ("\"interp\" not supported, using 1st entry of cdata");
+                     color = ccol(1,:);
+                   else
+                     if (isscalar (ccol))
+                       ccol = repmat(ccol, numel (xcol), 1);
+                     endif
+                     color = "interp";
+                     have_cdata(data_idx) = true;
+                   endif
+                 endif
+               elseif (isnumeric (ec))
+                 color = ec;
+               else
+                 color = [0, 0, 0];
+               endif
+             else
+               color = [0, 0, 0];
+             endif
+
+             if (isfield (obj, "linestyle"))
+               switch (obj.linestyle)
+                 case "-"
+                   lt = "lt 1";
+                 case "--"
+                   lt = "lt 2";
+                 case ":"
+                   lt = "lt 3";
+                 case "-."
+                   lt = "lt 6";
+                 case "none"
+                   lt = "";
+                 otherwise
+                   lt = "";
+               endswitch
+             else
+               lt = "";
+             endif
+
+             if (isfield (obj, "linewidth"))
+               lw = sprintf("linewidth %f", obj.linewidth);
+             else
+               lw  = "";
+             endif
+
+             [pt, pt2, obj] = gnuplot_pointtype (obj);
+             if (! isempty (pt))
+               pt = sprintf ("pointtype %s", pt);
+             endif
+             if (! isempty (pt2))
+               pt2 = sprintf ("pointtype %s", pt2);
+             endif
+
+             if (mono)
+               colorspec = "";
+             else
+               if (ischar (color))
+                 colorspec = "palette";
+               else
+                 colorspec = sprintf ("lc rgb \"#%02x%02x%02x\"",
+                                      round (255*color));
+               endif
+             endif
+
+             sidx = 1;
+             if (isempty (lt))
+               style = "";
+             else
+               style = "lines";
+             endif
+             tmpwith = {};
+
+             facesame = true;
+             if (! isequal (pt, pt2) && isfield (obj, "markerfacecolor")
+                 && !strncmp (obj.markerfacecolor, "none", 4))
+               if (strncmp (obj.markerfacecolor, "auto", 4)
+                   || ! isnumeric (obj.markerfacecolor)
+                   || (isnumeric (obj.markerfacecolor)
+                       && isequal (color, obj.markerfacecolor)))
+                 style = strcat (style, "points");
+                 if (isfield (obj, "markersize"))
+                   if (length (mdat) == nc)
+                     m = mdat(i);
+                   else
+                     m = mdat;
+                   endif
+                   ps = sprintf("pointsize %f", m / 3);
+                 else
+                   ps = "";
+                 endif
+
+                 tmpwith{sidx} = sprintf ("with %s %s %s %s %s %s",
+                                          style, lw, pt2, lt, ps,
+                                          colorspec);
+               else
+                 facesame = false;
+                 if (! isempty (style))
+                   tmpwith{sidx} = sprintf ("with %s %s %s %s",
+                                            style, lw, lt,
+                                            colorspec);
+                   sidx ++;
+                 endif
+                 if (isnumeric (obj.markerfacecolor) && ! mono)
+                   colorspec = sprintf ("lc rgb \"#%02x%02x%02x\"",
+                                        round (255*obj.markerfacecolor));
+                 endif
+                 style = "points";
+                 if (isfield (obj, "markersize"))
+                   if (length (mdat) == nc)
+                     m = mdat(i);
+                   else
+                     m = mdat;
+                   endif
+                   ps = sprintf("pointsize %f", m / 3);
+                 else
+                   ps = "";
+                 endif
+                 tmpwith{sidx} = sprintf ("with %s %s %s %s %s %s",
+                                          style, lw, pt2, lt, ps,
+                                          colorspec);
+               endif
+             endif
+
+             if (isfield (obj, "markeredgecolor")
+                 && !strncmp (obj.markeredgecolor, "none", 4))
+               if (facesame && !isempty (pt)
+                   && (strncmp (obj.markeredgecolor, "auto", 4)
+                       || ! isnumeric (obj.markeredgecolor)
+                       || (isnumeric (obj.markeredgecolor)
+                           && isequal (color, obj.markeredgecolor))))
+                 if (sidx == 1 && ((length (style) == 5
+                          && strncmp (style, "lines", 5))
+                         || isempty (style)))
+                   style = strcat (style, "points");
+                   if (isfield (obj, "markersize"))
+                     if (length (mdat) == nc)
+                       m = mdat(i);
+                     else
+                       m = mdat;
+                     endif
+                     ps = sprintf("pointsize %f", m / 3);
+                   else
+                     ps = "";
+                   endif
+                   tmpwith{sidx} = sprintf ("with %s %s %s %s %s %s",
+                                            style, lw, pt, lt, ps,
+                                            colorspec);
+                 endif
+               else
+                 if (!isempty (style))
+                   if (length(tmpwith) < sidx || isempty (tmpwith{sidx}))
+                     tmpwith{sidx} = sprintf ("with %s %s %s %s",
+                                              style, lw, lt,
+                                              colorspec);
+                   endif
+                   sidx ++;
+                 endif
+
+                 if (!isempty (pt))
+                   if (! mono)
+                     if (strncmp (obj.markeredgecolor, "auto", 4))
+                       colorspec = sprintf ("lc rgb \"#%02x%02x%02x\"",
+                                            round (255*color));
+                     elseif (isnumeric (obj.markeredgecolor) && ! mono)
+                       colorspec = sprintf ("lc rgb \"#%02x%02x%02x\"",
+                                            round (255*obj.markeredgecolor));
+                     endif
+                   endif
+                   style = "points";
+                   if (isfield (obj, "markersize"))
+                     if (length (mdat) == nc)
+                       m = mdat(i);
+                     else
+                       m = mdat;
+                     endif
+                     ps = sprintf("pointsize %f", m / 3);
+                   else
+                     ps = "";
+                   endif
+                   tmpwith{sidx} = sprintf ("with %s %s %s %s %s %s",
+                                            style, lw, pt, lt, ps,
+                                            colorspec);
+                 endif
+               endif
+             endif
+
+             if (isempty (tmpwith))
+               withclause{data_idx} = sprintf ("with %s %s %s %s %s",
+                                               style, lw, pt, lt,
+                                               colorspec);
+             else
+               withclause{data_idx} = tmpwith{1};
+             endif
+             if (nd == 3)
+               if (ischar (color))
+                 if (! isnan (xcol) && ! isnan (ycol) && ! isnan (zcol))
+                   data{data_idx} = [[xcol; xcol(1)], [ycol; ycol(1)], ...
+                                     [zcol; zcol(1)], [ccol; ccol(1)]]';
+                 else
+                   data{data_idx} = [xcol, ycol, zcol, ccol]';
+                 endif
+                 usingclause{data_idx} = sprintf ("record=%d using ($1):($2):($3):($4)", columns (data{data_idx}));
+               else
+                 if (! isnan (xcol) && ! isnan (ycol) && ! isnan (zcol))
+                   data{data_idx} = [[xcol; xcol(1)], [ycol; ycol(1)], ...
+                                     [zcol; zcol(1)]]';
+                 else
+                   data{data_idx} = [xcol, ycol, zcol]';
+                 endif
+                 usingclause{data_idx} = sprintf ("record=%d using ($1):($2):($3)", columns (data{data_idx}));
+               endif
+             else
+               if (ischar (color))
+                 if (! isnan (xcol) && ! isnan (ycol))
+                   data{data_idx} = [[xcol; xcol(1)], [ycol; ycol(1)], ...
+                                     [ccol; ccol(1)]]';
+                 else
+                   data{data_idx} = [xcol, ycol, ccol]';
+                 endif
+                 usingclause{data_idx} = sprintf ("record=%d using ($1):($2):($3)", columns (data{data_idx}));
+               else
+                 if (! isnan (xcol) && ! isnan (ycol))
+                   data{data_idx} = [[xcol; xcol(1)], [ycol; ycol(1)]]';
+                 else
+                   data{data_idx} = [xcol, ycol]';
+                 endif
+                 usingclause{data_idx} = sprintf ("record=%d using ($1):($2)", columns (data{data_idx}));
+               endif
+             endif
+
+             if (length (tmpwith) > 1)
+               data_idx++;
+               is_image_data(data_idx) = is_image_data(data_idx - 1);
+               parametric(data_idx) = parametric(data_idx - 1);
+               have_cdata(data_idx) = have_cdata(data_idx - 1);
+               have_3d_patch(data_idx) = have_3d_patch(data_idx - 1);
+               titlespec{data_idx} = "title \"\"";
+               usingclause{data_idx} = usingclause{data_idx - 1};
+               data{data_idx} = data{data_idx - 1};
+               withclause{data_idx} = tmpwith{2};
+             endif
+             if (length (tmpwith) > 2)
+               data_idx++;
+               is_image_data(data_idx) = is_image_data(data_idx - 1);
+               parametric(data_idx) = parametric(data_idx - 1);
+               have_cdata(data_idx) = have_cdata(data_idx - 1);
+               have_3d_patch(data_idx) = have_3d_patch(data_idx - 1);
+               titlespec{data_idx} = "title \"\"";
+               usingclause{data_idx} = usingclause{data_idx - 1};
+               data{data_idx} = data{data_idx - 1};
+               withclause{data_idx} = tmpwith{3};
+             endif
+           endif
+         endfor
+
+        case "surface"
+          view_map = true;
+          if (! (strncmp (obj.edgecolor, "none", 4)
+                 && strncmp (obj.facecolor, "none", 4)))
+            data_idx++;
+            is_image_data(data_idx) = false;
+            parametric(data_idx) = false;
+            have_cdata(data_idx) = true;
+            have_3d_patch(data_idx) = false;
+            style = do_linestyle_command (obj, obj.edgecolor,
+                                          data_idx, mono,
+                                          plot_stream);
+
+            if (isempty (obj.displayname))
+              titlespec{data_idx} = "title \"\"";
+            else
+              tmp = undo_string_escapes (__maybe_munge_text__ (enhanced, obj, "displayname"));
+              titlespec{data_idx} = cstrcat ("title \"", tmp, "\"");
+            endif
+            withclause{data_idx} = sprintf ("with pm3d linestyle %d",
+                                            data_idx);
+            withpm3d = true;
+            pm3didx = data_idx;
+
+            xdat = obj.xdata;
+            ydat = obj.ydata;
+            zdat = obj.zdata;
+            cdat = obj.cdata;
+
+            err = false;
+            if (! size_equal(zdat, cdat))
+              err = true;
+            endif
+            if (isvector (xdat) && isvector (ydat) && ismatrix (zdat))
+              if (rows (zdat) == length (ydat)
+                  && columns (zdat) == length (xdat))
+                [xdat, ydat] = meshgrid (xdat, ydat);
+              else
+                err = true;
+              endif
+            elseif (ismatrix (xdat) && ismatrix (ydat) && ismatrix (zdat))
+              if (! size_equal (xdat, ydat, zdat))
+                err = true;
+              endif
+            else
+              err = true;
+            endif
+            if (err)
+              error ("__go_draw_axes__: invalid grid data");
+            endif
+            xlen = columns (zdat);
+            ylen = rows (zdat);
+            if (xlen == columns (xdat) && xlen == columns (ydat)
+                && ylen == rows (xdat) && ylen == rows (ydat))
+              len = 4 * xlen;
+              zz = zeros (ylen, len);
+              k = 1;
+              for kk = 1:4:len
+                zz(:,kk)   = xdat(:,k);
+                zz(:,kk+1) = ydat(:,k);
+                zz(:,kk+2) = zdat(:,k);
+                zz(:,kk+3) = cdat(:,k);
+                k++;
+              endfor
+              data{data_idx} = zz.';
+            endif
+
+            if (doing_interp_color)
+              interp_str = "interpolate 0, 0";
+            else
+              ## No interpolation of facecolors.
+              interp_str = "";
+            endif
+            usingclause{data_idx} = sprintf ("record=%dx%d using ($1):($2):($3):($4)", ylen, xlen);
+
+            flat_interp_face = (strncmp (obj.facecolor, "flat", 4)
+                                || strncmp (obj.facecolor, "interp", 6));
+            flat_interp_edge = (strncmp (obj.edgecolor, "flat", 4)
+                                || strncmp (obj.edgecolor, "interp", 6));
+
+            facecolor_none_or_white = (strncmp (obj.facecolor, "none", 4)
+                                       || (isnumeric (obj.facecolor)
+                                           && all (obj.facecolor == 1)));
+            hidden_removal = false;
+            fputs (plot_stream, "set style increment default;\n");
+            if (flat_interp_edge && facecolor_none_or_white)
+              withpm3d = false;
+              withclause{data_idx} = sprintf ("with %s palette", style {1});
+              fputs (plot_stream, "unset pm3d\n");
+              if (all (obj.facecolor == 1))
+                hidden_removal = true;
+              endif
+            elseif (facecolor_none_or_white)
+              if (all (obj.facecolor == 1))
+                hidden_removal = true;
+              endif
+              fputs(plot_stream,"unset pm3d;\n");
+              fputs(plot_stream,"set style increment user;\n");
+              withpm3d = false;
+              withclause{data_idx} = sprintf("with %s linestyle %d",
+                                             style{1}, data_idx);
+              fputs (plot_stream, "unset pm3d\n");
+            endif
+
+            if (doing_interp_color)
+              ## "depthorder" interferes with interpolation of colors.
+              dord = "scansautomatic";
+            else
+              dord = "depthorder";
+            endif
+
+            if (flat_interp_face && strncmp (obj.edgecolor, "flat", 4))
+              fprintf (plot_stream, "set pm3d explicit at s %s %s corners2color c3;\n",
+                       interp_str, dord);
+            elseif (!facecolor_none_or_white)
+              if (strncmp (obj.edgecolor, "none", 4))
+                if (__gnuplot_has_feature__ ("transparent_surface")
+                    && isscalar (obj.facealpha))
+                  fprintf (plot_stream,
+                           "set style fill transparent solid %f;\n",
+                           obj.facealpha);
+                endif
+                fprintf (plot_stream, "set pm3d explicit at s %s corners2color c3;\n",
+                         interp_str, dord);
+              else
+                fprintf (plot_stream, "set pm3d explicit at s hidden3d %d %s %s corners2color c3;\n",
+                         data_idx, interp_str, dord);
+
+                if (__gnuplot_has_feature__ ("transparent_surface")
+                    && isscalar (obj.facealpha))
+                  fprintf (plot_stream,
+                           "set style fill transparent solid %f;\n",
+                           obj.facealpha);
+                endif
+              endif
+            endif
+
+            zz = [];
+            if (length (style) > 1)
+              len = 3 * xlen;
+              zz = zeros (ylen, len);
+              k = 1;
+              for kk = 1:3:len
+                zz(:,kk)   = xdat(:,k);
+                zz(:,kk+1) = ydat(:,k);
+                zz(:,kk+2) = zdat(:,k);
+                k++;
+              endfor
+              zz = zz.';
+
+              data_idx++;
+              is_image_data(data_idx) = is_image_data(data_idx - 1);
+              parametric(data_idx) = parametric(data_idx - 1);
+              have_cdata(data_idx) = false;
+              have_3d_patch(data_idx) = have_3d_patch(data_idx - 1);
+              titlespec{data_idx} = "title \"\"";
+              usingclause{data_idx} = sprintf ("record=%dx%d using ($1):($2):($3)", ylen, xlen);
+              data{data_idx} = zz;
+              withclause{data_idx} = sprintf ("with %s linestyle %d",
+                                              style{2}, data_idx);
+
+            endif
+            if (length (style) > 2)
+              data_idx++;
+              is_image_data(data_idx) = is_image_data(data_idx - 1);
+              parametric(data_idx) = parametric(data_idx - 1);
+              have_cdata(data_idx) = false;
+              have_3d_patch(data_idx) = have_3d_patch(data_idx - 1);
+              titlespec{data_idx} = "title \"\"";
+              usingclause{data_idx} = sprintf ("record=%dx%d using ($1):($2):($3)", ylen, xlen);
+              data{data_idx} = zz;
+              withclause{data_idx} = sprintf ("with %s linestyle %d",
+                                              style{3}, data_idx);
+            endif
+            if (withpm3d && strncmp (style {1}, "linespoints", 11))
+              if (isempty(zz))
+                len = 3 * xlen;
+                zz = zeros (ylen, len);
+                k = 1;
+                for kk = 1:3:len
+                  zz(:,kk)   = xdat(:,k);
+                  zz(:,kk+1) = ydat(:,k);
+                  zz(:,kk+2) = zdat(:,k);
+                  k++;
+                endfor
+                zz = zz.';
+              endif
+              data_idx++;
+              is_image_data(data_idx) = is_image_data(data_idx - 1);
+              parametric(data_idx) = parametric(data_idx - 1);
+              have_cdata(data_idx) = false;
+              have_3d_patch(data_idx) = have_3d_patch(data_idx - 1);
+              titlespec{data_idx} = "title \"\"";
+              usingclause{data_idx} = sprintf ("record=%dx%d using ($1):($2):($3)", ylen, xlen);
+              data{data_idx} = zz;
+              withclause{data_idx} = sprintf ("with points linestyle %d",
+                                              pm3didx);
+            endif
+          endif
+
+        case "text"
+          [label, f, s] = __maybe_munge_text__ (enhanced, obj, "string");
+          fontspec = create_fontspec (f, s, gnuplot_term);
+          lpos = obj.position;
+          halign = obj.horizontalalignment;
+          valign = obj.verticalalignment;
+          angle = obj.rotation;
+          units = obj.units;
+          color = obj.color;
+          if (strcmpi (units, "normalized"))
+            units = "graph";
+          elseif (strcmp (axis_obj.yaxislocation, "right")
+                  && strcmp (units, "data"))
+            units = "second";
+          else
+            units = "";
+          endif
+
+          if (isnumeric (color))
+            colorspec = get_text_colorspec (color, mono);
+          endif
+
+          if (ischar (obj.string))
+            num_lines = size (obj.string, 1);
+          else
+            num_lines = numel (obj.string);
+          endif
+          switch valign
+            ## Text offset in characters. This relies on gnuplot for font metrics.
+            case "top"
+              dy = -0.5;
+            case "cap"
+              dy = -0.5;
+            case "middle"
+              dy = 0.5 * (num_lines - 1);
+            case "baseline"
+              dy = 0.5 + (num_lines - 1);
+            case "bottom"
+              dy = 0.5 + (num_lines - 1);
+          endswitch
+          ## Gnuplot's Character units are different for x/y and vary with fontsize. The aspect ratio
+          ## of 1:1.7 was determined by experiment to work for eps/ps/etc. For the MacOS aqua terminal
+          ## a value of 2.5 is needed. However, the difference is barely noticable.
+          dx_and_dy = [(-dy * sind (angle)), (dy * cosd(angle))] .* [1.7 1];
+
+          ## FIXME - Multiline text produced the gnuplot "warning: ft_render: skipping glyph"
+          if (nd == 3)
+            ## This produces the desired vertical alignment in 3D.
+            fprintf (plot_stream,
+                     "set label \"%s\" at %s %.15e,%.15e,%.15e %s rotate by %f offset character %f,%f %s %s front %s;\n",
+                     undo_string_escapes (label), units, lpos(1),
+                     lpos(2), lpos(3), halign, angle, dx_and_dy, fontspec,
+                     __do_enhanced_option__ (enhanced, obj), colorspec);
+          else
+            fprintf (plot_stream,
+                     "set label \"%s\" at %s %.15e,%.15e %s rotate by %f offset character %f,%f %s %s front %s;\n",
+                     undo_string_escapes (label), units,
+                     lpos(1), lpos(2), halign, angle, dx_and_dy, fontspec,
+                     __do_enhanced_option__ (enhanced, obj), colorspec);
+          endif
+
+        case "hggroup"
+          ## Push group children into the kid list.
+          if (isempty (kids))
+            kids = obj.children;
+          elseif (! isempty (obj.children))
+            kids = [kids; obj.children];
+          endif
+
+        otherwise
+          error ("__go_draw_axes__: unknown object class, %s",
+                 obj.type);
+      endswitch
+
+    endwhile
+
+    ## This is need to prevent warnings for rotations in 3D plots, while
+    ## allowing colorbars with contours.
+    if (nd == 2 || (data_idx > 1 && !view_map))
+      fputs (plot_stream, "set pm3d implicit;\n");
+    else
+      fputs (plot_stream, "set pm3d explicit;\n");
+    endif
+
+    if (isnan(hidden_removal) || hidden_removal)
+      fputs (plot_stream, "set hidden3d;\n");
+    else
+      fputs (plot_stream, "unset hidden3d;\n");
+    endif
+
+    have_data = (! (isempty (data) || all (cellfun ("isempty", data))));
+
+    ## Note we don't use the [xy]2range of gnuplot as we don't use the
+    ## dual axis plotting features of gnuplot.
+    if (isempty (xlim))
+      return;
+    endif
+    if (strcmpi (axis_obj.xdir, "reverse"))
+      xdir = "reverse";
+    else
+      xdir = "noreverse";
+    endif
+    fprintf (plot_stream, "set xrange [%.15e:%.15e] %s;\n", xlim, xdir);
+    if (strcmpi (axis_obj.xaxislocation, "top"))
+      fprintf (plot_stream, "set x2range [%.15e:%.15e] %s;\n", xlim, xdir);
+    endif
+
+    if (isempty (ylim))
+      return;
+    endif
+    if (strcmpi (axis_obj.ydir, "reverse"))
+      ydir = "reverse";
+    else
+      ydir = "noreverse";
+    endif
+    fprintf (plot_stream, "set yrange [%.15e:%.15e] %s;\n", ylim, ydir);
+    if (strcmpi (axis_obj.yaxislocation, "right"))
+      fprintf (plot_stream, "set y2range [%.15e:%.15e] %s;\n", ylim, ydir);
+    endif
+
+    if (nd == 3)
+      if (isempty (zlim))
+        return;
+      endif
+      if (strcmpi (axis_obj.zdir, "reverse"))
+        zdir = "reverse";
+      else
+        zdir = "noreverse";
+      endif
+      fprintf (plot_stream, "set zrange [%.15e:%.15e] %s;\n", zlim, zdir);
+    endif
+
+    cmap = parent_figure_obj.colormap;
+    cmap_sz = rows(cmap);
+    if (! any (isinf (clim)))
+      if (truecolor || ! cdatadirect)
+        if (rows(addedcmap) > 0)
+          for i = 1:data_idx
+            if (have_3d_patch(i))
+              data{i}(end,:) = clim(2) * (data{i}(end, :) - 0.5) / cmap_sz;
+             endif
+          endfor
+          fprintf (plot_stream, "set cbrange [%g:%g];\n", clim(1), clim(2) *
+                   (cmap_sz + rows(addedcmap)) / cmap_sz);
+        else
+          fprintf (plot_stream, "set cbrange [%g:%g];\n", clim);
+        endif
+      else
+        fprintf (plot_stream, "set cbrange [1:%d];\n", cmap_sz +
+                 rows (addedcmap));
+      endif
+    endif
+
+    if (strcmpi (axis_obj.box, "on"))
+      if (nd == 3)
+        fputs (plot_stream, "set border 4095;\n");
+      else
+        fputs (plot_stream, "set border 431;\n");
+      endif
+    else
+      if (nd == 3)
+        fputs (plot_stream, "set border 895;\n");
+      elseif (! isempty (axis_obj.ytick))
+        if (strcmpi (axis_obj.yaxislocation, "right"))
+          fprintf (plot_stream, "unset ytics; set y2tics %s nomirror\n",
+                   axis_obj.tickdir);
+          if (strcmpi (axis_obj.xaxislocation, "top"))
+            fprintf (plot_stream, "unset xtics; set x2tics %s nomirror\n",
+                     axis_obj.tickdir);
+            fputs (plot_stream, "set border 12;\n");
+          else
+            fprintf (plot_stream, "unset x2tics; set xtics %s nomirror\n",
+                     axis_obj.tickdir);
+            fputs (plot_stream, "set border 9;\n");
+          endif
+        else
+          fprintf (plot_stream, "unset y2tics; set ytics %s nomirror\n",
+                   axis_obj.tickdir);
+          if (strcmpi (axis_obj.xaxislocation, "top"))
+            fprintf (plot_stream, "unset xtics; set x2tics %s nomirror\n",
+                     axis_obj.tickdir);
+            fputs (plot_stream, "set border 6;\n");
+          else
+            fprintf (plot_stream, "unset x2tics; set xtics %s nomirror\n",
+                     axis_obj.tickdir);
+            fputs (plot_stream, "set border 3;\n");
+          endif
+        endif
+      endif
+    endif
+
+    if (strcmpi (axis_obj.visible, "off"))
+      fputs (plot_stream, "unset border; unset tics\n");
+    else
+      fprintf (plot_stream, "set border lw %f;\n", axis_obj.linewidth);
+    endif
+
+    if (! isempty (hlgnd) && ! isempty (hlgnd.children)
+        && any (strcmpi (get (hlgnd.children, "visible"), "on")))
+      if (strcmpi (hlgnd.box, "on"))
+        box = "box";
+      else
+        box = "nobox";
+      endif
+      if (strcmpi (hlgnd.orientation, "vertical"))
+        horzvert = "vertical";
+      else
+        horzvert = "horizontal";
+      endif
+      if (strcmpi (hlgnd.textposition, "right"))
+        reverse = "reverse";
+      else
+        reverse = "noreverse";
+      endif
+      inout = "inside";
+      keypos = hlgnd.location;
+      if (ischar (keypos))
+        keypos = lower (keypos);
+        keyout = findstr (keypos, "outside");
+        if (! isempty (keyout))
+          inout = "outside";
+          keypos = keypos(1:keyout-1);
+        endif
+      endif
+      switch (keypos)
+        case "north"
+          pos = "center top";
+        case "south"
+          pos = "center bottom";
+        case "east"
+          pos = "right center";
+        case "west"
+          pos = "left center";
+        case "northeast"
+          pos = "right top";
+        case "northwest"
+          pos = "left top";
+        case "southeast"
+          pos = "right bottom";
+        case "southwest"
+          pos = "left bottom";
+        case "best"
+          pos = "";
+          warning ("legend: 'Best' not yet implemented for location specifier.\n");
+          ## Least conflict with data in plot.
+          ## Least unused space outside plot.
+        otherwise
+          pos = "";
+      endswitch
+      if (__gnuplot_has_feature__ ("key_has_font_properties"))
+        [fontname, fontsize] = get_fontname_and_size (hlgnd);
+        fontspec = create_fontspec (fontname, fontsize, gnuplot_term);
+      else
+        fontspec = "";
+      endif
+      fprintf (plot_stream, "set key %s %s;\nset key %s %s %s %s;\n",
+               inout, pos, box, reverse, horzvert, fontspec);
+    else
+      fputs (plot_stream, "unset key;\n");
+    endif
+    fputs (plot_stream, "set style data lines;\n");
+
+    cmap = [cmap; addedcmap];
+    cmap_sz = cmap_sz + rows(addedcmap);
+    if (length(cmap) > 0)
+      fprintf (plot_stream,
+               "set palette positive color model RGB maxcolors %i;\n",
+               cmap_sz);
+      fprintf (plot_stream,
+               "set palette file \"-\" binary record=%d using 1:2:3:4;\n",
+               cmap_sz);
+      fwrite (plot_stream, [1:cmap_sz; cmap.'], "float32");
+      fwrite (plot_stream, "\n");
+    endif
+
+    fputs (plot_stream, "unset colorbox;\n");
+
+    if (have_data)
+      if (nd == 2)
+        plot_cmd = "plot";
+      else
+        plot_cmd = "splot";
+        rot_x = 90 - axis_obj.view(2);
+        rot_z = axis_obj.view(1);
+        while (rot_z < 0)
+          rot_z += 360;
+        endwhile
+        fputs (plot_stream, "set ticslevel 0;\n");
+        if (view_map && rot_x == 0 && rot_z == 0)
+          fputs (plot_stream, "set view map;\n");
+        else
+          fprintf (plot_stream, "set view %.15g, %.15g;\n", rot_x, rot_z);
+        endif
+      endif
+      if (have_3d_patch (1))
+        fputs (plot_stream, "set pm3d depthorder\n");
+        fprintf (plot_stream, "%s \"-\" %s %s %s \\\n", plot_cmd,
+                 usingclause{1}, titlespec{1}, withclause{1});
+      elseif (is_image_data (1))
+        if (numel (is_image_data) > 1 && is_image_data(2))
+          ## Remove terminating semicolon
+          n = max (strfind (withclause{1}, ";"));
+          if (! isempty(n))
+            withclause{1} = withclause{1}(1:n-1);
+          endif
+        endif
+        fprintf (plot_stream, "%s \"-\" %s %s %s \\\n", plot_cmd,
+                 usingclause{1}, titlespec{1}, withclause{1});
+      else
+        fprintf (plot_stream, "%s \"-\" binary format='%%float64' %s %s %s \\\n", plot_cmd,
+                 usingclause{1}, titlespec{1}, withclause{1});
+      endif
+      for i = 2:data_idx
+        if (have_3d_patch (i))
+          fprintf (plot_stream, ", \"-\" %s %s %s \\\n",
+                   usingclause{i}, titlespec{i}, withclause{i});
+        elseif (is_image_data (i))
+          if (! is_image_data (i-1))
+            fputs (plot_stream, "; ");
+            if (bg_is_set)
+              fputs (plot_stream, "unset obj 1; \\\n");
+              bg_is_set = false;
+            endif
+            if (fg_is_set)
+              fputs (plot_stream, "unset obj 2; \\\n");
+              fg_is_set = false;
+            endif
+            if (numel (is_image_data) > i && is_image_data(i+1))
+              ## Remove terminating semicolon
+              n = max (strfind (withclause{i}, ";"));
+              if (! isempty(n))
+                withclause{i} = withclause{i}(1:n-1);
+              endif
+            endif
+            fprintf (plot_stream, "%s \"-\" %s %s %s \\\n", plot_cmd,
+                     usingclause{i}, titlespec{i}, withclause{i});
+          else
+            ## For consecutive images continue with the same plot command
+            fprintf (plot_stream, "%s \"-\" %s %s %s \\\n", ",",
+                     usingclause{i}, titlespec{i}, withclause{i});
+          endif
+        elseif (is_image_data (i-1))
+          if (bg_is_set)
+            fputs (plot_stream, "unset obj 1; \\\n");
+            bg_is_set = false;
+          endif
+          if (fg_is_set)
+            fputs (plot_stream, "unset obj 2; \\\n");
+            fg_is_set = false;
+          endif
+          fprintf (plot_stream, "%s \"-\" binary format='%%float64' %s %s %s \\\n", plot_cmd,
+                   usingclause{i}, titlespec{i}, withclause{i});
+        else
+          fprintf (plot_stream, ", \"-\" binary format='%%float64' %s %s %s \\\n",
+                   usingclause{i}, titlespec{i}, withclause{i});
+        endif
+      endfor
+      fputs (plot_stream, ";\n");
+      for i = 1:data_idx
+        if (have_3d_patch (i))
+          ## Can't write 3d patch data as binary as can't plot more than
+          ## a single patch at a time and have to plot all patches together
+          ## so that the gnuplot depth ordering is done correctly
+          for j = 1 : 4 : columns(data{i})
+            if (j != 1)
+              fputs (plot_stream, "\n\n");
+            endif
+            fprintf (plot_stream, "%.15g %.15g %.15g %.15g\n", data{i}(:,j).');
+            fprintf (plot_stream, "%.15g %.15g %.15g %.15g\n\n", data{i}(:,j+1).');
+            fprintf (plot_stream, "%.15g %.15g %.15g %.15g\n", data{i}(:,j+2).');
+            fprintf (plot_stream, "%.15g %.15g %.15g %.15g\n", data{i}(:,j+3).');
+          endfor
+          fputs (plot_stream, "e\n");
+        elseif (is_image_data(i))
+          fwrite (plot_stream, data{i}, "float32");
+        else
+          __gnuplot_write_data__ (plot_stream, data{i}, nd, parametric(i),
+                                  have_cdata(i));
+        endif
+      endfor
+    else
+      fputs (plot_stream, "plot \"-\";\nInf Inf\ne\n");
+    endif
+
+    ## Needed to allow mouse rotation with pcolor.
+    if (view_map)
+      fputs (plot_stream, "unset view;\n");
+    endif
+
+    if (bg_is_set)
+      fputs (plot_stream, "unset obj 1;\n");
+      bg_is_set = false;
+    endif
+
+    fflush (plot_stream);
+
+  else
+    print_usage ();
+  endif
+
+endfunction
+
+function x = flip (x)
+  if (size (x, 1) == 1)
+    x = fliplr (x);
+  elseif (size (x, 2) == 1 || ischar (x))
+    x = flipup (x);
+  else
+    x = flipud (fliplr (x));
+  endif
+endfunction
+
+function fontspec = create_fontspec (f, s, gp_term)
+  if (strcmp (f, "*") || strcmp (gp_term, "tikz"))
+    fontspec = sprintf ("font \",%d\"", s);
+  else
+    fontspec = sprintf ("font \"%s,%d\"", f, s);
+  endif
+endfunction
+
+function style = do_linestyle_command (obj, linecolor, idx, mono,
+                                       plot_stream, errbars = "")
+  style = {};
+
+  fprintf (plot_stream, "set style line %d default;\n", idx);
+  fprintf (plot_stream, "set style line %d", idx);
+
+  found_style = false;
+  if (isnumeric (linecolor))
+    color = linecolor;
+    if (! mono)
+      fprintf (plot_stream, " linecolor rgb \"#%02x%02x%02x\"",
+               round (255*color));
+    endif
+  else
+    color = [0, 0, 0];
+  endif
+
+  if (isfield (obj, "linestyle"))
+    switch (obj.linestyle)
+      case "-"
+        lt = "1";
+      case "--"
+        lt = "2";
+      case ":"
+        lt = "3";
+      case "-."
+        lt = "6";
+      case "none"
+        lt = "";
+      otherwise
+        lt = "";
+    endswitch
+
+    if (! isempty (lt))
+      fprintf (plot_stream, " linetype %s", lt);
+    endif
+
+  else
+    lt = "";
+  endif
+  if (! isempty (errbars))
+    found_style = true;
+  endif
+
+  if (isfield (obj, "linewidth"))
+    fprintf (plot_stream, " linewidth %f", obj.linewidth);
+    found_style = true;
+  endif
+
+  [pt, pt2, obj] = gnuplot_pointtype (obj);
+
+  if (! isempty (pt))
+    found_style = true;
+  endif
+
+  sidx = 1;
+  if (isempty (errbars))
+    if (isempty (lt))
+      style {sidx} = "";
+    else
+      style {sidx} = "lines";
+    endif
+
+    facesame = true;
+    if (! isequal (pt, pt2) && isfield (obj, "markerfacecolor")
+        && !strncmp (obj.markerfacecolor, "none", 4))
+      if (strncmp (obj.markerfacecolor, "auto", 4)
+          || ! isnumeric (obj.markerfacecolor)
+          || (isnumeric (obj.markerfacecolor)
+              && isequal (color, obj.markerfacecolor)))
+        if (! isempty (pt2))
+          fprintf (plot_stream, " pointtype %s", pt2);
+          style {sidx} = strcat (style{sidx}, "points");
+        endif
+        if (isfield (obj, "markersize"))
+          fprintf (plot_stream, " pointsize %f", obj.markersize / 3);
+        endif
+      else
+        facesame = false;
+        if (! found_style)
+          fputs (plot_stream, " default");
+        endif
+        fputs (plot_stream, ";\n");
+        if (! isempty (style {sidx}))
+          sidx ++;
+          idx ++;
+        else
+          fputs (plot_stream, ";\n");
+        endif
+        fprintf (plot_stream, "set style line %d default;\n", idx);
+        fprintf (plot_stream, "set style line %d", idx);
+        if (isnumeric (obj.markerfacecolor) && ! mono)
+          fprintf (plot_stream, " linecolor rgb \"#%02x%02x%02x\"",
+                   round (255*obj.markerfacecolor));
+        endif
+        if (! isempty (pt2))
+          style {sidx} = "points";
+          fprintf (plot_stream, " pointtype %s", pt2);
+        endif
+        if (isfield (obj, "markersize"))
+          fprintf (plot_stream, " pointsize %f", obj.markersize / 3);
+        endif
+      endif
+    endif
+    if (isfield (obj, "markeredgecolor")
+        && !strncmp (obj.markeredgecolor, "none", 4))
+      if (facesame && !isempty (pt)
+          && (strncmp (obj.markeredgecolor, "auto", 4)
+              || ! isnumeric (obj.markeredgecolor)
+              || (isnumeric (obj.markeredgecolor)
+                  && isequal (color, obj.markeredgecolor))))
+        if (sidx == 1 && ((length (style {sidx}) == 5
+            && strncmp (style {sidx}, "lines", 5)) || isempty (style {sidx})))
+          if (! isempty (pt))
+            style {sidx} = strcat (style{sidx}, "points");
+            fprintf (plot_stream, " pointtype %s", pt);
+          endif
+          if (isfield (obj, "markersize"))
+            fprintf (plot_stream, " pointsize %f", obj.markersize / 3);
+          endif
+        endif
+      else
+        if (! found_style)
+          fputs (plot_stream, " default");
+        endif
+        fputs (plot_stream, ";\n");
+        if (!isempty (style {sidx}))
+          sidx ++;
+          idx ++;
+        else
+          fputs (plot_stream, ";\n");
+        endif
+        fprintf (plot_stream, "set style line %d default;\n", idx);
+        fprintf (plot_stream, "set style line %d", idx);
+        if (! mono)
+          if (strncmp (obj.markeredgecolor, "auto", 4))
+            fprintf (plot_stream, " linecolor rgb \"#%02x%02x%02x\"",
+                     round (255*color));
+          elseif (isnumeric (obj.markeredgecolor) && ! mono)
+            fprintf (plot_stream, " linecolor rgb \"#%02x%02x%02x\"",
+                     round (255*obj.markeredgecolor));
+          endif
+        endif
+        if (! isempty (pt))
+          style {sidx} = "points";
+          fprintf (plot_stream, " pointtype %s", pt);
+        endif
+        if (isfield (obj, "markersize"))
+          fprintf (plot_stream, " pointsize %f", obj.markersize / 3);
+        endif
+      endif
+    endif
+  else
+    style{1} = errbars;
+    fputs (plot_stream, " pointtype 0");
+  endif
+
+  if (! found_style && isempty (style {1}))
+    fputs (plot_stream, " default");
+  endif
+
+  fputs (plot_stream, ";\n");
+
+endfunction
+
+function [pt, pt2, obj] = gnuplot_pointtype (obj)
+  if (isfield (obj, "marker"))
+    switch (obj.marker)
+      case "+"
+        pt = pt2 = "1";
+      case "o"
+        pt = "6";
+        pt2 = "7";
+      case "*"
+        pt = pt2 = "3";
+      case "."
+        pt = "6";
+        pt2 = "7";
+        if (isfield (obj, "markerfacecolor")
+            || strncmp (obj.markerfacecolor, "none", 4))
+          obj.markerfacecolor = "auto";
+        endif
+        if (isfield (obj, "markersize"))
+          obj.markersize /= 3;
+        else
+          obj.markersize = 5;
+        endif
+      case "x"
+        pt = pt2 = "2";
+      case {"square", "s"}
+        pt = "4";
+        pt2 = "5";
+      case {"diamond", "d"}
+        pt = "12";
+        pt2 = "13";
+      case "^"
+        pt = "8";
+        pt2 = "9";
+      case "v"
+        pt = "10";
+        pt2 = "11";
+      case ">"
+        ## FIXME -- should be triangle pointing right, use triangle pointing up
+        pt = "8";
+        pt2 = "9";
+      case "<"
+        ## FIXME -- should be triangle pointing left, use triangle pointing down
+        pt = "10";
+        pt2 = "11";
+      case {"pentagram", "p"}
+        ## FIXME -- should be pentagram, using pentagon
+        pt = "14";
+        pt2 = "15";
+      case {"hexagram", "h"}
+        ## FIXME -- should be 6 pt start, using "*" instead
+        pt = pt2 = "3";
+      case "none"
+        pt = pt2 = "";
+      otherwise
+        pt = pt2 = "";
+    endswitch
+  else
+    pt = pt2 = "";
+  endif
+endfunction
+
+function __gnuplot_write_data__ (plot_stream, data, nd, parametric, cdata)
+
+  ## DATA is already transposed.
+
+  ## FIXME -- this may need to be converted to C++ for speed.
+
+  ## Convert NA elements to normal NaN values because fprintf writes
+  ## "NA" and that confuses gnuplot.
+  idx = find (isna (data));
+  if (any (idx))
+    data(idx) = NaN;
+  endif
+
+  if (nd == 2)
+    fwrite (plot_stream, data, "float64");
+  elseif (nd == 3)
+    if (parametric)
+      fwrite (plot_stream, data, "float64");
+    else
+      nr = rows (data);
+      if (cdata)
+        for j = 1:4:nr
+          fwrite (plot_stream, data(j:j+3,:), "float64");
+        endfor
+      else
+        for j = 1:3:nr
+          fwrite (plot_stream, data(j:j+2,:), "float64");
+        endfor
+      endif
+    endif
+  endif
+
+endfunction
+
+function do_tics (obj, plot_stream, ymirror, mono, gnuplot_term)
+
+  obj.xticklabel = ticklabel_to_cell (obj.xticklabel);
+  obj.yticklabel = ticklabel_to_cell (obj.yticklabel);
+  obj.zticklabel = ticklabel_to_cell (obj.zticklabel);
+
+  if (strcmp (obj.xminorgrid, "on"))
+    obj.xminortick = "on";
+  endif
+  if (strcmp (obj.yminorgrid, "on"))
+    obj.yminortick = "on";
+  endif
+  if (strcmp (obj.zminorgrid, "on"))
+    obj.zminortick = "on";
+  endif
+
+  [fontname, fontsize] = get_fontname_and_size (obj);
+  fontspec = create_fontspec (fontname, fontsize, gnuplot_term);
+
+  ## A Gnuplot tic scale of 69 is equivalent to Octave's 0.5.
+  ticklength = sprintf ("scale %4.1f", (69/0.5)*obj.ticklength(1));
+
+  if (strcmpi (obj.xaxislocation, "top"))
+    do_tics_1 (obj.xtickmode, obj.xtick, obj.xminortick, obj.xticklabelmode,
+               obj.xticklabel, obj.xcolor, "x2", plot_stream, true, mono,
+               "border", obj.tickdir, ticklength, fontname, fontspec,
+               obj.interpreter, obj.xscale, gnuplot_term);
+    do_tics_1 ("manual", [], "off", obj.xticklabelmode, obj.xticklabel,
+               obj.xcolor, "x", plot_stream, true, mono, "border",
+               "", "", fontname, fontspec, obj.interpreter, obj.xscale,
+               gnuplot_term);
+  elseif (strcmpi (obj.xaxislocation, "zero"))
+    do_tics_1 (obj.xtickmode, obj.xtick, obj.xminortick, obj.xticklabelmode,
+               obj.xticklabel, obj.xcolor, "x", plot_stream, true, mono,
+               "axis", obj.tickdir, ticklength, fontname, fontspec,
+               obj.interpreter, obj.xscale, gnuplot_term);
+    do_tics_1 ("manual", [], "off", obj.xticklabelmode, obj.xticklabel,
+               obj.xcolor, "x2", plot_stream, true, mono, "axis",
+               "", "", fontname, fontspec, obj.interpreter, obj.xscale,
+               gnuplot_term);
+  else
+    do_tics_1 (obj.xtickmode, obj.xtick, obj.xminortick, obj.xticklabelmode,
+               obj.xticklabel, obj.xcolor, "x", plot_stream, true, mono,
+               "border", obj.tickdir, ticklength, fontname, fontspec,
+               obj.interpreter, obj.xscale, gnuplot_term);
+    do_tics_1 ("manual", [], "off", obj.xticklabelmode, obj.xticklabel,
+               obj.xcolor, "x2", plot_stream, true, mono, "border",
+               "", "", fontname, fontspec, obj.interpreter, obj.xscale,
+               gnuplot_term);
+  endif
+  if (strcmpi (obj.yaxislocation, "right"))
+    do_tics_1 (obj.ytickmode, obj.ytick, obj.yminortick, obj.yticklabelmode,
+               obj.yticklabel, obj.ycolor, "y2", plot_stream, ymirror, mono,
+               "border", obj.tickdir, ticklength, fontname, fontspec,
+               obj.interpreter, obj.yscale, gnuplot_term);
+    do_tics_1 ("manual", [], "off", obj.yticklabelmode, obj.yticklabel,
+               obj.ycolor, "y", plot_stream, ymirror, mono, "border",
+               "", "", fontname, fontspec, obj.interpreter, obj.yscale,
+               gnuplot_term);
+  elseif (strcmpi (obj.yaxislocation, "zero"))
+    do_tics_1 (obj.ytickmode, obj.ytick, obj.yminortick, obj.yticklabelmode,
+               obj.yticklabel, obj.ycolor, "y", plot_stream, ymirror, mono,
+               "axis", obj.tickdir, ticklength, fontname, fontspec,
+               obj.interpreter, obj.yscale, gnuplot_term);
+    do_tics_1 ("manual", [], "off", obj.yticklabelmode, obj.yticklabel,
+               obj.ycolor, "y2", plot_stream, ymirror, mono, "axis",
+               "", "", fontname, fontspec, obj.interpreter, obj.yscale,
+               gnuplot_term);
+  else
+    do_tics_1 (obj.ytickmode, obj.ytick, obj.yminortick, obj.yticklabelmode,
+               obj.yticklabel, obj.ycolor, "y", plot_stream, ymirror, mono,
+               "border", obj.tickdir, ticklength, fontname, fontspec,
+               obj.interpreter, obj.yscale, gnuplot_term);
+    do_tics_1 ("manual", [], "off", obj.yticklabelmode, obj.yticklabel,
+               obj.ycolor, "y2", plot_stream, ymirror, mono, "border",
+               "", "", fontname, fontspec, obj.interpreter, obj.yscale,
+               gnuplot_term);
+  endif
+  do_tics_1 (obj.ztickmode, obj.ztick, obj.zminortick, obj.zticklabelmode,
+             obj.zticklabel, obj.zcolor, "z", plot_stream, true, mono,
+             "border", obj.tickdir, ticklength, fontname, fontspec,
+             obj.interpreter, obj.zscale, gnuplot_term);
+endfunction
+
+function do_tics_1 (ticmode, tics, mtics, labelmode, labels, color, ax,
+                    plot_stream, mirror, mono, axispos, tickdir, ticklength,
+                    fontname, fontspec, interpreter, scale, gnuplot_term)
+  persistent warned_latex = false;
+  if (strcmpi (interpreter, "tex"))
+    for n = 1 : numel(labels)
+      labels{n} = __tex2enhanced__ (labels{n}, fontname, false, false);
+    endfor
+  elseif (strcmpi (interpreter, "latex"))
+    if (! warned_latex)
+      warning ("latex markup not supported for tick marks");
+      warned_latex = true;
+    endif
+  endif
+  if (strcmp (scale, "log"))
+    num_mtics = 10;
+    if (any (strcmp (gnuplot_term, {"tikz", "pstex", "pslatex", "epslatex"})))
+      fmt = "$10^{%T}$";
+    else
+      fmt = "10^{%T}";
+    endif
+  else
+    fmt = "%g";
+    num_mtics = 5;
+  endif
+  colorspec = get_text_colorspec (color, mono);
+  if (strcmpi (ticmode, "manual") || strcmpi (labelmode, "manual"))
+    if (isempty (tics))
+      fprintf (plot_stream, "unset %stics;\nunset m%stics;\n", ax, ax);
+    elseif (strcmpi (labelmode, "manual"))
+      if (ischar (labels))
+        labels = cellstr (labels);
+      endif
+      if (isnumeric (labels))
+        labels = num2str (real (labels(:)));
+      endif
+      if (ischar (labels))
+        labels = permute (cellstr (labels), [2, 1]);
+      endif
+      if (iscellstr (labels))
+        k = 1;
+        ntics = numel (tics);
+        nlabels = numel (labels);
+        fprintf (plot_stream, "set format %s \"%%s\";\n", ax);
+        if (mirror)
+          fprintf (plot_stream, "set %stics %s %s %s mirror (", ax,
+                   tickdir, ticklength, axispos);
+        else
+          fprintf (plot_stream, "set %stics %s %s %s nomirror (", ax,
+                   tickdir, ticklength, axispos);
+        endif
+
+        labels = regexprep(labels, '%', "%%");
+        for i = 1:ntics
+          fprintf (plot_stream, " \"%s\" %.15g", labels{k++}, tics(i));
+          if (i < ntics)
+            fputs (plot_stream, ", ");
+          endif
+          if (k > nlabels)
+            k = 1;
+          endif
+        endfor
+        fprintf (plot_stream, ") %s %s;\n", colorspec, fontspec);
+        if (strcmp (mtics, "on"))
+          fprintf (plot_stream, "set m%stics %d;\n", ax, num_mtics);
+        else
+          fprintf (plot_stream, "unset m%stics;\n", ax);
+        endif
+     else
+        error ("__go_draw_axes__: unsupported type of ticklabel");
+      endif
+    else
+      fprintf (plot_stream, "set format %s \"%s\";\n", ax, fmt);
+      if (mirror)
+        fprintf (plot_stream, "set %stics %s %s %s mirror (", ax, tickdir,
+                 ticklength, axispos);
+      else
+        fprintf (plot_stream, "set %stics %s %s %s nomirror (", ax, tickdir,
+                 ticklength, axispos);
+      endif
+      fprintf (plot_stream, " %.15g,", tics(1:end-1));
+      fprintf (plot_stream, " %.15g) %s;\n", tics(end), fontspec);
+      if (strcmp (mtics, "on"))
+        fprintf (plot_stream, "set m%stics %d;\n", ax, num_mtics);
+      else
+        fprintf (plot_stream, "unset m%stics;\n", ax);
+      endif
+    endif
+  else
+    fprintf (plot_stream, "set format %s \"%s\";\n", ax, fmt);
+    if (mirror)
+      fprintf (plot_stream, "set %stics %s %s %s mirror %s %s;\n", ax,
+               axispos, tickdir, ticklength, colorspec, fontspec);
+    else
+      fprintf (plot_stream, "set %stics %s %s %s nomirror %s %s;\n", ax,
+               tickdir, ticklength, axispos, colorspec, fontspec);
+    endif
+    if (strcmp (mtics, "on"))
+      fprintf (plot_stream, "set m%stics %d;\n", ax, num_mtics);
+    else
+      fprintf (plot_stream, "unset m%stics;\n", ax);
+    endif
+  endif
+endfunction
+
+function ticklabel = ticklabel_to_cell (ticklabel)
+  if (isnumeric (ticklabel))
+    ## Use upto 5 significant digits
+    ticklabel = num2str (ticklabel(:), 5);
+  endif
+  if (ischar (ticklabel))
+    if (size (ticklabel, 1) == 1 && any (ticklabel == "|"))
+      n = setdiff (findstr (ticklabel, "|"), findstr (ticklabel, '\|'));
+      ticklabel = strsplit (ticklabel, "|");
+    else
+      ticklabel = cellstr (ticklabel);
+    endif
+  elseif (isempty (ticklabel))
+    ticklabel = {""};
+  else
+    ticklabel = ticklabel;
+  endif
+endfunction
+
+function colorspec = get_text_colorspec (color, mono)
+  if (mono)
+    colorspec = "";
+  else
+    colorspec = sprintf ("textcolor rgb \"#%02x%02x%02x\"",
+                         round (255*color));
+  endif
+endfunction
+
+function [f, s, fnt, it, bld] = get_fontname_and_size (t)
+  if (isempty (t.fontname) || strcmp (t.fontname, "*"))
+    fnt = "{}";
+  else
+    fnt = t.fontname;
+  endif
+  f = fnt;
+  it = false;
+  bld = false;
+  if (! isempty (t.fontweight) && strcmpi (t.fontweight, "bold"))
+    if (! isempty(t.fontangle)
+        && (strcmpi (t.fontangle, "italic")
+            || strcmpi (t.fontangle, "oblique")))
+      f = cstrcat (f, "-bolditalic");
+      it = true;
+      bld = true;
+    else
+      f = cstrcat (f, "-bold");
+      bld = true;
+    endif
+  elseif (! isempty(t.fontangle)
+          && (strcmpi (t.fontangle, "italic")
+              || strcmpi (t.fontangle, "oblique")))
+    f = cstrcat (f, "-italic");
+    it = true;
+  endif
+  if (isempty (t.fontsize))
+    s = 10;
+  else
+    s = t.fontsize;
+  endif
+endfunction
+
+function [str, f, s] = __maybe_munge_text__ (enhanced, obj, fld)
+
+  persistent warned_latex = false;
+
+  if (strcmp (fld, "string"))
+    [f, s, fnt, it, bld] = get_fontname_and_size (obj);
+  else
+    f = "Helvetica";
+    s = 10;
+    fnt = f;
+    it = false;
+    bld = false;
+  endif
+
+  ## The text object maybe multiline, and may be of any class
+  str = getfield (obj, fld);
+  if (ischar (str) && size (str, 1) > 1)
+    str = cellstr (str);
+  elseif (isnumeric (str))
+    str = cellstr (num2str (str(:)));
+  endif
+  if (iscellstr (str))
+    for n = 1:numel(str)
+      if (isnumeric (str{n}))
+        str{n} = num2str (str{n});
+      endif
+    endfor
+    str = sprintf ("%s\n", str{:})(1:end-1);
+  endif
+
+  if (enhanced)
+    if (strcmpi (obj.interpreter, "tex"))
+      if (iscellstr (str))
+        for n = 1:numel(str)
+          str{n} = __tex2enhanced__ (str{n}, fnt, it, bld);
+        endfor
+      else
+        str = __tex2enhanced__ (str, fnt, it, bld);
+      endif
+    elseif (strcmpi (obj.interpreter, "latex"))
+      if (! warned_latex)
+        warning ("latex markup not supported for text objects");
+        warned_latex = true;
+      endif
+    endif
+  endif
+endfunction
+
+function str = __tex2enhanced__ (str, fnt, it, bld)
+  persistent sym = __setup_sym_table__ ();
+  persistent flds = fieldnames (sym);
+
+  [s, e, m] = regexp(str,'\\([a-zA-Z]+|0)','start','end','matches');
+
+  for i = length (s) : -1 : 1
+    ## special case for "\0"  and replace with "{/Symbol \306}'
+    if (strncmp (m{i}, '\0', 2))
+      str = cstrcat (str(1:s(i) - 1), '{/Symbol \306}', str(s(i) + 2:end));
+    else
+      f = m{i}(2:end);
+      if (isfield (sym, f))
+        g = getfield(sym, f);
+        ## FIXME The symbol font doesn't seem to support bold or italic
+        ##if (bld)
+        ##  if (it)
+        ##    g = regexprep (g, '/Symbol', '/Symbol-bolditalic');
+        ##  else
+        ##    g = regexprep (g, '/Symbol', '/Symbol-bold');
+        ##  endif
+        ##elseif (it)
+        ##  g = regexprep (g, '/Symbol', '/Symbol-italic');
+        ##endif
+        str = cstrcat (str(1:s(i) - 1), g, str(e(i) + 1:end));
+      elseif (strncmp (f, "rm", 2))
+        bld = false;
+        it = false;
+        str = cstrcat (str(1:s(i) - 1), '/', fnt, ' ', str(s(i) + 3:end));
+      elseif (strncmp (f, "it", 2) || strncmp (f, "sl", 2))
+        it = true;
+        if (bld)
+          str = cstrcat (str(1:s(i) - 1), '/', fnt, '-bolditalic ',
+                        str(s(i) + 3:end));
+        else
+          str = cstrcat (str(1:s(i) - 1), '/', fnt, '-italic ',
+                        str(s(i) + 3:end));
+        endif
+      elseif (strncmp (f, "bf", 2))
+        bld = true;
+        if (it)
+          str = cstrcat (str(1:s(i) - 1), '/', fnt, '-bolditalic ',
+                        str(2(i) + 3:end));
+        else
+          str = cstrcat (str(1:s(i) - 1), '/', fnt, '-bold ',
+                        str(s(i) + 3:end));
+        endif
+      elseif (strcmpi (f, "color"))
+        ## FIXME Ignore \color but remove trailing {} block as well
+        d = strfind(str(e(i) + 1:end),'}');
+        if (isempty (d))
+          warning ('syntax error in \color argument');
+        else
+          str = cstrcat (str(1:s(i) - 1), str(e(i) + d + 1:end));
+        endif
+      elseif(strcmpi (f, "fontname"))
+        b1 = strfind(str(e(i) + 1:end),'{');
+        b2 = strfind(str(e(i) + 1:end),'}');
+        if (isempty(b1) || isempty(b2))
+          warning ('syntax error in \fontname argument');
+        else
+          str = cstrcat (str(1:s(i) - 1), '/',
+                        str(e(i)+b1(1) + 1:e(i)+b2(1)-1), '{}',
+                        str(e(i) + b2(1) + 1:end));
+        endif
+      elseif(strcmpi (f, "fontsize"))
+        b1 = strfind(str(e(i) + 1:end),'{');
+        b2 = strfind(str(e(i) + 1:end),'}');
+        if (isempty(b1) || isempty(b2))
+          warning ('syntax error in \fontname argument');
+        else
+          str = cstrcat (str(1:s(i) - 1), '/=',
+                        str(e(i)+b1(1) + 1:e(i)+b2(1)-1), '{}',
+                        str(e(i) + b2(1) + 1:end));
+        endif
+      else
+        ## Last desperate attempt to treat the symbol. Look for things
+        ## like \pix, that should be translated to the symbol Pi and x
+        for j = 1 : length (flds)
+          if (strncmp (flds{j}, f, length (flds{j})))
+            g = getfield(sym, flds{j});
+            ## FIXME The symbol font doesn't seem to support bold or italic
+            ##if (bld)
+            ##  if (it)
+            ##    g = regexprep (g, '/Symbol', '/Symbol-bolditalic');
+            ##  else
+            ##    g = regexprep (g, '/Symbol', '/Symbol-bold');
+            ##  endif
+            ##elseif (it)
+            ##  g = regexprep (g, '/Symbol', '/Symbol-italic');
+            ##endif
+            str = cstrcat (str(1:s(i) - 1), g,
+                          str(s(i) + length (flds{j}) + 1:end));
+            break;
+          endif
+        endfor
+      endif
+    endif
+  endfor
+
+  ## Prepend @ to things  things like _0^x or _{-100}^{100} for
+  ## alignment But need to put the shorter of the two arguments first.
+  ## Carful of nested {} and unprinted characters when defining
+  ## shortest.. Don't have to worry about things like ^\theta as they
+  ## are already converted to ^{/Symbol q}.
+
+  ## FIXME -- This is a mess... Is it worth it just for a "@" character?
+
+  [s, m] = regexp(str,'[_\^]','start','matches');
+  i = 1;
+  p = 0;
+  while (i < length (s))
+    if (i < length(s))
+      if (str(s(i) + p + 1) == "{")
+        s1 = strfind(str(s(i) + p + 2:end),'{');
+        si = 1;
+        l1 = strfind(str(s(i) + p + 1:end),'}');
+        li = 1;
+        while (li <= length (l1) && si <= length (s1))
+          if (l1(li) < s1(si))
+            if (li == si)
+              break;
+            endif
+            li++;
+          else
+            si++;
+          endif
+        endwhile
+        l1 = l1 (min (length(l1), si));
+        if (s(i) + l1 + 1 == s(i+1))
+          if (str(s(i + 1) + p + 1) == "{")
+            s2 = strfind(str(s(i + 1) + p + 2:end),'{');
+            si = 1;
+            l2 = strfind(str(s(i + 1) + p + 1:end),'}');
+            li = 1;
+            while (li <= length (l2) && si <= length (s2))
+              if (l2(li) < s2(si))
+                if (li == si)
+                  break;
+                endif
+                li++;
+              else
+                si++;
+              endif
+            endwhile
+            l2 = l2 (min (length(l2), si));
+            if (length_string (str(s(i)+p+2:s(i)+p+l1-1)) <=
+                length_string(str(s(i+1)+p+2:s(i+1)+p+l2-1)))
+              ## Shortest already first!
+              str = cstrcat (str(1:s(i)+p-1), "@", str(s(i)+p:end));
+            else
+              ## Have to swap sub/super-script to get shortest first.
+              str = cstrcat (str(1:s(i)+p-1), "@", str(s(i+1)+p:s(i+1)+p+l2),
+                            str(s(i)+p:s(i)+p+l1), str(s(i+1)+p+l2+1:end));
+            endif
+          else
+            ## Have to swap sub/super-script to get shortest first.
+            str = cstrcat (str(1:s(i)+p-1), "@", str(s(i+1)+p:s(i+1)+p+1),
+                          str(s(i)+p:s(i)+p+l1), str(s(i+1)+p+2:end));
+          endif
+          i += 2;
+          p ++;
+        else
+          i++;
+        endif
+      else
+        if (s(i+1) == s(i) + 2)
+          ## Shortest already first!
+          str = cstrcat (str(1:s(i)+p-1), "@", str(s(i)+p:end));
+          p ++;
+          i += 2;
+        else
+          i ++;
+        endif
+      endif
+    else
+      i ++;
+    endif
+  endwhile
+
+endfunction
+
+function l = length_string (s)
+  l = length (s) - length (strfind(s,'{')) - length (strfind(s,'}'));
+  m = regexp (s, '/([\w-]+|[\w-]+=\d+)', 'matches');
+  if (!isempty (m))
+    l = l - sum (cellfun ("length", m));
+  endif
+endfunction
+
+function sym = __setup_sym_table__ ()
+  ## Setup the translation table for TeX to gnuplot enhanced mode.
+  sym.forall = '{/Symbol \042}';
+  sym.exists = '{/Symbol \044}';
+  sym.ni = '{/Symbol \047}';
+  sym.cong = '{/Symbol \100}';
+  sym.Delta = '{/Symbol D}';
+  sym.Phi = '{/Symbol F}';
+  sym.Gamma = '{/Symbol G}';
+  sym.vartheta = '{/Symbol J}';
+  sym.Lambda = '{/Symbol L}';
+  sym.Pi = '{/Symbol P}';
+  sym.Theta = '{/Symbol Q}';
+  sym.Sigma = '{/Symbol S}';
+  sym.varsigma = '{/Symbol V}';
+  sym.Omega = '{/Symbol W}';
+  sym.Xi = '{/Symbol X}';
+  sym.Psi = '{/Symbol Y}';
+  sym.perp = '{/Symbol \136}';
+  sym.alpha = '{/Symbol a}';
+  sym.beta = '{/Symbol b}';
+  sym.chi = '{/Symbol c}';
+  sym.delta = '{/Symbol d}';
+  sym.epsilon = '{/Symbol e}';
+  sym.phi = '{/Symbol f}';
+  sym.gamma = '{/Symbol g}';
+  sym.eta = '{/Symbol h}';
+  sym.iota = '{/Symbol i}';
+  sym.varphi = '{/Symbol j}';
+  sym.kappa = '{/Symbol k}';
+  sym.lambda = '{/Symbol l}';
+  sym.mu = '{/Symbol m}';
+  sym.nu = '{/Symbol n}';
+  sym.o =  '{/Symbol o}';
+  sym.pi = '{/Symbol p}';
+  sym.theta = '{/Symbol q}';
+  sym.rho = '{/Symbol r}';
+  sym.sigma = '{/Symbol s}';
+  sym.tau = '{/Symbol t}';
+  sym.upsilon = '{/Symbol u}';
+  sym.varpi = '{/Symbol v}';
+  sym.omega = '{/Symbol w}';
+  sym.xi = '{/Symbol x}';
+  sym.psi = '{/Symbol y}';
+  sym.zeta = '{/Symbol z}';
+  sym.sim = '{/Symbol \176}';
+  sym.Upsilon = '{/Symbol \241}';
+  sym.prime = '{/Symbol \242}';
+  sym.leq = '{/Symbol \243}';
+  sym.infty = '{/Symbol \245}';
+  sym.clubsuit = '{/Symbol \247}';
+  sym.diamondsuit = '{/Symbol \250}';
+  sym.heartsuit = '{/Symbol \251}';
+  sym.spadesuit = '{/Symbol \252}';
+  sym.leftrightarrow = '{/Symbol \253}';
+  sym.leftarrow = '{/Symbol \254}';
+  sym.uparrow = '{/Symbol \255}';
+  sym.rightarrow = '{/Symbol \256}';
+  sym.downarrow = '{/Symbol \257}';
+  sym.circ = '{/Symbol \260}';
+  sym.pm = '{/Symbol \261}';
+  sym.geq = '{/Symbol \263}';
+  sym.times = '{/Symbol \264}';
+  sym.propto = '{/Symbol \265}';
+  sym.partial = '{/Symbol \266}';
+  sym.bullet = '{/Symbol \267}';
+  sym.div = '{/Symbol \270}';
+  sym.neq = '{/Symbol \271}';
+  sym.equiv = '{/Symbol \272}';
+  sym.approx = '{/Symbol \273}';
+  sym.ldots = '{/Symbol \274}';
+  sym.mid = '{/Symbol \275}';
+  sym.aleph = '{/Symbol \300}';
+  sym.Im = '{/Symbol \301}';
+  sym.Re = '{/Symbol \302}';
+  sym.wp = '{/Symbol \303}';
+  sym.otimes = '{/Symbol \304}';
+  sym.oplus = '{/Symbol \305}';
+  sym.oslash = '{/Symbol \306}';
+  sym.cap = '{/Symbol \307}';
+  sym.cup = '{/Symbol \310}';
+  sym.supset = '{/Symbol \311}';
+  sym.supseteq = '{/Symbol \312}';
+  sym.subset = '{/Symbol \314}';
+  sym.subseteq = '{/Symbol \315}';
+  sym.in = '{/Symbol \316}';
+  sym.notin = '{/Symbol \317}';
+  sym.angle = '{/Symbol \320}';
+  sym.bigtriangledown = '{/Symbol \321}';
+  sym.langle = '{/Symbol \341}';
+  sym.rangle = '{/Symbol \361}';
+  sym.nabla = '{/Symbol \321}';
+  sym.prod = '{/Symbol \325}';
+  sym.surd = '{/Symbol \326}';
+  sym.cdot = '{/Symbol \327}';
+  sym.neg = '{/Symbol \330}';
+  sym.wedge = '{/Symbol \331}';
+  sym.vee = '{/Symbol \332}';
+  sym.Leftrightarrow = '{/Symbol \333}';
+  sym.Leftarrow = '{/Symbol \334}';
+  sym.Uparrow = '{/Symbol \335}';
+  sym.Rightarrow = '{/Symbol \336}';
+  sym.Downarrow = '{/Symbol \337}';
+  sym.diamond = '{/Symbol \340}';
+  sym.copyright = '{/Symbol \343}';
+  sym.lfloor = '{/Symbol \353}';
+  sym.lceil  = '{/Symbol \351}';
+  sym.rfloor = '{/Symbol \373}';
+  sym.rceil  = '{/Symbol \371}';
+  sym.int = '{/Symbol \362}';
+endfunction
+
+function retval = __do_enhanced_option__ (enhanced, obj)
+  retval = "";
+  if (enhanced)
+    if (strcmpi (obj.interpreter, "none"))
+      retval = "noenhanced";
+    else
+      retval = "enhanced";
+    endif
+  endif
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/private/__go_draw_figure__.m	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,198 @@
+## Copyright (C) 2005-2011 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 3 of the License, 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, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {} __go_draw_figure__ (@var{h}, @var{plot_stream}, @var{enhanced}, @var{mono})
+## Undocumented internal function.
+## @end deftypefn
+
+## Author: jwe
+
+function __go_draw_figure__ (h, plot_stream, enhanced, mono)
+
+  if (nargin == 4)
+    htype = get (h, "type");
+    if (strcmp (htype, "figure"))
+      ## Get complete list of children.
+      kids = allchild (h);
+      nkids = length (kids);
+
+      if (nkids > 0)
+        fputs (plot_stream, "\nreset;\n");
+        fputs (plot_stream, "set autoscale keepfix;\n");
+        fputs (plot_stream, "set origin 0, 0\n");
+        fputs (plot_stream, "set size 1, 1\n");
+        bg = get (h, "color");
+        if (isnumeric (bg))
+          fprintf (plot_stream, "set obj 1 rectangle from screen 0,0 to screen 1,1 behind fc rgb \"#%02x%02x%02x\"\n", 255 * bg);
+          bg_is_set = true;
+        else
+          bg_is_set = false;
+        endif
+
+        for i = nkids:-1:1
+          type = get (kids(i), "type");
+          switch (type)
+            case "axes"
+              if (strcmpi (get (kids (i), "tag"), "legend"))
+                ## This is so ugly. If there was a way of getting
+                ## gnuplot to give us the text extents of strings
+                ## then we could get rid of this mess.
+                lh = getfield (get (kids(i), "userdata"), "handle");
+                if (isscalar (lh))
+                  ## We have a legend with a single parent. It'll be handled
+                  ## below as a gnuplot key to the axis it corresponds to
+                  continue;
+                else
+                  ca = lh(1);
+                  ## Rely upon listener to convert axes position
+                  ## to "normalized" units.
+                  legend_axes_units = get (kids(i), "units");
+                  legend_axes_position = get (kids(i), "position");
+                  legend_axes_outerposition = get (kids(i), "outerposition");
+                  legend_axes_box = get (kids(i), "box");
+                  legend_axes_ylim = get (kids(i), "ylim");
+                  orig_axes_units = get (ca, "units");
+                  hlgnd = get (kids(i));
+
+                  unwind_protect
+                    set (ca, "units", "normalized");
+                    set (kids(i), "units", "normalized", "box", "off",
+                         "ylim", [-2, -1], "position", get (ca(1), "position"),
+                         "outerposition", get (ca(1), "outerposition"));
+
+                    ## Create a new set of lines with the appropriate
+                    ## displaynames, etc
+                    toberm = [];
+                    hobj = get (kids(i), "children");
+                    for j = numel (hobj) : -1 : 1
+                      if (! strcmp (get (hobj(j), "type"), "text"))
+                        continue;
+                      endif
+                      displayname = get (hobj(j), "string");
+                      ll = [];
+                      lm = [];
+                      for k = numel (hobj) : -1 : 1
+                        if (! strcmp (get (hobj(k), "type"), "line"))
+                          continue;
+                        endif
+                        if (get (hobj(j), "userdata")
+                            != get (hobj(k), "userdata"))
+                          continue;
+                        endif
+                        if (! strcmp (get (hobj(k), "linestyle"), "none"))
+                          ll = hobj(k);
+                        endif
+                        if (! strcmp (get (hobj(k), "marker"), "none"))
+                          lm = hobj(k);
+                        endif
+                      endfor
+
+                      if (! isempty (ll))
+                        if (!isempty (lm))
+                          toberm = [toberm, line("xdata",[0,0],"ydata",[0,0], "color", get(lm,"color"), "linestyle", get(ll,"linestyle"), "marker", get(lm,"marker"), "markeredgecolor", get(lm,"markeredgecolor"), "markerfacecolor", get(lm,"markerfacecolor"), "markersize", get (lm, "markersize"), "displayname", displayname, "parent", kids(i))];
+                        else
+                          toberm = [toberm, line("xdata",[0,0],"ydata",[0,0], "color", get(ll,"color"), "linestyle", get(ll,"linestyle"), "marker", "none", "displayname", displayname, "parent", kids(i))];
+                        endif
+                      elseif (! isempty (lm))
+                        toberm = [toberm, line("xdata",[0,0],"ydata",[0,0], "color", get(lm,"color"), "linestyle", "none", "marker", get(lm,"marker"), "markeredgecolor", get(lm,"markeredgecolor"), "markerfacecolor", get(lm,"markerfacecolor"), "markersize", get (lm, "markersize"), "displayname", displayname, "parent", kids(i))];
+                      endif
+                    endfor
+                    if (bg_is_set)
+                      fprintf (plot_stream, "set border linecolor rgb \"#%02x%02x%02x\"\n", 255 * (1 - bg));
+                    endif
+                    __go_draw_axes__ (kids(i), plot_stream, enhanced, mono,
+                                      bg_is_set, false, hlgnd);
+                  unwind_protect_cleanup
+                    ## Return axes "units" and "position" back to
+                    ## their original values.
+                    set (ca, "units", orig_axes_units);
+                    set (kids(i), "units", legend_axes_units,
+                         "box", legend_axes_box,
+                         "ylim", legend_axes_ylim,
+                         "position", legend_axes_position,
+                         "outerposition", legend_axes_outerposition);
+                    delete (toberm);
+                    bg_is_set = false;
+                  end_unwind_protect
+                endif
+              else
+                ## Rely upon listener to convert axes position
+                ## to "normalized" units.
+                orig_axes_units = get (kids(i), "units");
+                orig_axes_position = get (kids(i), "position");
+                unwind_protect
+                  set (kids(i), "units", "normalized");
+                  fg = get (kids(i), "color");
+                  if (isnumeric (fg) && strcmp (get (kids(i), "visible"), "on"))
+                    fprintf (plot_stream, "set obj 2 rectangle from graph 0,0 to graph 1,1 behind fc rgb \"#%02x%02x%02x\"\n", 255 * fg);
+                    fg_is_set = true;
+                  else
+                    fg_is_set = false;
+                  endif
+                  if (bg_is_set)
+                    fprintf (plot_stream, "set border linecolor rgb \"#%02x%02x%02x\"\n", 255 * (1 - bg));
+                  endif
+                  ## Find if this axes has an associated legend axes and pass it
+                  ## to __go_draw_axes__
+                  hlegend = [];
+                  fkids = get (h, "children");
+                  for j = 1 : numel(fkids)
+                    if (ishandle (fkids (j))
+                        && strcmp (get (fkids (j), "type"), "axes")
+                        && (strcmp (get (fkids (j), "tag"), "legend")))
+                      udata = get (fkids (j), "userdata");
+                      if (isscalar(udata.handle)
+                          && ! isempty (intersect (udata.handle, kids (i))))
+                        hlegend = get (fkids (j));
+                        break;
+                      endif
+                    endif
+                  endfor
+                  __go_draw_axes__ (kids(i), plot_stream, enhanced, mono,
+                                    bg_is_set, fg_is_set, hlegend);
+                unwind_protect_cleanup
+                  ## Return axes "units" and "position" back to
+                  ## their original values.
+                  set (kids(i), "units", orig_axes_units);
+                  set (kids(i), "position", orig_axes_position);
+                  bg_is_set = false;
+                  fg_is_set = false;
+                end_unwind_protect
+              endif
+            case "uimenu"
+              ## ignore uimenu objects
+            otherwise
+              error ("__go_draw_figure__: unknown object class, %s", type);
+          endswitch
+        endfor
+        fputs (plot_stream, "\nunset multiplot;\n");
+      else
+        fputs (plot_stream, "\nreset; clear;\n");
+        fflush (plot_stream);
+      endif
+    else
+      error ("__go_draw_figure__: expecting figure object, found `%s'",
+             htype);
+    endif
+  else
+    print_usage ();
+  endif
+
+endfunction
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/private/__marching_cube__.m	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,530 @@
+## Copyright (C) 2009-2011 Martin Helm
+##
+## 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 3 of the License, 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, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {Function File} {[@var{t}, @var{p}] =} __marching_cube__ (@var{x}, @var{y}, @var{z}, @var{val}, @var{iso})
+## @deftypefnx {Function File} {[@var{t}, @var{p}, @var{c}] =} __marching_cube__ (@var{x}, @var{y}, @var{z}, @var{val}, @var{iso}, @var{col})
+## Undocumented internal function.
+## @end deftypefn
+
+## -*- texinfo -*-
+## @deftypefn  {Function File} {[@var{t}, @var{p}] =} __marching_cube__ (@var{x}, @var{y}, @var{z}, @var{val}, @var{iso})
+## @deftypefnx {Function File} {[@var{t}, @var{p}, @var{c}] =} __marching_cube__ (@var{x}, @var{y}, @var{z}, @var{val}, @var{iso}, @var{col})
+##
+## Return the triangulation information @var{t} at points @var{p} for
+## the isosurface values resp. the volume data @var{val} and the iso
+## level @var{iso}.  It is considered that the volume data @var{val} is
+## given at the points @var{x}, @var{y} and @var{z} which are of type
+## three--dimensional numeric arrays.  The orientation of the triangles
+## is choosen such that the normals point from the higher values to the
+## lower values.
+##
+## Optionally the color data @var{col} can be passed to this function
+## whereas computed vertices color data @var{c} is returned as third
+## argument.
+##
+## The marching cube algorithm is well known and described, for example, at
+## Wikipedia.  The triangulation lookup table and the edge table used
+## here are based on Cory Gene Bloyd's implementation and can be found
+## beyond other surface and geometry stuff at Paul Bourke's website
+## @uref{http://local.wasp.uwa.edu.au/~pbourke/geometry/polygonise}.
+##
+## For example:
+##
+## @example
+## @group
+## N = 20;
+## lin = linspace(0, 2, N);
+## [x, y, z] = meshgrid (lin, lin, lin);
+##
+## c = (x-.5).^2 + (y-.5).^2 + (z-.5).^2;
+## [t, p] = __marching_cube__ (x, y, z, c, .5);
+##
+## figure ();
+## trimesh (t, p(:,1), p(:,2), p(:,3));
+## @end group
+## @end example
+##
+## Instead of the @command{trimesh} function the @command{patch}
+## function can be used to visualize the geometry.  For example:
+##
+## @example
+## @group
+## figure (); view (-38, 20);
+## pa = patch ("Faces", t, "Vertices", p, "FaceVertexCData", p, \
+##             "FaceColor", "interp", "EdgeColor", "none");
+##
+## ## Revert normals
+## set (pa, "VertexNormals", -get(pa, "VertexNormals"));
+##
+## ## Set lightning (available with the JHandles package)
+## # set (pa, "FaceLighting", "gouraud");
+## # light( "Position", [1 1 5]);
+## @end group
+## @end example
+##
+## @end deftypefn
+
+## Author: Martin Helm <martin@mhelm.de>
+
+function [T, p, col] = __marching_cube__ (xx, yy, zz, c, iso, colors)
+
+  persistent edge_table=[];
+  persistent tri_table=[];
+
+  calc_cols = false;
+  lindex = 4;
+
+  if (isempty (tri_table) || isempty (edge_table))
+    [edge_table, tri_table] = init_mc ();
+  endif
+
+  if ((nargin != 5 && nargin != 6) || (nargout != 2 && nargout != 3))
+    print_usage ();
+  endif
+
+  if (!ismatrix (xx) || !ismatrix (yy) || !ismatrix (zz) || !ismatrix (c) || ...
+    ndims (xx) != 3 || ndims (yy) != 3 || ndims (zz) != 3 || ndims (c) != 3)
+    error ("__marching_cube__: XX, YY, ZZ, C must be matrices of dim 3");
+  endif
+
+  if (!size_equal (xx, yy, zz, c))
+    error ("__marching_cube__: XX, YY, ZZ, C must be of equal size");
+  endif
+
+  if (any (size (xx) < [2 2 2]))
+    error ("__marching_cube__: grid size must be at least 2x2x2");
+  endif
+
+  if (!isscalar (iso))
+    error ("__marching_cube__: ISO must be scalar value");
+  endif
+
+  if (nargin == 6)
+    if ( !ismatrix (colors) || ndims (colors) != 3 || size (colors) != size (c) )
+      error ( "COLORS must be a matrix of dim 3 and of same size as C" );
+    endif
+    calc_cols = true;
+    lindex = 5;
+  endif
+
+  n = size (c) - 1;
+
+  ## phase I: assign information to each voxel which edges are intersected by
+  ## the isosurface
+  cc = zeros (n(1), n(2), n(3), "uint16");
+  cedge = zeros (size (cc), "uint16");
+
+  vertex_idx = {1:n(1), 1:n(2), 1:n(3); ...
+    2:n(1)+1, 1:n(2), 1:n(3); ...
+    2:n(1)+1, 2:n(2)+1, 1:n(3); ...
+    1:n(1), 2:n(2)+1, 1:n(3); ...
+    1:n(1), 1:n(2), 2:n(3)+1; ...
+    2:n(1)+1, 1:n(2), 2:n(3)+1; ...
+    2:n(1)+1, 2:n(2)+1, 2:n(3)+1; ...
+    1:n(1), 2:n(2)+1, 2:n(3)+1 };
+
+  ## calculate which vertices have values higher than iso
+  for ii=1:8
+    idx = c(vertex_idx{ii, :}) > iso;
+    cc(idx) = bitset (cc(idx), ii);
+  endfor
+
+  cedge = edge_table(cc+1); # assign the info about intersected edges
+  id =  find (cedge); # select only voxels which are intersected
+  if (isempty (id))
+    T = p = col = [];
+    return
+  endif
+
+  ## phase II: calculate the list of intersection points
+  xyz_off = [1, 1, 1; 2, 1, 1; 2, 2, 1; 1, 2, 1; 1, 1, 2;  2, 1, 2; 2, 2, 2; 1, 2, 2];
+  edges = [1 2; 2 3; 3 4; 4 1; 5 6; 6 7; 7 8; 8 5; 1 5; 2 6; 3 7; 4 8];
+  offset = sub2ind (size (c), xyz_off(:, 1), xyz_off(:, 2), xyz_off(:, 3)) -1;
+  pp = zeros (length (id), lindex, 12);
+  ccedge = [vec(cedge(id)), id];
+  ix_offset=0;
+  for jj=1:12
+    id__ = bitget (ccedge(:, 1), jj);
+    id_ = ccedge(id__, 2);
+    [ix iy iz] = ind2sub (size (cc), id_);
+    id_c = sub2ind (size (c), ix, iy, iz);
+    id1 = id_c + offset(edges(jj, 1));
+    id2 = id_c + offset(edges(jj, 2));
+    if (calc_cols)
+      pp(id__, 1:5, jj) = [vertex_interp(iso, xx(id1), yy(id1), zz(id1), ...
+        xx(id2), yy(id2), zz(id2), c(id1), c(id2), colors(id1), colors(id2)), ...
+        (1:size (id_, 1))' + ix_offset ];
+    else
+      pp(id__, 1:4, jj) = [vertex_interp(iso, xx(id1), yy(id1), zz(id1), ...
+        xx(id2), yy(id2), zz(id2), c(id1), c(id2)), ...
+        (1:size (id_, 1))' + ix_offset ];
+    endif
+    ix_offset += size (id_, 1);
+  endfor
+
+  ## phase III: calculate the triangulation from the point list
+  T = [];
+  tri = tri_table(cc(id)+1, :);
+  for jj=1:3:15
+    id_ = find (tri(:, jj)>0);
+    p = [id_, lindex*ones(size (id_, 1), 1),tri(id_, jj:jj+2)];
+    if (!isempty (p))
+      p1 = sub2ind (size (pp), p(:,1), p(:,2), p(:,3));
+      p2 = sub2ind (size (pp), p(:,1), p(:,2), p(:,4));
+      p3 = sub2ind (size (pp), p(:,1), p(:,2), p(:,5));
+      T = [T; pp(p1), pp(p2), pp(p3)];
+    endif
+  endfor
+
+  p = [];
+  col = [];
+  for jj = 1:12
+    idp = pp(:, lindex, jj) > 0;
+    if (any (idp))
+      p(pp(idp, lindex, jj), 1:3) = pp(idp, 1:3, jj);
+      if (calc_cols)
+        col(pp(idp, lindex, jj),1) = pp(idp, 4, jj);
+      endif
+    endif
+  endfor
+endfunction
+
+function p = vertex_interp(isolevel,p1x, p1y, p1z,...
+  p2x, p2y, p2z,valp1,valp2, col1, col2)
+
+  if (nargin == 9)
+    p = zeros (length (p1x), 3);
+  elseif (nargin == 11)
+    p = zeros (length (p1x), 4);
+  else
+    error ("__marching_cube__: wrong number of arguments");
+  endif
+  mu = zeros (length (p1x), 1);
+  id = abs (valp1-valp2) < (10*eps) .* (abs (valp1) .+ abs (valp2));
+  if (any (id))
+    p(id, 1:3) = [ p1x(id), p1y(id), p1z(id) ];
+    if (nargin == 11)
+      p(id, 4) = col1(id);
+    endif
+  endif
+  nid = !id;
+  if (any (nid))
+    mu(nid) = (isolevel - valp1(nid)) ./ (valp2(nid) - valp1(nid));
+    p(nid, 1:3) = [p1x(nid) + mu(nid) .* (p2x(nid) - p1x(nid)), ...
+      p1y(nid) + mu(nid) .* (p2y(nid) - p1y(nid)), ...
+      p1z(nid) + mu(nid) .* (p2z(nid) - p1z(nid))];
+    if (nargin == 11)
+      p(nid, 4) = col1(nid) + mu(nid) .* (col2(nid) - col1(nid));
+    endif
+  endif
+endfunction
+
+function [edge_table, tri_table] = init_mc()
+  edge_table = [
+  0x0  , 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c, ...
+  0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00, ...
+  0x190, 0x99 , 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c, ...
+  0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90, ...
+  0x230, 0x339, 0x33 , 0x13a, 0x636, 0x73f, 0x435, 0x53c, ...
+  0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30, ...
+  0x3a0, 0x2a9, 0x1a3, 0xaa , 0x7a6, 0x6af, 0x5a5, 0x4ac, ...
+  0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0, ...
+  0x460, 0x569, 0x663, 0x76a, 0x66 , 0x16f, 0x265, 0x36c, ...
+  0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60, ...
+  0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff , 0x3f5, 0x2fc, ...
+  0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0, ...
+  0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55 , 0x15c, ...
+  0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950, ...
+  0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc , ...
+  0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0, ...
+  0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc, ...
+  0xcc , 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0, ...
+  0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c, ...
+  0x15c, 0x55 , 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650, ...
+  0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc, ...
+  0x2fc, 0x3f5, 0xff , 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0, ...
+  0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c, ...
+  0x36c, 0x265, 0x16f, 0x66 , 0x76a, 0x663, 0x569, 0x460, ...
+  0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac, ...
+  0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa , 0x1a3, 0x2a9, 0x3a0, ...
+  0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c, ...
+  0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x33 , 0x339, 0x230, ...
+  0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c, ...
+  0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99 , 0x190, ...
+  0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c, ...
+  0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x0   ];
+
+  tri_table =[
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1;
+  3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1;
+  3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1;
+  3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1;
+  9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1;
+  1, 2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1;
+  9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1;
+  2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1;
+  8, 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1;
+  9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1;
+  4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1;
+  3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1;
+  1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1;
+  4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1;
+  4, 7, 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1;
+  9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1;
+  1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1;
+  5, 2, 10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1;
+  2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1;
+  9, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  0, 11, 2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1;
+  0, 5, 4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1;
+  2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1;
+  10, 3, 11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1;
+  4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1;
+  5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1;
+  5, 4, 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1;
+  9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1;
+  0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1;
+  1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1;
+  10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1;
+  8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1;
+  2, 10, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1;
+  7, 9, 5, 7, 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1;
+  9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1;
+  2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1;
+  11, 2, 1, 11, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1;
+  9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, -1, -1, -1, -1;
+  5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, -1;
+  11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, -1;
+  11, 10, 5, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  1, 8, 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1;
+  1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  1, 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1;
+  9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1;
+  5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1;
+  2, 3, 11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1;
+  0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1;
+  5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1;
+  6, 3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1;
+  0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1;
+  3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1;
+  6, 5, 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1;
+  5, 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1;
+  1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1;
+  10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1;
+  6, 1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1;
+  1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1;
+  8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1;
+  7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1;
+  3, 11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1;
+  5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1;
+  0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1;
+  9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, -1;
+  8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, -1, -1, -1, -1;
+  5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, -1;
+  0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, -1;
+  6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, -1, -1, -1, -1;
+  10, 4, 9, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  4, 10, 6, 4, 9, 10, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1;
+  10, 0, 1, 10, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1;
+  8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, -1, -1, -1, -1;
+  1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1;
+  3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, -1, -1, -1, -1;
+  0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1;
+  10, 4, 9, 10, 6, 4, 11, 2, 3, -1, -1, -1, -1, -1, -1, -1;
+  0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, -1, -1, -1, -1;
+  3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, -1, -1, -1, -1;
+  6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, -1;
+  9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, -1, -1, -1, -1;
+  8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, -1;
+  3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1;
+  6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1;
+  0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, -1, -1, -1, -1;
+  10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1;
+  10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1;
+  1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1;
+  2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, -1;
+  7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1;
+  7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, -1, -1, -1;
+  2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, -1;
+  1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, -1;
+  11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, -1;
+  8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1;
+  0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1;
+  7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  8, 1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1;
+  10, 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1;
+  2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1;
+  6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1;
+  7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1;
+  2, 7, 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1;
+  1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1;
+  10, 7, 6, 10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1;
+  10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1;
+  0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1;
+  7, 6, 10, 7, 10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1;
+  6, 8, 4, 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  3, 6, 11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1;
+  8, 6, 11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1;
+  9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1;
+  6, 8, 4, 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1;
+  1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1;
+  4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1;
+  10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1;
+  8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1;
+  0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1;
+  1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1;
+  8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1;
+  10, 1, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1;
+  4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1;
+  10, 9, 4, 6, 10, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1;
+  5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1;
+  11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1;
+  9, 5, 4, 10, 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1;
+  6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1;
+  7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1;
+  3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, -1;
+  7, 2, 3, 7, 6, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1;
+  9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, -1, -1, -1, -1;
+  3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, -1, -1, -1, -1;
+  6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, -1;
+  9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, -1, -1, -1, -1;
+  1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, -1;
+  4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, -1;
+  7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1, -1, -1;
+  6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1;
+  3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1;
+  0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1, -1;
+  6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1;
+  1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1, -1;
+  0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1;
+  11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1;
+  6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1;
+  5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1;
+  9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1;
+  1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, -1;
+  1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, -1;
+  10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, -1, -1, -1, -1;
+  0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  11, 5, 10, 7, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  11, 5, 10, 11, 7, 5, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1;
+  5, 11, 7, 5, 10, 11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1;
+  10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1;
+  11, 1, 2, 11, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1;
+  0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1;
+  9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1;
+  7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, -1;
+  2, 5, 10, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1;
+  8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, -1, -1, -1, -1;
+  9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, -1, -1, -1, -1;
+  9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, -1;
+  1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1;
+  9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1;
+  9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  5, 8, 4, 5, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1;
+  5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, -1, -1, -1, -1;
+  0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, -1, -1, -1, -1;
+  10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, -1;
+  2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, -1, -1, -1, -1;
+  0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, -1;
+  0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, -1;
+  9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1;
+  5, 10, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1;
+  3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, -1;
+  5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, -1, -1, -1, -1;
+  8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1;
+  0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, -1, -1, -1, -1;
+  9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  4, 11, 7, 4, 9, 11, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1;
+  0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, -1, -1, -1, -1;
+  1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, -1, -1, -1, -1;
+  3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, -1;
+  4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, -1, -1, -1, -1;
+  9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, -1;
+  11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1;
+  11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, -1, -1, -1, -1;
+  2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1;
+  9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, -1;
+  3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, -1;
+  1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1;
+  4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, -1;
+  4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1;
+  0, 1, 10, 0, 10, 8, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1;
+  3, 1, 10, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  1, 2, 11, 1, 11, 9, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1;
+  3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, -1, -1, -1, -1;
+  0, 2, 11, 8, 0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  2, 3, 8, 2, 8, 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1;
+  9, 10, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1;
+  1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1;
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ] + 1;
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/private/__next_line_color__.m	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,54 @@
+## Copyright (C) 2007-2011 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 3 of the License, 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, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {@var{rgb} =} __next_line_color__ (@var{reset})
+## Undocumented internal function.
+## @end deftypefn
+
+## Return the next line color in the rotation.
+
+## Author: jwe
+
+function rgb = __next_line_color__ (reset)
+
+  persistent color_rotation;
+  persistent num_colors;
+  persistent color_index;
+
+  if (nargin < 2)
+    if (nargin == 1)
+      if (reset || isempty (color_rotation))
+        color_rotation = get (gca (), "colororder");
+        num_colors = rows (color_rotation);
+        color_index = 1;
+      endif
+    elseif (! isempty (color_rotation))
+      rgb = color_rotation(color_index,:);
+      if (++color_index > num_colors)
+        color_index = 1;
+        __next_line_style__ ("incr");
+      endif
+    else
+      error ("__next_line_color__: color_rotation not initialized");
+    endif
+  else
+    print_usage ();
+  endif
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/private/__next_line_style__.m	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,58 @@
+## Copyright (C) 2010-2011 David Bateman
+##
+## 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 3 of the License, 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, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {@var{style} =} __next_line_style__ (@var{reset})
+## Undocumented internal function.
+## @end deftypefn
+
+## Return the next line style in the rotation.
+
+
+function [linestyle, marker] = __next_line_style__ (reset)
+
+  persistent style_rotation;
+  persistent num_styles;
+  persistent style_index;
+
+  if (nargin < 2)
+    if (nargin == 1)
+      if (ischar (reset) && strncmp (reset, "incr", 4))
+        if (isempty (style_rotation))
+          error ("__next_line_style__: style_rotation not initialized");
+        elseif (++style_index > num_styles)
+          style_index = 1;
+        endif
+      elseif (reset || isempty (style_rotation))
+        style_rotation = strsplit (get (gca (), "linestyleorder"), "|");
+        num_styles = length (style_rotation);
+        style_index = 1;
+      endif
+    elseif (! isempty (style_rotation))
+      options = __pltopt__ ("__next_line_style__",
+                            style_rotation (style_index));
+      linestyle = options.linestyle;
+      marker = options.marker;
+    else
+      error ("__next_line_style__: style_rotation not initialized");
+    endif
+  else
+    print_usage ();
+  endif
+
+endfunction
--- a/scripts/plot/private/__patch__.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/private/__patch__.m	Tue Sep 20 15:38:24 2011 -0400
@@ -31,7 +31,10 @@
 
   failed = false;
 
-  if (isstruct (varargin{1}))
+  if (isempty (varargin))
+    args = {"xdata", [0; 1; 1], "ydata", [0; 0; 1], "facecolor", "blue"};
+    args = setvertexdata (args);
+  elseif (isstruct (varargin{1}))
     if (isfield (varargin{1}, "vertices") && isfield (varargin{1}, "faces"))
       args{1} = "faces";
       args{2} = getfield(varargin{1}, "faces");
@@ -134,7 +137,7 @@
     endif
   else
     args = varargin;
-    if (any(cellfun (@(x) strcmpi(x,"faces") || strcmpi(x, "vertices"), args)))
+    if (any (strcmpi (args, "faces") | strcmpi (args, "vertices")))
       args = setdata (args);
     else
       args = setvertexdata (args);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/private/__print_parse_opts__.m	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,610 @@
+## Copyright (C) 2008-2011 David Bateman
+##
+## 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 3 of the License, 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, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {[@var{x}, @var{y}, @var{buttons}] =} ginput (@var{n})
+## Return which mouse buttons were pressed and keys were hit on the current
+## figure.  If @var{n} is defined, then wait for @var{n} mouse clicks
+## before returning.  If @var{n} is not defined, then @code{ginput} will
+## loop until the return key is pressed.
+## @end deftypefn
+
+function arg_st = __print_parse_opts__ (varargin)
+
+  persistent warn_on_missing_binary = true
+
+  arg_st.append_to_file = false;
+  arg_st.canvas_size = [];
+  arg_st.debug = false;
+  arg_st.debug_file = "octave-print-commands.log";
+  arg_st.devopt = "";
+  arg_st.epstool_binary = __quote_path__ (__find_binary__ ("epstool"));
+  arg_st.figure = get (0, "currentfigure");
+  arg_st.fig2dev_binary = __quote_path__ (__find_binary__ ("fig2dev"));
+  arg_st.fontsize = "";
+  arg_st.font = "";
+  arg_st.force_solid = 0; # 0=default, -1=dashed, +1=solid
+  arg_st.formatted_for_printing = false;
+  arg_st.ghostscript.binary = __quote_path__ (__ghostscript_binary__ ());
+  arg_st.ghostscript.debug = false;
+  arg_st.ghostscript.device = "";
+  arg_st.ghostscript.epscrop = true;
+  arg_st.ghostscript.level = [];
+  arg_st.ghostscript.output = "";
+  arg_st.ghostscript.papersize = "";
+  arg_st.ghostscript.pageoffset = [];
+  arg_st.ghostscript.resolution = 150;
+  arg_st.ghostscript.antialiasing = false;
+  arg_st.loose = false;
+  arg_st.lpr_binary = __quote_path__ (__find_binary__ ("lpr"));
+  arg_st.name = "";
+  arg_st.orientation = "";
+  arg_st.pstoedit_binary = __quote_path__ (__find_binary__ ("pstoedit"));
+  arg_st.preview = "";
+  arg_st.printer = "";
+  arg_st.send_to_printer = false;
+  arg_st.special_flag = "textnormal";
+  arg_st.tight_flag = false;
+  arg_st.use_color = 0; # 0=default, -1=mono, +1=color
+
+  if (isunix ())
+    arg_st.lpr_options = "-l";
+  elseif (ispc ())
+    arg_st.lpr_options = "-o l";
+  else
+    arg_st.lpr_options = "";
+  endif
+  arg_st.unlink = {};
+
+  if (nargin > 0 && isfigure (varargin{1}))
+    arg_st.figure = varargin{1};
+    varargin(1) = [];
+  endif
+
+  for i = 1:numel(varargin)
+    arg = strtrim (varargin{i});
+    if (ischar (arg))
+      if (strcmp (arg, "-color"))
+        arg_st.use_color = 1;
+      elseif (strcmp (arg, "-append"))
+        arg_st.append_to_file = true;
+      elseif (strcmp (arg, "-mono"))
+        arg_st.use_color = -1;
+      elseif (strcmp (arg, "-solid"))
+        arg_st.force_solid = 1;
+      elseif (strcmp (arg, "-dashed"))
+        arg_st.force_solid = -1;
+      elseif (strncmp (arg, "-portrait", numel (arg)))
+        arg_st.orientation = "portrait";
+      elseif (strncmp (arg, "-landscape", numel (arg)))
+        arg_st.orientation = "landscape";
+      elseif (strcmp (arg, "-loose"))
+        arg_st.loose = true;
+        arg_st.tight_flag = false;
+      elseif (strcmp (arg, "-tight"))
+        arg_st.loose = false;
+        arg_st.tight_flag = true;
+      elseif (strcmp (arg, "-textspecial"))
+        arg_st.special_flag = "textspecial";
+      elseif (any (strcmp (arg, {"-interchange", "-metafile", "-pict", "-tiff"})))
+        arg_st.preview = arg(2:end);
+      elseif (strncmp (arg, "-debug", 6))
+        arg_st.debug = true;
+        arg_st.ghostscript.debug = true;
+        if (length (arg) > 7)
+          arg_st.debug_file = arg(8:end);
+        endif
+      elseif (length (arg) > 2 && arg(1:2) == "-d")
+        arg_st.devopt = tolower (arg(3:end));
+      elseif (length (arg) > 2 && arg(1:2) == "-P")
+        arg_st.printer = arg;
+      elseif (strncmp (arg, "-EPSTOOL:", 9))
+        arg_st.epstool_binary = arg{10:end};
+      elseif (strncmp (arg, "-FIG2DEV:", 9))
+        arg_st.fig2dev_binary = arg{10:end};
+      elseif (strncmp (arg, "-PSTOEDIT:", 9))
+        arg_st.pstoedit_binary = arg{10:end};
+      elseif ((length (arg) > 2) && arg(1:2) == "-G")
+        arg_st.ghostscript.binary = file_in_path (getenv ("PATH"), arg(3:end));
+        if (isempty (arg_st.ghostscript.binary))
+          error ("print: Ghostscript binary ""%s"" could not be located",
+                 arg(3:end));
+        else
+          arg_st.ghostscript_binary = __quote_path__ (arg_st.ghostscript_binary);
+        endif
+      elseif (length (arg) > 2 && arg(1:2) == "-F")
+        idx = rindex (arg, ":");
+        if (idx)
+          arg_st.font = arg(3:idx-1);
+          arg_st.fontsize = str2num (arg(idx+1:end));
+        else
+          arg_st.font = arg(3:end);
+        endif
+      elseif (length (arg) > 2 && arg(1:2) == "-S")
+        arg_st.canvas_size = str2num (arg(3:end));
+      elseif (length (arg) > 2 && arg(1:2) == "-r")
+        arg_st.ghostscript.resolution = str2double (arg(3:end));
+      elseif (length (arg) > 2 && arg(1:2) == "-f")
+        arg_st.figure = str2num (arg(3:end));
+      elseif (length (arg) >= 1 && arg(1) == "-")
+        error ("print: unknown option `%s'", arg);
+      elseif (length (arg) > 0)
+        arg_st.name = arg;
+      endif
+    elseif (isfigure (arg))
+      arg_st.figure = arg;
+    else
+      error ("print: expecting inputs to be character string options or a figure handle");
+    endif
+  endfor
+
+  if (arg_st.ghostscript.resolution == 0)
+    ## Do as Matlab does.
+    arg_st.ghostscript.resolution = num2str (get (0, "screenpixelsperinch"));
+  endif
+
+  if (isempty (arg_st.orientation))
+    if (isfigure (arg_st.figure))
+      arg_st.orientation = get (arg_st.figure, "paperorientation");
+    else
+      ## Allows tests to be run without error.
+      arg_st.orientation = "portrait";
+    endif
+  endif
+
+  if (isempty (arg_st.ghostscript.binary))
+    arg_st.ghostscript.binary = __ghostscript_binary__ ();
+  endif
+
+  dot = rindex (arg_st.name, ".");
+  if (isempty (arg_st.devopt))
+    if (dot == 0)
+      arg_st.devopt = "psc";
+    else
+      arg_st.devopt = tolower (arg_st.name(dot+1:end));
+    endif
+  endif
+
+  if (arg_st.use_color == 0)
+    if (any (strcmp ({"ps", "ps2", "eps", "eps2"}, arg_st.devopt)))
+      arg_st.use_color = -1;
+    else
+      arg_st.use_color = 1;
+    endif
+  endif
+
+  if (strcmp (arg_st.devopt, "tex"))
+    arg_st.devopt = "epslatex";
+  elseif (strcmp (arg_st.devopt, "ill"))
+    arg_st.devopt = "aifm";
+  elseif (strcmp (arg_st.devopt, "cdr"))
+    arg_st.devopt = "corel";
+  elseif (strcmp (arg_st.devopt, "meta"))
+    arg_st.devopt = "emf";
+  elseif (strcmp (arg_st.devopt, "jpg"))
+    arg_st.devopt = "jpeg";
+  endif
+
+  dev_list = {"aifm", "corel", "fig", "png", "jpeg", ...
+              "gif", "pbm", "pbmraw", "dxf", "mf", ...
+              "svg", "hpgl", "ps", "ps2", "psc", ...
+              "psc2", "eps", "eps2", "epsc", "epsc2", ...
+              "emf", "pdf", "pslatex", "epslatex", "epslatexstandalone", ...
+              "pslatexstandalone", "pdflatexstandalone", ...
+              "pstex", "tiff", "tiffn" "tikz", "pcxmono", ...
+              "pcx24b", "pcx256", "pcx16", "pgm", "pgmraw", ...
+              "ppm", "ppmraw", "pdflatex", "texdraw", ...
+              "pdfcairo", "pngcairo", "pstricks", ...
+              "epswrite", "pswrite", "ps2write", "pdfwrite"};
+
+  suffixes = {"ai", "cdr", "fig", "png", "jpg", ...
+              "gif", "pbm", "pbm", "dxf", "mf", ...
+              "svg", "hpgl", "ps", "ps", "ps", ...
+              "ps", "eps", "eps", "eps", "eps", ...
+              "emf", "pdf", "tex", "tex", "tex", ...
+              "tex", "tex", ...
+              "ps", "tiff", "tiff", "tikz", "pcx", ...
+              "pcx", "pcx", "pcx", "pgm", "pgm", ...
+              "ppm", "ppm", "tex", "tex", ...
+              "pdf", "png", "tex", ...
+              "eps", "ps", "ps", "pdf"};
+
+  if (isfigure (arg_st.figure))
+    __graphics_toolkit__ = get (arg_st.figure, "__graphics_toolkit__");
+  else
+    ## Allow tests when no figures are present.
+    __graphics_toolkit__ = get (0, "defaultfigure__graphics_toolkit__");
+  endif
+
+  if (strcmp (__graphics_toolkit__, "gnuplot")
+      && __gnuplot_has_feature__ ("epslatex_implies_eps_filesuffix"))
+    suffixes(strncmp (dev_list, "epslatex", 8)) = {"eps"};
+  endif
+
+  match = strcmpi (dev_list, arg_st.devopt);
+  if (any (match))
+    default_suffix = suffixes {match};
+  else
+    default_suffix = arg_st.devopt;
+  endif
+
+  if (dot == 0 && ! isempty (arg_st.name))
+    arg_st.name = strcat (arg_st.name, ".", default_suffix);
+  endif
+
+  if (arg_st.append_to_file)
+    if (isempty (arg_st.name))
+      arg_st.append_to_file = false;
+    elseif (any (strcmpi (arg_st.devopt, {"eps", "eps2", "epsc", "epsc2", ...
+                                          "ps", "ps2", "psc", "psc2", "pdf"})))
+      have_ghostscript = ! isempty (__ghostscript_binary__ ());
+      if (have_ghostscript)
+        file_exists = ((numel (dir (arg_st.name)) == 1)
+                       && (! isdir (arg_st.name)));
+        if (! file_exists)
+          arg_st.append_to_file = false;
+        endif
+      else
+        arg_st.append_to_file = false;
+        warning ("print.m: appended output requires ghostscript to be installed");
+      endif
+    else
+      warning ("print.m: appended output is not supported for device '%s'",
+               arg_st.devopt);
+      arg_st.append_to_file = false;
+    endif
+  endif
+
+  if (! isempty (arg_st.printer) || isempty (arg_st.name))
+    arg_st.send_to_printer = true;
+  endif
+
+  if (any (strcmp (arg_st.devopt, {"ps", "ps2", "psc", "psc2", "pdf"})))
+    arg_st.formatted_for_printing = true;
+  endif
+
+  aliases = gs_aliases ();
+  if (any (strcmp (arg_st.devopt, fieldnames (aliases))))
+    arg_st.devopt = aliases.(arg_st.devopt);
+  endif
+
+  ## FIXME - eps2 & epsc2 needs to be handled
+  if (strcmp (arg_st.devopt, "pswrite"))
+    arg_st.ghostscript.level = 1;
+  elseif (strcmp (arg_st.devopt, "ps2write"))
+    arg_st.ghostscript.level = 2;
+  endif
+
+  if ((any (strcmp (arg_st.devopt, gs_device_list))
+       && ! arg_st.formatted_for_printing)
+      || any (strcmp (arg_st.devopt, {"pswrite", "ps2write", "pdfwrite"})))
+    ## Use ghostscript for graphic formats
+    arg_st.ghostscript.device = arg_st.devopt;
+    arg_st.ghostscript.output = arg_st.name;
+    arg_st.ghostscript.antialiasing = true;
+    if (arg_st.formatted_for_printing)
+      arg_st.ghostscript.epscrop = ! arg_st.loose;
+    else
+      ## pstoedit throws errors if the EPS file isn't cropped
+      arg_st.ghostscript.epscrop = true;
+    endif
+  elseif (all (! strcmp (arg_st.devopt, dev_list)))
+    ## Assume we are formating output for a printer
+    arg_st.formatted_for_printing = true;
+    arg_st.ghostscript.device = arg_st.devopt;
+    arg_st.ghostscript.output = arg_st.name;
+    arg_st.ghostscript.antialiasing = false;
+    arg_st.ghostscript.epscrop = ! arg_st.loose;
+  endif
+
+  if (isempty (arg_st.canvas_size))
+    if (isfigure (arg_st.figure))
+      [arg_st.ghostscript.papersize, paperposition] = ...
+                           gs_papersize (arg_st.figure, arg_st.orientation);
+    else
+      ## allows tests to be run
+      arg_st.ghostscript.papersize = "letter";
+      paperposition = [0.25, 2.50, 8.00, 6.00] * 72;
+    endif
+    arg_st.canvas_size = paperposition(3:4);
+    if (strcmp (__graphics_toolkit__, "gnuplot") && ! arg_st.ghostscript.epscrop)
+      arg_st.ghostscript.pageoffset = paperposition(1:2) - 50;
+    else
+      arg_st.ghostscript.pageoffset = paperposition(1:2);
+    endif
+  else
+    ## Convert canvas size to points from pixles.
+    arg_st.canvas_size = arg_st.canvas_size * 72 / arg_st.ghostscript.resolution;
+    arg_st.ghostscript.papersize = arg_st.canvas_size;
+    arg_st.ghostscript.epscrop = true;
+    arg_st.ghostscript.pageoffset = [0, 0];
+  endif
+
+  if (arg_st.formatted_for_printing)
+    arg_st.ghostscript.resolution = [];
+  else
+    arg_st.ghostscript.papersize = "";
+    arg_st.ghostscript.pageoffset = [0, 0];
+  endif
+
+  if (warn_on_missing_binary)
+    if (isempty (arg_st.ghostscript.binary))
+      warning ("print:missing_gs", "print.m: Ghostscript binary is not available.\nOnly eps output is available.");
+    else
+      if (isempty (arg_st.epstool_binary))
+        warning ("print:missing_epstool", "print.m: epstool binary is not available.\nSome output formats are not available.");
+      endif
+      if (isempty (arg_st.fig2dev_binary))
+        warning ("print:missing_fig2dev", "print.m: fig2dev binary is not available.\nSome output formats are not available.");
+      endif
+      if (isempty (arg_st.pstoedit_binary))
+        warning ("print:missing_pstoedit", "print.m: pstoedit binary is not available.\nSome output formats are not available.");
+      endif
+    endif
+    warn_on_missing_binary = false;
+  endif
+
+endfunction
+
+## Test blocks are not allowed (and not needed) for private functions
+#%!test
+%! opts = __print_parse_opts__ ();
+%! assert (opts.devopt, "pswrite");
+%! assert (opts.use_color, 1);
+%! assert (opts.send_to_printer, true);
+%! assert (opts.canvas_size, [576, 432]);
+%! assert (opts.ghostscript.device, "pswrite")
+
+#%!test
+%! opts = __print_parse_opts__ ("test.pdf", "-S640,480");
+%! assert (opts.canvas_size, [307.2, 230.4], 0.1);
+
+#%!test
+%! opts = __print_parse_opts__ ("-dpsc", "-append", "-loose");
+%! assert (opts.devopt, "pswrite");
+%! assert (opts.send_to_printer, true);
+%! assert (opts.use_color, 1);
+%! assert (opts.append_to_file, false);
+%! assert (opts.ghostscript.device, "pswrite")
+%! assert (opts.ghostscript.epscrop, false);
+
+#%!test
+%! opts = __print_parse_opts__ ("-deps", "-tight");
+%! assert (opts.tight_flag, true);
+%! assert (opts.send_to_printer, true);
+%! assert (opts.use_color, -1);
+%! assert (opts.ghostscript.device, "")
+
+#%!test
+%! opts = __print_parse_opts__ ("-djpg", "foobar", "-mono", "-loose");
+%! assert (opts.devopt, "jpeg")
+%! assert (opts.name, "foobar.jpg")
+%! assert (opts.ghostscript.device, "jpeg")
+%! assert (opts.ghostscript.epscrop, true);
+%! assert (opts.ghostscript.papersize, "");
+%! assert (opts.ghostscript.pageoffset, [0, 0]);
+%! assert (opts.send_to_printer, false);
+%! assert (opts.printer, "");
+%! assert (opts.use_color, -1);
+
+#%!test
+%! opts = __print_parse_opts__ ("-ddeskjet", "foobar", "-mono", "-Pmyprinter");
+%! assert (opts.ghostscript.output, "foobar.deskjet")
+%! assert (opts.ghostscript.device, "deskjet")
+%! assert (opts.devopt, "deskjet")
+%! assert (opts.send_to_printer, true);
+%! assert (opts.printer, "-Pmyprinter");
+%! assert (opts.use_color, -1);
+
+#%!test
+%! opts = __print_parse_opts__ ("-f5", "-dljet3");
+%! assert (opts.ghostscript.device, "ljet3")
+%! assert (strfind (opts.ghostscript.output, ".ljet3"))
+%! assert (opts.devopt, "ljet3")
+%! assert (opts.send_to_printer, true);
+%! assert (opts.figure, 5)
+
+function cmd = __quote_path__ (cmd)
+  if (any (cmd == " ") && ! (cmd(1) == """" && cmd(end) == """"))
+    cmd = strcat ("""", strrep (cmd, """", """"""), """");
+  endif
+endfunction
+
+function gs = __ghostscript_binary__ ()
+
+  persistent ghostscript_binary = ""
+  persistent warn_on_no_ghostscript = true
+  persistent warn_on_bad_gsc = true
+
+  if (isempty (ghostscript_binary))
+    GSC = getenv ("GSC");
+    if (exist (GSC, "file")
+        || (! isempty (GSC) && file_in_path (getenv ("PATH"), GSC)))
+      gs_binaries = {GSC};
+    elseif (! isempty (GSC) && warn_on_bad_gsc)
+      warning ("print:badgscenv",
+               "print.m: GSC environment variable not set properly");
+      warn_on_bad_gsc = false;
+      gs_binaries = {};
+    else
+      gs_binaries = {};
+    endif
+    if (isunix ())
+      ## Unix - Includes Mac OSX and Cygwin.
+      gs_binaries = horzcat (gs_binaries, {"gs", "gs.exe"});
+    else
+      ## pc - Includes Win32 and mingw.
+      gs_binaries = horzcat (gs_binaries, {"gs.exe", "gswin32c.exe"});
+    endif
+    n = 0;
+    while (n < numel (gs_binaries) && isempty (ghostscript_binary))
+      n = n + 1;
+      ghostscript_binary = file_in_path (getenv ("PATH"), gs_binaries{n});
+    endwhile
+    if (warn_on_no_ghostscript && isempty (ghostscript_binary))
+      warning ("print:noghostscript",
+               "print.m: ghostscript not found in PATH");
+      warn_on_no_ghostscript = false;
+    endif
+  endif
+
+  gs = ghostscript_binary;
+
+endfunction
+
+function bin = __find_binary__ (binary)
+
+  persistent data = struct ()
+
+  if (! isfield (data, binary))
+    ## Reinitialize when `user_binaries' is present.
+    data.(binary).bin = "";
+    data.(binary).warn_on_absence = false;
+  endif
+
+  if (isempty (data.(binary).bin))
+    if (isunix ())
+      ## Unix - Includes Mac OSX and Cygwin.
+      binaries = strcat (binary, {"", ".exe"});
+    else
+      ## pc - Includes Win32 and mingw.
+      binaries = strcat (binary, {".exe"});
+    endif
+    n = 0;
+    while (n < numel (binaries) && isempty (data.(binary).bin))
+      n = n + 1;
+      data.(binary).bin = file_in_path (getenv ("PATH"), binaries{n});
+    endwhile
+    if (isempty (data.(binary).bin) && data.(binary).warn_on_absence)
+      warning (sprintf ("print:no%s", binary),
+               "print.m: '%s' not found in PATH", binary);
+      data.(binary).warn_on_absence = false;
+    endif
+  endif
+
+  bin = data.(binary).bin;
+
+endfunction
+
+function [papersize, paperposition] = gs_papersize (hfig, paperorientation)
+  persistent papertypes papersizes
+
+  if (isempty (papertypes))
+    papertypes = {"usletter", "uslegal",     "a0",     "a1", ...
+                        "a2",      "a3",     "a4",     "a5", ...
+                        "b0",      "b1",     "b2",     "b3", ...
+                        "b4",      "b5", "arch-a", "arch-b", ...
+                    "arch-c",  "arch-d", "arch-e",      "a", ...
+                         "b",       "c",      "d",      "e", ...
+                   "tabloid"};
+    papersizes = [ 8.5, 11.0;  8.5, 14.0; 33.1, 46.8; 23.4, 33.1;
+                  16.5, 23.4; 11.7, 16.5;  8.3, 11.7;  5.8,  8.3;
+                  39.4, 55.7; 27.8, 39.4; 19.7, 27.8; 13.9, 19.7;
+                   9.8, 13.9;  6.9,  9.8;  9.0, 12.0; 12.0, 18.0;
+                  18.0, 24.0; 24.0, 36.0; 36.0, 48.0;  8.5, 11.0;
+                  11.0, 17.0; 18.0, 24.0; 24.0, 36.0; 36.0, 48.0;
+                  11.0, 17.0] * 72;
+  endif
+
+  papertype = get (hfig, "papertype");
+  paperunits = get (hfig, "paperunits");
+  paperposition = get (hfig, "paperposition");
+  if (strcmp (papertype, "<custom>"))
+    papersize = get (hfig, "papersize");
+    papersize = convert2points (papersize , paperunits);
+  else
+    papersize = papersizes (strcmp (papertypes, papertype), :);
+  endif
+
+  if (strcmp (paperunits, "normalized"))
+    paperposition = paperposition .* papersize([1,2,1,2]);
+  else
+    paperposition = convert2points (paperposition, paperunits);
+  endif
+
+  ## FIXME - This will be obsoleted by listeners for paper properties.
+  ##         Papersize is tall when portrait,and wide when landscape.
+  if ((papersize(1) > papersize(2) && strcmpi (paperorientation, "portrait"))
+      || (papersize(1) < papersize(2) && strcmpi (paperorientation, "landscape")))
+    papersize = papersize ([2,1]);
+    paperposition = paperposition([2,1,4,3]);
+  endif
+
+  if ((! strcmp (papertype, "<custom>")) && (strcmp (paperorientation, "portrait")))
+    ## For portrait use the ghostscript name
+    papersize = papertype;
+    papersize(papersize=="-") = "";
+    papersize = strrep (papersize, "us", "");
+    switch (papersize)
+    case "a"
+      papersize = "letter";
+    case {"b", "tabloid"}
+      papersize = "11x17";
+    case {"c", "d", "e"}
+      papersize = strcat ("arch", papersize);
+    endswitch
+    if (strncmp (papersize, "arch", 4))
+      papersize(end) = upper (papersize(end));
+    endif
+  endif
+
+endfunction
+
+function value = convert2points (value, units)
+    switch (units)
+    case "inches"
+      value = value * 72;
+    case "centimeters"
+      value = value * 72 / 2.54;
+    case "normalized"
+      error ("print:customnormalized",
+             "print.m: papersize=='<custom>' and paperunits='normalized' may not be combined");
+    endswitch
+endfunction
+
+function device_list = gs_device_list ();
+  ## Graphics formats/languages, not priners.
+  device_list = {"bmp16"; "bmp16m"; "bmp256"; "bmp32b"; "bmpgray"; ...
+                 "epswrite"; "jpeg"; "jpegcymk"; "jpeggray"; "pbm"; ...
+                 "pbmraw"; "pcx16"; "pcx24b"; "pcx256"; "pcx2up"; ...
+                 "pcxcmyk"; "pcxgray"; "pcxmono"; "pdfwrite"; "pgm"; ...
+                 "pgmraw"; "pgnm"; "pgnmraw"; "png16"; "png16m"; ...
+                 "png256"; "png48"; "pngalpha"; "pnggray"; "pngmono"; ...
+                 "pnm"; "pnmraw"; "ppm"; "ppmraw"; "ps2write"; ...
+                 "pswrite"; "tiff12nc"; "tiff24nc"; "tiff32nc"; ...
+                 "tiffcrle"; "tiffg3"; "tiffg32d"; "tiffg4"; ...
+                 "tiffgray"; "tifflzw"; "tiffpack"; "tiffsep"};
+endfunction
+
+function aliases = gs_aliases ();
+  ## Aliases for other devices: "bmp", "png", "tiff", "tiffn", "pdf",
+  ##                            "ps", "ps2", "psc", "psc2"
+  ##
+  ## eps, epsc, eps2, epsc2 are not included here because those are
+  ## are generated by the graphics toolkit.
+  aliases.bmp = "bmp32b";
+  aliases.pdf = "pdfwrite";
+  aliases.png = "png16m";
+  aliases.ps = "pswrite";
+  aliases.ps2 = "ps2write";
+  aliases.psc = "pswrite";
+  aliases.psc2 = "ps2write";
+  aliases.tiff = "tiff24nc";
+  aliases.tiffn = "tiff24nc";
+endfunction
+
--- a/scripts/plot/private/__quiver__.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/private/__quiver__.m	Tue Sep 20 15:38:24 2011 -0400
@@ -125,8 +125,8 @@
       sd = sqrt (dx.^2 + dy.^2 + dz.^2) / len;
       if (sd != 0)
         s = sqrt(2) * autoscale * sd;
-      else # special case of identical points with multiple vectors 
-        s = autoscale; 
+      else # special case of identical points with multiple vectors
+        s = autoscale;
       endif
       uu = s * u;
       vv = s * v;
--- a/scripts/plot/private/__scatter__.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/private/__scatter__.m	Tue Sep 20 15:38:24 2011 -0400
@@ -368,14 +368,14 @@
     if (isempty (z1))
       for i = 1 : length (hlist)
         set (hlist(i), "vertices", [x1(i), y1(i)], "cdata",
-             reshape(c1(i,:),[1, size(c1)(2:end)]), 
+             reshape(c1(i,:),[1, size(c1)(2:end)]),
              "facevertexcdata", c1(i,:),
              "markersize", size1(i));
       endfor
     else
       for i = 1 : length (hlist)
         set (hlist(i), "vertices", [x1(i), y1(i), z1(i)], "cdata",
-             reshape(c1(i,:),[1, size(c1)(2:end)]), 
+             reshape(c1(i,:),[1, size(c1)(2:end)]),
              "facevertexcdata", c1(i,:),
              "markersize", size1(i));
       endfor
--- a/scripts/plot/rectangle.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/rectangle.m	Tue Sep 20 15:38:24 2011 -0400
@@ -25,15 +25,15 @@
 ## @deftypefnx {Function File} {@var{h} =} rectangle (@dots{})
 ##
 ## Draw rectangular patch defined by @var{pos} and @var{curv}.  The variable
-## @code{@var{pos}(1 : 2)} defines the lower left-hand corner of the patch
-## and @code{@var{pos}(3 : 4)} defines its width and height.  By default, the
+## @code{@var{pos}(1:2)} defines the lower left-hand corner of the patch
+## and @code{@var{pos}(3:4)} defines its width and height.  By default, the
 ## value of @var{pos} is @code{[0, 0, 1, 1]}.
 ##
 ## The variable @var{curv} defines the curvature of the sides of the rectangle
 ## and may be a scalar or two-element vector with values between 0 and 1.
 ## A value of 0 represents no curvature of the side, whereas a value of 1
 ## means that the side is entirely curved into the arc of a circle.
-## If @var{curv} is a two-element vector, then the first element is the 
+## If @var{curv} is a two-element vector, then the first element is the
 ## curvature along the x-axis of the patch and the second along y-axis.
 ##
 ## If @var{curv} is a scalar, it represents the curvature of the shorter of the
@@ -41,11 +41,11 @@
 ## by
 ##
 ## @example
-## min (pos (1: 2)) / max (pos (1:2)) * curv
+## min (pos (1:2)) / max (pos (1:2)) * curv
 ## @end example
 ##
-## Other properties are passed to the underlying patch command.  If called 
-## with an output argument, @code{rectangle} returns the handle to the 
+## Other properties are passed to the underlying patch command.  If called
+## with an output argument, @code{rectangle} returns the handle to the
 ## rectangle.
 ## @end deftypefn
 ## @seealso{patch}
--- a/scripts/plot/refreshdata.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/refreshdata.m	Tue Sep 20 15:38:24 2011 -0400
@@ -83,7 +83,7 @@
     obj = get (h (i));
     fldnames = fieldnames (obj);
     m = regexpi (fieldnames(obj), '^.+datasource$', "match");
-    idx = cellfun (@(x) !isempty(x), m);
+    idx = ! cellfun ("isempty", m);
     if (any (idx))
       tmp = m(idx);
       props = [props; {vertcat(tmp{:})}];
--- a/scripts/plot/semilogx.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/semilogx.m	Tue Sep 20 15:38:24 2011 -0400
@@ -59,3 +59,46 @@
   end_unwind_protect
 
 endfunction
+
+%!demo
+%! x = 1:0.01:10;
+%! y = (x .* (1 + rand (size (x)))) .^ 2;
+%! semilogx (y, x);
+
+%!demo
+%! clf ();
+%! a = logspace (-5, 1, 10);
+%! b =-logspace (-5, 1, 10);
+%!
+%! subplot (1, 2, 1)
+%! semilogx (b, a)
+%! xlabel ('semilogx (a, b)')
+%!
+%! subplot (1, 2, 2)
+%! semilogx (abs (b), a)
+%! set (gca, 'ydir', 'reverse')
+%! xlabel ('semilogx (a, abs (b))')
+
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   a = logspace (-5, 1, 10);
+%!   b = logspace (-5, 1, 10);
+%!   semilogx (a, b)
+%!   assert (get (gca, "xscale"), "log");
+%!   assert (get (gca, "yscale"), "linear");
+%! unwind_protect_cleanup
+%! close (hf);
+%! end_unwind_protect
+
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   a = logspace (-5, 1, 10);
+%!   b =-logspace (-5, 1, 10);
+%!   semilogx (a, b)
+%!   axis tight
+%!   assert (all (get (gca, "ytick") < 0));
+%! unwind_protect_cleanup
+%! close (hf);
+%! end_unwind_protect
--- a/scripts/plot/semilogy.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/semilogy.m	Tue Sep 20 15:38:24 2011 -0400
@@ -60,3 +60,48 @@
   end_unwind_protect
 
 endfunction
+
+%!demo
+%! x = 1:0.01:10;
+%! y = (x .* (1 + rand (size (x)))) .^ 2;
+%! semilogy (x, y);
+
+%!demo
+%! clf ();
+%! a = logspace (-5, 1, 10);
+%! b =-logspace (-5, 1, 10);
+%!
+%! subplot (1, 2, 1)
+%! semilogy (a, b)
+%! xlabel ('semilogy (a, b)')
+%!
+%! subplot (1, 2, 2)
+%! semilogy (a, abs (b))
+%! set (gca, 'ydir', 'reverse')
+%! xlabel ('semilogy (a, abs (b))')
+
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   a = logspace (-5, 1, 10);
+%!   b = logspace (-5, 1, 10);
+%!   semilogy (a, b)
+%!   assert (get (gca, "yscale"), "log");
+%!   assert (get (gca, "xscale"), "linear");
+%! unwind_protect_cleanup
+%! close (hf);
+%! end_unwind_protect
+
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   a = logspace (-5, 1, 10);
+%!   b =-logspace (-5, 1, 10);
+%!   semilogy (a, b)
+%!   axis tight
+%!   assert (all (get (gca, "ytick") < 0));
+%! unwind_protect_cleanup
+%! close (hf);
+%! end_unwind_protect
+
+
--- a/scripts/plot/subplot.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/subplot.m	Tue Sep 20 15:38:24 2011 -0400
@@ -124,7 +124,22 @@
     units = "normalized";
     set (0, "defaultaxesunits", units);
     set (cf, "units", "pixels");
-    pos = subplot_position (rows, cols, index, "position");
+
+    ## FIXME: At the moment we force gnuplot to use the aligned mode
+    ##        which will set "activepositionproperty" to "position".
+    ##        Τhis can yield to text overlap between labels and titles
+    ##        see bug #31610
+    if (strcmp (get (cf, "__graphics_toolkit__"), "gnuplot"))
+      align_axes = true;
+    endif
+
+    if (align_axes)
+      pos = subplot_position (rows, cols, index, "position");
+    elseif (strcmp (get (cf, "__graphics_toolkit__"), "gnuplot"))
+      pos = subplot_position (rows, cols, index, "outerpositiontight");
+    else
+      pos = subplot_position (rows, cols, index, "outerposition");
+    endif
 
     set (cf, "nextplot", "add");
 
@@ -144,7 +159,11 @@
             || strcmp (get (child, "tag"), "colorbar"))
           continue;
         endif
-        objpos = get (child, "position");
+        if (align_axes)
+          objpos = get (child, "position");
+        else
+          objpos = get (child, "outerposition");
+        endif
         if (all (objpos == pos) && ! replace_axes)
           ## If the new axes are in exactly the same position as an
           ## existing axes object, use the existing axes.
@@ -170,14 +189,13 @@
 
     if (found)
       set (cf, "currentaxes", tmp);
+    elseif (align_axes)
+      tmp = axes ("box", "off", "position", pos);
+    elseif (strcmp (get (cf, "__graphics_toolkit__"), "gnuplot"))
+      tmp = axes ("box", "off", "outerposition", pos);
     else
-      outpos = subplot_position (rows, cols, index, "outerposition");
-      tmp = axes ("looseinset", [0 0 0 0], "box", "off",
-                  "outerposition", outpos, "position", pos);
-    endif
-
-    if (align_axes || strcmp (get (cf, "__graphics_toolkit__"), "gnuplot"))
-      set (tmp, "activepositionproperty", "position");
+      tmp = axes ("looseinset", [0 0 0 0], "box", "off", "outerposition", pos,
+                  "autopos_tag", "subplot");
     endif
 
   unwind_protect_cleanup
@@ -193,67 +211,55 @@
 
 function pos = subplot_position (rows, cols, index, position_property)
 
-  defaultaxesposition = get (0, "defaultaxesposition");
-  defaultaxesouterposition = get (0, "defaultaxesouterposition");
-
   if (rows == 1 && cols == 1)
     ## Trivial result for subplot (1,1,1)
     if (strcmpi (position_property, "position"))
-      pos = defaultaxesposition;
+      pos = get (0, "defaultaxesposition");
     else
-      pos = defaultaxesouterposition;
+      pos = get (0, "defaultaxesouterposition");
     endif
     return
   endif
 
-  ## The outer margins surrounding all subplot "positions" are independent of
-  ## the number of rows and/or columns
-  margins.left   = defaultaxesposition(1);
-  margins.bottom = defaultaxesposition(2);
-  margins.right  = 1.0 - margins.left - defaultaxesposition(3);
-  margins.top    = 1.0 - margins.bottom - defaultaxesposition(4);
-
-  ## Fit from Matlab experiments
-  pc = 1 ./ [0.1860, (margins.left + margins.right - 1)];
-  margins.column = 1 ./ polyval (pc , cols);
-  pr = 1 ./ [0.2282, (margins.top + margins.bottom - 1)];
-  margins.row    = 1 ./ polyval (pr , rows);
-
-  ## Calculate the width/height of the subplot axes "position".
-  ## This is also consistent with Matlab
-  width = 1 - margins.left - margins.right - (cols-1)*margins.column;
-  width = width / cols;
-  height = 1 - margins.top - margins.bottom - (rows-1)*margins.row;
-  height = height / rows;
+  if (strcmp (position_property, "outerposition")
+      || strcmp (position_property, "outerpositiontight"))
+    margins.left   = 0.05;
+    margins.bottom = 0.05;
+    margins.right  = 0.05;
+    margins.top    = 0.05;
+    if (strcmp (position_property, "outerpositiontight"))
+      margins.column = 0.;
+      margins.row = 0.;
+    else
+      margins.column = 0.04 / cols;
+      margins.row = 0.04 / rows;
+    endif
+    width = 1 - margins.left - margins.right - (cols-1)*margins.column;
+    width = width / cols;
+    height = 1 - margins.top - margins.bottom - (rows-1)*margins.row;
+    height = height / rows;
+  else
+    defaultaxesposition = get (0, "defaultaxesposition");
 
-  if (strcmp (position_property, "outerposition") )
-    ## Calculate the inset of the position relative to the outerposition
-    ## The outerpositions are assumed to be tiled. Matlab's implementation
-    ## has outerposition overlap.
-    if (rows > 1)
-      ## Title on top and xlabel & xticks on bottom
-      inset.top = margins.row * (1/3);
-      inset.bottom = margins.row * (2/3);
-      ## Matlab behavior is approximately ...
-      % inset.bottom = margins.row;
-    else
-      inset.bottom = margins.bottom;
-      inset.top = margins.top;
-    endif
-    if (cols > 1)
-      ## ylabel & yticks on left and some overhang for xticks on right
-      x = 0.1;
-      inset.right = x * margins.column;
-      inset.left = (1 - x) * margins.column;
-    else
-      inset.left  = margins.left;
-      inset.right = margins.right;
-    endif
-    ## Apply the inset to the geometries for the "position" property.
-    margins.column = margins.column - inset.right - inset.left;
-    margins.row = margins.row - inset.top - inset.bottom;
-    width = width + inset.right + inset.left;
-    height = height + inset.top + inset.bottom;
+    ## The outer margins surrounding all subplot "positions" are independent
+    ## of the number of rows and/or columns
+    margins.left   = defaultaxesposition(1);
+    margins.bottom = defaultaxesposition(2);
+    margins.right  = 1.0 - margins.left - defaultaxesposition(3);
+    margins.top    = 1.0 - margins.bottom - defaultaxesposition(4);
+
+    ## Fit from Matlab experiments
+    pc = 1 ./ [0.1860, (margins.left + margins.right - 1)];
+    margins.column = 1 ./ polyval (pc , cols);
+    pr = 1 ./ [0.2282, (margins.top + margins.bottom - 1)];
+    margins.row    = 1 ./ polyval (pr , rows);
+
+    ## Calculate the width/height of the subplot axes "position".
+    ## This is also consistent with Matlab
+    width = 1 - margins.left - margins.right - (cols-1)*margins.column;
+    width = width / cols;
+    height = 1 - margins.top - margins.bottom - (rows-1)*margins.row;
+    height = height / rows;
   endif
 
   ## Index offsets from the lower left subplot
@@ -265,12 +271,6 @@
   x0 = xi .* (width + margins.column) + margins.left;
   y0 = yi .* (height + margins.row) + margins.bottom;
 
-  if (strcmp (position_property, "outerposition") )
-    ## Shift from position(1:2) to outerposition(1:2)
-    x0 = x0 - inset.left;
-    y0 = y0 - inset.bottom;
-  endif
-
   if (numel(x0) > 1)
     ## subplot (row, col, m:n)
     x1 = max (x0(:)) + width;
--- a/scripts/plot/surface.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/surface.m	Tue Sep 20 15:38:24 2011 -0400
@@ -136,6 +136,10 @@
     else
       error ("surface: Z argument must be a matrix");
     endif
+  elseif (firststring == 1)
+    x = 1:3;
+    y = (x).';
+    c = z = eye(3);
   else
     bad_usage = true;
   endif
@@ -155,3 +159,24 @@
   endif
 
 endfunction
+
+## Mark file as being tested.  Tests for surface are in
+## surf.m, surfc.m, surfl.m, and pcolor.m
+
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   h = surface;
+%!   assert (findobj (hf, "type", "surface"), h);
+%!   assert (get (h, "xdata"), 1:3, eps);
+%!   assert (get (h, "ydata"), (1:3)', eps);
+%!   assert (get (h, "zdata"), eye(3));
+%!   assert (get (h, "cdata"), eye(3));
+%!   assert (get (h, "type"), "surface");
+%!   assert (get (h, "linestyle"), get (0, "defaultsurfacelinestyle"));
+%!   assert (get (h, "linewidth"), get (0, "defaultsurfacelinewidth"), eps);
+%!   assert (get (h, "marker"), get (0, "defaultsurfacemarker"));
+%!   assert (get (h, "markersize"), get (0, "defaultsurfacemarkersize"));
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
--- a/scripts/plot/surfc.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/surfc.m	Tue Sep 20 15:38:24 2011 -0400
@@ -45,7 +45,26 @@
   drawnow ();
   zmin = get (ax, "zlim")(1);
 
-  [c, tmp2] = __contour__ (ax, zmin, varargin{:});
+  # don't pass axis handle and/or string arguments to __contour__()
+  stop_idx = nargin;
+  for i = 2 : nargin
+    if (ischar (varargin{i}))
+      stop_idx = i - 1;
+      break;
+    endif
+  endfor
+
+  start_idx = 1;
+  if (ishandle (varargin{1}))
+    start_idx = 2;
+  endif
+
+  if (stop_idx - start_idx == 1 || stop_idx - start_idx == 3)
+    #don't pass a color matrix c to __contour__
+    stop_idx -= 1;
+  endif
+
+  [c, tmp2] = __contour__ (ax, zmin, varargin{start_idx:stop_idx});
 
   tmp = [tmp; tmp2];
 
--- a/scripts/plot/text.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/text.m	Tue Sep 20 15:38:24 2011 -0400
@@ -47,15 +47,33 @@
     endif
 
     label = varargin{offset};
-    if (ischar (label) || iscellstr (label))
-      varargin(1:offset) = [];
-      if (ischar (label))
+    varargin(1:offset) = [];
+
+    nx = numel (x);
+    ny = numel (y);
+    nz = numel (z);
+    if (ischar (label) || isnumeric (label))
+      nt = size (label, 1);
+      if (nx > 1 && nt == 1)
+        ## Mutiple text objects with same string
+        label = repmat ({label}, [nx, 1]);
+        nt = nx;
+      elseif (nx > 1 && nt == nx)
+        ## Mutiple text objects with different strings
         label = cellstr (label);
+      elseif (ischar (label))
+        ## Single text object with one or more lines
+        label = {label};
       endif
-      n = numel (label);
-      nx = numel (x);
-      ny = numel (y);
-      nz = numel (z);
+    elseif (iscell (label))
+      nt = numel (label);
+      if (nx > 1 && nt == 1)
+        label = repmat ({label}, [nx, 1]);
+        nt = nx;
+      elseif (! (nx > 1 && nt == nx))
+        label = {label};
+        nt = 1;
+      endif
     else
       error ("text: expecting LABEL to be a character string or cell array of character strings");
     endif
@@ -63,35 +81,35 @@
     x = y = z = 0;
     nx = ny = nz = 1;
     label = {""};
-    n = 1;
+    nt = 1;
   endif
 
   if (rem (numel (varargin), 2) == 0)
 
-    if (nx == ny && nx == nz)
+    if (nx == ny && nx == nz && (nt == nx || nt == 1 || nx == 1))
       pos = [x(:), y(:), z(:)];
       ca = gca ();
-      tmp = zeros (n, 1);
-      if (n == 1)
-        label = label{1};
-        for i = 1:nx
-          tmp(i) = __go_text__ (ca, "string", label,
+      tmp = zeros (nt, 1);
+      if (nx == 1)
+        ## TODO - Modify __go_text__() to accept cell-strings
+        tmp = __go_text__ (ca, "string", "foobar",
+                           varargin{:},
+                           "position", pos);
+        set (tmp, "string", label{1});
+      elseif (nt == nx)
+        for n = 1:nt
+          tmp(n) = __go_text__ (ca, "string", label{n},
                                 varargin{:},
-                                "position", pos(i,:));
-        endfor
-        __request_drawnow__ ();
-      elseif (n == nx)
-        for i = 1:nx
-          tmp(i) = __go_text__ (ca, "string", label{i},
-                                varargin{:},
-                                "position", pos(i,:));
+                                "position", pos(n,:));
         endfor
         __request_drawnow__ ();
       else
         error ("text: dimension mismatch for coordinates and LABEL");
       endif
+    elseif (nt == nx || nt == 1 || nx == 1)
+      error ("text: dimension mismatch for coordinates");
     else
-      error ("text: dimension mismatch for coordinates");
+      error ("text: mismatch betwween coordinates and strings");
     endif
 
     if (nargout > 0)
@@ -142,3 +160,91 @@
 %! endfor
 %! caxis ([-100 100])
 %! title ("Vertically Aligned at Bottom")
+
+%!demo
+%! clf
+%! axis ([0 8 0 8])
+%! title (["1st title";"2nd title"])
+%! xlabel (["1st xlabel";"2nd xlabel"])
+%! ylabel (["1st ylabel";"2nd ylabel"])
+%! text (4, 4, {"Hello", "World"}, ...
+%!       "horizontalalignment", "center", ...
+%!       "verticalalignment", "middle")
+%! grid on
+
+%!demo
+%! clf
+%! h = mesh (peaks, "edgecolor", 0.7 * [1 1 1], ...
+%!                  "facecolor", "none", ...
+%!                  "facealpha", 0);
+%! title (["1st title";"2nd title"])
+%! xlabel (["1st xlabel";"2nd xlabel"])
+%! ylabel (["1st ylabel";"2nd ylabel"])
+%! zlabel (["1st zlabel";"2nd zlabel"])
+%! text (0, 0, 5, {"Hello", "World"}, ...
+%!       "horizontalalignment", "center", ...
+%!       "verticalalignment", "middle")
+%! hold on
+%! plot3 (0, 0, 5, "+k")
+%!
+
+%!demo
+%! clf
+%! h = text (0.5, 0.3, "char");
+%! assert ("char", class (get (h, "string")))
+%! h = text (0.5, 0.4, ["char row 1"; "char row 2"]);
+%! assert ("char", class (get (h, "string")))
+%! h = text (0.5, 0.6, {"cell2str (1,1)", "cell2str (1,2)"; "cell2str (2,1)", "cell2str (2,2)"});
+%! assert ("cell", class (get (h, "string")))
+%! h = text (0.5, 0.8, "foobar");
+%! set (h, "string", 1:3)
+%! h = text ([0.1, 0.1], [0.3, 0.4], "one string & two objects");
+%! assert ("char", class (get (h(1), "string")))
+%! assert ("char", class (get (h(2), "string")))
+%! h = text ([0.1, 0.1], [0.5, 0.6], {"one cellstr & two objects"});
+%! assert ("cell", class (get (h(1), "string")))
+%! assert ("cell", class (get (h(2), "string")))
+%! h = text ([0.1, 0.1], [0.7, 0.8], {"cellstr 1 object 1", "cellstr 2 object 2"});
+%! assert ("char", class (get (h(1), "string")))
+%! assert ("char", class (get (h(2), "string")))
+%! h = text ([0.1, 0.1], [0.1, 0.2], ["1st string & 1st object"; "2nd string & 2nd object"]);
+%! assert ("char", class (get (h(1), "string")))
+%! assert ("char", class (get (h(2), "string")))
+%! h = text (0.7, 0.6, "single string");
+%! assert ("char", class (get (h, "string")))
+%! h = text (0.7, 0.5, {"single cell-string"});
+%! assert ("cell", class (get (h, "string")))
+%! xlabel (1:2)
+%! ylabel (1:2)
+%! title (1:2)
+
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   h = text (0.5, 0.3, "char");
+%!   assert ("char", class (get (h, "string")))
+%!   h = text (0.5, 0.4, ["char row 1"; "char row 2"]);
+%!   assert ("char", class (get (h, "string")))
+%!   h = text (0.5, 0.6, {"cell2str (1,1)", "cell2str (1,2)"; "cell2str (2,1)", "cell2str (2,2)"});
+%!   assert ("cell", class (get (h, "string")))
+%!   h = text (0.5, 0.8, "foobar");
+%!   set (h, "string", 1:3)
+%!   h = text ([0.1, 0.1], [0.3, 0.4], "one string & two objects");
+%!   assert ("char", class (get (h(1), "string")))
+%!   assert ("char", class (get (h(2), "string")))
+%!   h = text ([0.1, 0.1], [0.5, 0.6], {"one cellstr & two objects"});
+%!   assert ("cell", class (get (h(1), "string")))
+%!   assert ("cell", class (get (h(2), "string")))
+%!   h = text ([0.1, 0.1], [0.7, 0.8], {"cellstr 1 object 1", "cellstr 2 object 2"});
+%!   assert ("char", class (get (h(1), "string")))
+%!   assert ("char", class (get (h(2), "string")))
+%!   h = text ([0.1, 0.1], [0.1, 0.2], ["1st string & 1st object"; "2nd string & 2nd object"]);
+%!   assert ("char", class (get (h(1), "string")))
+%!   assert ("char", class (get (h(2), "string")))
+%!   h = text (0.7, 0.6, "single string");
+%!   assert ("char", class (get (h, "string")))
+%!   h = text (0.7, 0.5, {"single cell-string"});
+%!   assert ("cell", class (get (h, "string")))
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
--- a/scripts/plot/title.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/title.m	Tue Sep 20 15:38:24 2011 -0400
@@ -37,3 +37,39 @@
   endif
 
 endfunction
+
+%!demo
+%! clf ();
+%! ax=axes();
+%! xl = get(ax,"title");
+%! title("Testing title")
+%! assert(get(xl,"string"),"Testing title")
+
+%!demo
+%! clf ();
+%! plot3 ([0,1], [0,1], [0,1]);
+%! xl = get(gca (), "title");
+%! title("Testing title")
+%! assert(get(xl,"string"),"Testing title")
+
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   ax=axes();
+%!   xl = get(ax,"title");
+%!   title("Testing title")
+%!   assert(get(xl,"string"),"Testing title")
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   plot3 ([0,1], [0,1], [0,1]);
+%!   xl = get(gca (), "title");
+%!   title("Testing title")
+%!   assert(get(xl,"string"),"Testing title")
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/trimesh.m	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,66 @@
+## Copyright (C) 2007-2011 David Bateman
+##
+## 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 3 of the License, 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, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {Function File} {} trimesh (@var{tri}, @var{x}, @var{y}, @var{z})
+## @deftypefnx {Function File} {@var{h} =} trimesh (@dots{})
+## Plot a triangular mesh in 3D@.  The variable @var{tri} is the triangular
+## meshing of the points @code{(@var{x}, @var{y})} which is returned
+## from @code{delaunay}.  The variable @var{z} is value at the point
+## @code{(@var{x}, @var{y})}.  The output argument @var{h} is the graphic
+## handle of the plot.
+## @seealso{triplot, trisurf, delaunay3}
+## @end deftypefn
+
+function h = trimesh (tri, x, y, z, varargin)
+
+  if (nargin < 3)
+    print_usage ();
+  endif
+
+  if (nargin == 3)
+    triplot (tri, x, y);
+  elseif (ischar (z))
+    triplot (tri, x, y, z, varargin{:});
+  else
+    newplot ();
+    if (nargout > 0)
+      h = patch ("Vertices", [x(:), y(:), z(:)], "Faces", tri,
+                 "FaceColor", "none", "EdgeColor", __next_line_color__(),
+                 varargin{:});
+    else
+      patch ("Vertices", [x(:), y(:), z(:)], "Faces", tri,
+             "FaceColor", "none", "EdgeColor", __next_line_color__(),
+             varargin{:});
+    endif
+
+    if (! ishold ())
+      set (gca(), "view", [-37.5, 30],
+           "xgrid", "on", "ygrid", "on", "zgrid", "on");
+    endif
+  endif
+endfunction
+
+%!demo
+%! N = 10;
+%! rand ('state', 10)
+%! x = 3 - 6 * rand (N, N);
+%! y = 3 - 6 * rand (N, N);
+%! z = peaks (x, y);
+%! tri = delaunay (x(:), y(:));
+%! trimesh (tri, x(:), y(:), z(:));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/triplot.m	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,53 @@
+## Copyright (C) 2007-2011 David Bateman
+##
+## 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 3 of the License, 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, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {Function File} {} triplot (@var{tri}, @var{x}, @var{y})
+## @deftypefnx {Function File} {} triplot (@var{tri}, @var{x}, @var{y}, @var{linespec})
+## @deftypefnx {Function File} {@var{h} =} triplot (@dots{})
+## Plot a triangular mesh in 2D@.  The variable @var{tri} is the triangular
+## meshing of the points @code{(@var{x}, @var{y})} which is returned from
+## @code{delaunay}.  If given, the @var{linespec} determines the properties
+## to use for the lines.  The output argument @var{h} is the graphic handle
+## of the plot.
+## @seealso{plot, trimesh, trisurf, delaunay}
+## @end deftypefn
+
+function h = triplot (tri, x, y, varargin)
+
+  if (nargin < 3)
+    print_usage ();
+  endif
+
+  idx = tri(:, [1, 2, 3, 1]).';
+  nt = size (tri, 1);
+  if (nargout > 0)
+    h = plot ([x(idx); NaN(1, nt)](:),
+              [y(idx); NaN(1, nt)](:), varargin{:});
+  else
+    plot ([x(idx); NaN(1, nt)](:),
+          [y(idx); NaN(1, nt)](:), varargin{:});
+  endif
+endfunction
+
+%!demo
+%! rand ('state', 2)
+%! x = rand (20, 1);
+%! y = rand (20, 1);
+%! tri = delaunay (x, y);
+%! triplot (tri, x, y);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/trisurf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,102 @@
+## Copyright (C) 2007-2011 David Bateman
+##
+## 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 3 of the License, 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, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {Function File} {} trisurf (@var{tri}, @var{x}, @var{y}, @var{z})
+## @deftypefnx {Function File} {@var{h} =} trisurf (@dots{})
+## Plot a triangular surface in 3D@.  The variable @var{tri} is the triangular
+## meshing of the points @code{(@var{x}, @var{y})} which is returned
+## from @code{delaunay}.  The variable @var{z} is value at the point
+## @code{(@var{x}, @var{y})}.  The output argument @var{h} is the graphic
+## handle of the plot.
+## @seealso{triplot, trimesh, delaunay3}
+## @end deftypefn
+
+function varargout = trisurf (tri, x, y, z, varargin)
+
+  if (nargin < 3)
+    print_usage ();
+  endif
+
+  if (nargin == 3)
+    triplot (tri, x, y);
+  elseif (ischar (z))
+    triplot (tri, x, y, z, varargin{:});
+  else
+    if (nargin > 4 && isnumeric (varargin{1}))
+      c = varargin{1};
+      varargin(1) = [];
+    else
+      c = z;
+    endif
+    if (! any (strcmpi (varargin, "FaceColor")))
+      nfc = numel (varargin) + 1;
+      varargin(nfc+(0:1)) = {"FaceColor", "flat"};
+    else
+      nfc = find (any (strcmpi (varargin, "FaceColor")), 1);
+    endif
+    if (! any (strcmpi (varargin, "EdgeColor"))
+        && strcmpi (varargin{nfc+1}, "interp"))
+      varargin(end+(1:2)) = {"EdgeColor", "none"};
+    endif
+    newplot ();
+    h = patch ("Faces", tri, "Vertices", [x(:), y(:), z(:)],
+               "FaceVertexCData", reshape (c, numel (c), 1),
+               varargin{:});
+    if (nargout > 0)
+      varargout = {h};
+    endif
+
+    if (! ishold ())
+      set (gca(), "view", [-37.5, 30],
+           "xgrid", "on", "ygrid", "on", "zgrid", "on");
+    endif
+  endif
+endfunction
+
+%!demo
+%! N = 10;
+%! rand ('state', 10)
+%! x = 3 - 6 * rand (N, N);
+%! y = 3 - 6 * rand (N, N);
+%! z = peaks (x, y);
+%! tri = delaunay (x(:), y(:));
+%! trisurf (tri, x(:), y(:), z(:));
+
+%!demo
+%! x = rand (100, 1);
+%! y = rand (100, 1);
+%! z = x.^2 + y.^2;
+%! tri = delaunay (x, y);
+%! trisurf (tri, x, y, z)
+
+%!demo
+%! x = rand (100, 1);
+%! y = rand (100, 1);
+%! z = x.^2 + y.^2;
+%! tri = delaunay (x, y);
+%! trisurf (tri, x, y, z, "facecolor", "interp")
+
+%!demo
+%! x = rand (100, 1);
+%! y = rand (100, 1);
+%! z = x.^2 + y.^2;
+%! tri = delaunay (x, y);
+%! trisurf (tri, x, y, z, "facecolor", "interp", "edgecolor", "k")
+
+
--- a/scripts/plot/uimenu.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/uimenu.m	Tue Sep 20 15:38:24 2011 -0400
@@ -66,8 +66,10 @@
 ## @group
 ## f = uimenu("label", "&File", "accelerator", "f");
 ## e = uimenu("label", "&Edit", "accelerator", "e");
-## uimenu(f, "label", "Close", "accelerator", "q", "callback", "close (gcf)");
-## uimenu(e, "label", "Toggle &Grid", "accelerator", "g", "callback", "grid (gca)");
+## uimenu(f, "label", "Close", "accelerator", "q", ...
+##           "callback", "close (gcf)");
+## uimenu(e, "label", "Toggle &Grid", "accelerator", "g", ...
+##           "callback", "grid (gca)");
 ## @end group
 ## @end example
 ## @seealso{figure}
--- a/scripts/plot/view.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/view.m	Tue Sep 20 15:38:24 2011 -0400
@@ -93,3 +93,32 @@
   endif
 
 endfunction
+
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   plot3 ([0,1], [0,1], [0,1]);
+%!   [az, el] = view;
+%!   assert ([az, el], [-37.5, 30], eps);
+%!   view (2);
+%!   [az, el] = view;
+%!   assert ([az, el], [0, 90], eps);
+%!   view ([1 1 0]);
+%!   [az, el] = view;
+%!   assert ([az, el], [135, 0], eps);
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   line;
+%!   [az, el] = view;
+%!   assert ([az, el], [0, 90], eps);
+%!   view (3);
+%!   [az, el] = view;
+%!   assert ([az, el], [-37.5, 30], eps);
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
--- a/scripts/plot/whitebg.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/whitebg.m	Tue Sep 20 15:38:24 2011 -0400
@@ -40,7 +40,7 @@
   h = 0;
   color = NaN;
 
-  if (nargin > 0 && nargin < 2)
+  if (nargin > 0 && nargin < 3)
     if (ishandle (varargin{1}))
       h = varargin{1};
       if (nargin == 2)
@@ -74,7 +74,7 @@
     if (isroot)
       fac = get (0, "factory");
       fields = fieldnames (fac);
-      fieldindex = intersect (find (!cellfun (@isempty, regexp(fields, 'color'))), union (find (!cellfun (@isempty, regexp(fields, 'factoryaxes.*'))), find (!cellfun (@isempty, regexp(fields, 'factoryfigure.*')))));
+      fieldindex = intersect (find (!cellfun ("isempty", regexp(fields, 'color'))), union (find (!cellfun ("isempty", regexp(fields, 'factoryaxes.*'))), find (!cellfun ("isempty", regexp(fields, 'factoryfigure.*')))));
 
       ## Check whether the factory value has been replaced
       for nf = 1 : numel (fieldindex);
@@ -104,7 +104,7 @@
     for nh = 1 : numel(h)
       p = get (h (nh));
       fields = fieldnames (p);
-      fieldindex = find (!cellfun (@isempty, regexp(fields, 'color')));
+      fieldindex = find (!cellfun ("isempty", regexp(fields, 'color')));
       if (numel (fieldindex))
         for nf = 1 : numel (fieldindex);
           field = fields {fieldindex (nf)};
@@ -121,7 +121,7 @@
         def = get (h (nh), "default");
         fields = fieldnames (def);
         if (! isempty (fields))
-          fieldindex = find (!cellfun (@isempty, regexp(fields, 'color')));
+          fieldindex = find (!cellfun ("isempty", regexp(fields, 'color')));
           for nf = 1 : numel (fieldindex)
             defaultfield = fields {fieldindex (nf)};
             defaultvalue = 1 - subsref (def, struct ("type", ".", "subs", defaultfield));
@@ -143,3 +143,22 @@
     endif
   endif
 endfunction
+
+%!test
+%! dac = get (0, "defaultaxescolor");
+%! dfc = get (0, "defaultfigurecolor");
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   l = line;
+%!   assert (get (hf, "color"), dfc);
+%!   assert (get (gca, "color"), dac);
+%!   whitebg (hf);
+%!   assert (get (hf, "color"), 1 - dfc);
+%!   assert (get (gca, "color"), 1 - dac);
+%!   c = [0.2 0.2 0.2];
+%!   whitebg (hf, c);
+%!   assert (get (hf, "color"), 1 - dfc);
+%!   assert (get (gca, "color"), c);
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
--- a/scripts/plot/xlabel.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/xlabel.m	Tue Sep 20 15:38:24 2011 -0400
@@ -53,3 +53,15 @@
   endif
 
 endfunction
+
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   x = xlabel ("xlabel_string");
+%!   assert (get(gca, "xlabel"), x);
+%!   assert (get(x, "type"), "text");
+%!   assert (get(x, "visible"), "on");
+%!   assert (get(x, "string"), "xlabel_string");
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
--- a/scripts/plot/xlim.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/xlim.m	Tue Sep 20 15:38:24 2011 -0400
@@ -44,3 +44,53 @@
     retval = ret;
   endif
 endfunction
+
+%!demo
+%! clf ();
+%! line ();
+%! xlim ([0.2, 0.8]);
+%! title ("xlim is [0.2, 0.8]");
+%! assert (xlim (), [0.2, 0.8]);
+
+%!demo
+%! clf ();
+%! line ();
+%! xlim ('auto');
+%! title ("xlim is auto");
+%! assert (xlim ("mode"), "auto");
+
+%!demo
+%! clf ();
+%! plot3 ([0,1], [0,1], [0,1]);
+%! xlim ([0.2, 0.8]);
+%! title ("xlim is [0.2, 0.8]");
+%! assert (xlim (), [0.2, 0.8]);
+
+%!demo
+%! clf ();
+%! plot3 ([0,1], [0,1], [0,1]);
+%! xlim ('auto');
+%! title ("xlim is auto");
+%! assert (xlim ("mode"), "auto");
+
+
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   plot3 ([0,1], [0,1], [0,1]);
+%!   xlim ([0, 1.1]);
+%!   assert (get (gca, "xlim"), [0, 1.1], eps);
+%!   assert (xlim ("mode"), "manual");
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   h = plot3 ([0,1.1], [0,1], [0, 1]);
+%!   assert (get (gca, "xlim"), [0, 1.4], eps);
+%!   assert (xlim ("mode"), "auto");
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
--- a/scripts/plot/ylabel.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/ylabel.m	Tue Sep 20 15:38:24 2011 -0400
@@ -47,3 +47,15 @@
   endif
 
 endfunction
+
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   y = ylabel ("ylabel_string");
+%!   assert (get(gca, "ylabel"), y);
+%!   assert (get(y, "type"), "text");
+%!   assert (get(y, "visible"), "on");
+%!   assert (get(y, "string"), "ylabel_string");
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
--- a/scripts/plot/ylim.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/ylim.m	Tue Sep 20 15:38:24 2011 -0400
@@ -44,3 +44,53 @@
     retval = ret;
   endif
 endfunction
+
+%!demo
+%! clf ();
+%! line ();
+%! ylim ([0.2, 0.8]);
+%! title ("ylim is [0.2, 0.8]");
+%! assert (ylim (), [0.2, 0.8]);
+
+%!demo
+%! clf ();
+%! line ();
+%! ylim ('auto');
+%! title ("ylim is auto");
+%! assert (ylim ("mode"), "auto");
+
+%!demo
+%! clf ();
+%! plot3 ([0,1], [0,1], [0,1]);
+%! ylim ([0.2, 0.8]);
+%! title ("ylim is [0.2, 0.8]");
+%! assert (ylim (), [0.2, 0.8]);
+
+%!demo
+%! clf ();
+%! plot3 ([0,1], [0,1], [0,1]);
+%! ylim ('auto');
+%! title ("ylim is auto");
+%! assert (ylim ("mode"), "auto");
+
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   limy = [0, 1.1];
+%!   plot3 ([0,1], [0,1], [0,1]);
+%!   ylim (limy);
+%!   assert (get (gca, "ylim"), limy, eps);
+%!   assert (ylim ("mode"), "manual");
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   plot3 ([0,1], [0,1.1], [0, 1]);
+%!   assert (get (gca, "ylim"), [0, 1.4], eps);
+%!   assert (ylim ("mode"), "auto");
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
--- a/scripts/plot/zlabel.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/zlabel.m	Tue Sep 20 15:38:24 2011 -0400
@@ -47,3 +47,28 @@
   endif
 
 endfunction
+
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   z = zlabel ("zlabel_string");
+%!   assert (get(gca, "zlabel"), z);
+%!   assert (get(z, "type"), "text");
+%!   assert (get(z, "visible"), "off");
+%!   assert (get(z, "string"), "zlabel_string");
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+%!test
+%! hf = figure ("visible", "off");
+%! plot3 (0, 0, 0);
+%! unwind_protect
+%!   z = zlabel ("zlabel_string");
+%!   assert (get(gca, "zlabel"), z);
+%!   assert (get(z, "type"), "text");
+%!   assert (get(z, "visible"), "off");
+%!   assert (get(z, "string"), "zlabel_string");
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
--- a/scripts/plot/zlim.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/plot/zlim.m	Tue Sep 20 15:38:24 2011 -0400
@@ -44,3 +44,53 @@
     retval = ret;
   endif
 endfunction
+
+%!demo
+%! clf ();
+%! line ();
+%! zlim ([0.2, 0.8]);
+%! title ("zlim is [0.2, 0.8]");
+%! assert (zlim (), [0.2, 0.8]);
+
+%!demo
+%! clf ();
+%! line ();
+%! zlim ('auto');
+%! title ("zlim is auto");
+%! assert (zlim ("mode"), "auto");
+
+%!demo
+%! clf ();
+%! plot3 ([0,1], [0,1], [0,1]);
+%! zlim ([0.2, 0.8]);
+%! title ("zlim is [0.2, 0.8]");
+%! assert (zlim (), [0.2, 0.8]);
+
+%!demo
+%! clf ();
+%! plot3 ([0,1], [0,1], [0,1]);
+%! zlim ('auto');
+%! title ("zlim is auto");
+%! assert (zlim ("mode"), "auto");
+
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   limz = [0, 1.1];
+%!   plot3 ([0,1], [0,1], [0,1]);
+%!   zlim (limz);
+%!   assert (get (gca, "zlim"), limz, eps);
+%!   assert (zlim ("mode"), "manual");
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   plot3 ([0,1], [0,1], [0, 1.1]);
+%!   assert (get (gca, "zlim"), [0, 1.4], eps);
+%!   assert (zlim ("mode"), "auto");
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
--- a/scripts/polynomial/mkpp.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/polynomial/mkpp.m	Tue Sep 20 15:38:24 2011 -0400
@@ -17,50 +17,66 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {@var{pp} =} mkpp (@var{x}, @var{p})
-## @deftypefnx {Function File} {@var{pp} =} mkpp (@var{x}, @var{p}, @var{d})
+## @deftypefn  {Function File} {@var{pp} =} mkpp (@var{breaks}, @var{coefs})
+## @deftypefnx {Function File} {@var{pp} =} mkpp (@var{breaks}, @var{coefs}, @var{d})
+##
+## Construct a piece-wise polynomial (pp) structure from sample points
+## @var{breaks} and coefficients @var{coefs}.  @var{breaks} must be a vector of
+## strictly increasing values. The number of intervals is given by
+## @code{@var{ni} = length (@var{breaks}) - 1}.
+## When @var{m} is the polynomial order @var{coefs} must be of
+## size: @var{ni} x @var{m} + 1.
 ##
-## Construct a piecewise polynomial structure from sample points
-## @var{x} and coefficients @var{p}.  The i-th row of @var{p},
-## @code{@var{p} (@var{i},:)}, contains the coefficients for the polynomial
-## over the @var{i}-th interval, ordered from highest to
-## lowest.  There must be one row for each interval in @var{x}, so
-## @code{rows (@var{p}) == length (@var{x}) - 1}.
+## The i-th row of @var{coefs},
+## @code{@var{coefs} (@var{i},:)}, contains the coefficients for the polynomial
+## over the @var{i}-th interval, ordered from highest (@var{m}) to
+## lowest (@var{0}).
 ##
-## @var{p} may also be a multi-dimensional array, specifying a vector-valued
-## or array-valued polynomial.  The shape is determined by @var{d}.  If @var{d}
-## is
-## not given, the default is @code{size (p)(1:end-2)}.  If @var{d} is given, the
-## leading dimensions of @var{p} are reshaped to conform to @var{d}.
+## @var{coefs} may also be a multi-dimensional array, specifying a vector-valued
+## or array-valued polynomial. In that case the polynomial order is defined
+## by the length of the last dimension of @var{coefs}.
+## The size of first dimension(s) are given by the scalar or
+## vector @var{d}. If @var{d} is not given it is set to @code{1}.
+## In any case @var{coefs} is reshaped to a 2d matrix of
+## size @code{[@var{ni}*prod(@var{d} @var{m})] }
 ##
 ## @seealso{unmkpp, ppval, spline}
 ## @end deftypefn
 
 function pp = mkpp (x, P, d)
+
+  # check number of arguments
   if (nargin < 2 || nargin > 3)
     print_usage ();
   endif
-  pp.x = x(:);
-  n = length (x) - 1;
-  if (n < 1)
+
+  # check x
+  if (length (x) < 2)
     error ("mkpp: at least one interval is needed");
   endif
-  nd = ndims (P);
-  k = size (P, nd);
-  if (nargin < 3)
-    if (nd == 2)
-      d = 1;
-    else
-      d = prod (size (P)(1:nd-1));
-    endif
+
+  if (!isvector (x))
+    error ("mkpp: x must be a vector");
   endif
-  pp.d = d;
-  pp.P = P = reshape (P, prod (d), [], k);
-  pp.orient = 0;
+
+  len = length (x) - 1;
+  dP = length (size (P));
 
-  if (size (P, 2) != n)
-    error ("mkpp: num intervals in X doesn't match num polynomials in P");
+  pp = struct ("form", "pp",
+               "breaks", x(:).',
+               "coefs", [],
+               "pieces", len,
+               "order", prod (size (P)) / len,
+               "dim", 1);
+
+  if (nargin == 3)
+    pp.dim = d;
+    pp.order /= prod (d);
   endif
+
+  dim_vec = [pp.pieces * prod(pp.dim), pp.order];
+  pp.coefs = reshape (P, dim_vec);
+
 endfunction
 
 %!demo # linear interpolation
@@ -72,3 +88,25 @@
 %! xi=linspace(0,pi,50);
 %! plot(x,t,"x",xi,ppval(pp,xi));
 %! legend("control","interp");
+
+%!shared b,c,pp
+%! b = 1:3; c = 1:24; pp=mkpp(b,c);
+%!assert (pp.pieces,2);
+%!assert (pp.order,12);
+%!assert (pp.dim,1);
+%!assert (size(pp.coefs),[2,12]);
+%! pp=mkpp(b,c,2);
+%!assert (pp.pieces,2);
+%!assert (pp.order,6);
+%!assert (pp.dim,2);
+%!assert (size(pp.coefs),[4,6]);
+%! pp=mkpp(b,c,3);
+%!assert (pp.pieces,2);
+%!assert (pp.order,4);
+%!assert (pp.dim,3);
+%!assert (size(pp.coefs),[6,4]);
+%! pp=mkpp(b,c,[2,3]);
+%!assert (pp.pieces,2);
+%!assert (pp.order,2);
+%!assert (pp.dim,[2,3]);
+%!assert (size(pp.coefs),[12,2]);
--- a/scripts/polynomial/module.mk	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/polynomial/module.mk	Tue Sep 20 15:38:24 2011 -0400
@@ -10,7 +10,6 @@
   polynomial/poly.m \
   polynomial/polyaffine.m \
   polynomial/polyder.m \
-  polynomial/polyderiv.m \
   polynomial/polyfit.m \
   polynomial/polygcd.m \
   polynomial/polyint.m \
--- a/scripts/polynomial/pchip.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/polynomial/pchip.m	Tue Sep 20 15:38:24 2011 -0400
@@ -27,8 +27,8 @@
 ##
 ## The variable @var{x} must be a strictly monotonic vector (either
 ## increasing or decreasing).  While @var{y} can be either a vector or
-## array.  In the case where @var{y} is a vector, it must have a length
-## of @var{n}.  If @var{y} is an array, then the size of @var{y} must
+## an array.  In the case where @var{y} is a vector, it must have the
+## length @var{n}.  If @var{y} is an array, then the size of @var{y} must
 ## have the form
 ## @tex
 ## $$[s_1, s_2, \cdots, s_k, n]$$
@@ -73,15 +73,22 @@
     print_usage ();
   endif
 
+  ## make row vector
   x = x(:).';
   n = length (x);
 
   ## Check the size and shape of y
   if (isvector (y))
-    y = y(:).';
+    y = y(:).'; ##row vector
     szy = size (y);
+    if !(size_equal (x, y))
+      error ("pchip: length of X and Y must match")
+    endif
   else
     szy = size (y);
+    if (n != szy(end))
+      error ("pchip: length of X and last dimension of Y must match")
+    endif
     y = reshape (y, [prod(szy(1:end-1)), szy(end)]);
   endif
 
@@ -94,16 +101,12 @@
     error("pchip: X must be strictly monotonic");
   endif
 
-  if (columns (y) != n)
-    error("pchip: size of X and Y must match");
-  endif
-
-  f1 = y(:,1:n-1);
+  f1 = y(:, 1:n-1);
 
   ## Compute derivatives.
   d = __pchip_deriv__ (x, y, 2);
-  d1 = d(:,1:n-1);
-  d2 = d(:,2:n);
+  d1 = d(:, 1:n-1);
+  d2 = d(:, 2:n);
 
   ## This is taken from SLATEC.
   h = diag (h);
@@ -114,14 +117,12 @@
   c3 = del1 + del2;
   c2 = -c3 - del1;
   c3 = c3 / h;
-
   coeffs = cat (3, c3, c2, d1, f1);
-  pp = mkpp (x, coeffs, szy(1:end-1));
 
-  if (nargin == 2)
-    ret = pp;
-  else
-    ret = ppval (pp, xi);
+  ret = mkpp (x, coeffs, szy(1:end-1));
+
+  if (nargin == 3)
+    ret = ppval (ret, xi);
   endif
 
 endfunction
@@ -138,7 +139,7 @@
 %! %-------------------------------------------------------------------
 %! % confirm that pchip agreed better to discontinuous data than spline
 
-%!shared x,y
+%!shared x,y,y2,pp,yi1,yi2,yi3
 %! x = 0:8;
 %! y = [1, 1, 1, 1, 0.5, 0, 0, 0, 0];
 %!assert (pchip(x,y,x), y);
@@ -148,3 +149,23 @@
 %!assert (isempty(pchip(x',y',[])));
 %!assert (isempty(pchip(x,y,[])));
 %!assert (pchip(x,[y;y],x), [pchip(x,y,x);pchip(x,y,x)])
+%!assert (pchip(x,[y;y],x'), [pchip(x,y,x);pchip(x,y,x)])
+%!assert (pchip(x',[y;y],x), [pchip(x,y,x);pchip(x,y,x)])
+%!assert (pchip(x',[y;y],x'), [pchip(x,y,x);pchip(x,y,x)])
+%!test
+%! x=(0:8)*pi/4;y=[sin(x);cos(x)];
+%! y2(:,:,1)=y;y2(:,:,2)=y+1;y2(:,:,3)=y-1;
+%! pp=pchip(x,shiftdim(y2,2));
+%! yi1=ppval(pp,(1:4)*pi/4);
+%! yi2=ppval(pp,repmat((1:4)*pi/4,[5,1]));
+%! yi3=ppval(pp,[pi/2,pi]);
+%!assert(size(pp.coefs),[48,4]);
+%!assert(pp.pieces,8);
+%!assert(pp.order,4);
+%!assert(pp.dim,[3,2]);
+%!assert(ppval(pp,pi),[0,-1;1,0;-1,-2],1e-14);
+%!assert(yi3(:,:,2),ppval(pp,pi),1e-14);
+%!assert(yi3(:,:,1),[1,0;2,1;0,-1],1e-14);
+%!assert(squeeze(yi1(1,2,:)),[1/sqrt(2); 0; -1/sqrt(2);-1],1e-14);
+%!assert(size(yi2),[3,2,5,4]);
+%!assert(squeeze(yi2(1,2,3,:)),[1/sqrt(2); 0; -1/sqrt(2);-1],1e-14);
\ No newline at end of file
--- a/scripts/polynomial/polyder.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/polynomial/polyder.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,4 +1,4 @@
-## Copyright (C) 1995-2011 John W. Eaton
+## Copyright (C) 1994-2011 John W. Eaton
 ##
 ## This file is part of Octave.
 ##
@@ -17,27 +17,84 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} polyderiv (@var{p})
-## @deftypefnx {Function File} {[@var{k}] =} polyderiv (@var{a}, @var{b})
-## @deftypefnx {Function File} {[@var{q}, @var{d}] =} polyderiv (@var{b}, @var{a})
-## An alias for @code{polyderiv}.
-## @seealso{polyderiv}
+## @deftypefn  {Function File} {} polyder (@var{p})
+## @deftypefnx {Function File} {[@var{k}] =} polyder (@var{a}, @var{b})
+## @deftypefnx {Function File} {[@var{q}, @var{d}] =} polyder (@var{b}, @var{a})
+## Return the coefficients of the derivative of the polynomial whose
+## coefficients are given by the vector @var{p}.  If a pair of polynomials
+## is given, return the derivative of the product @math{@var{a}*@var{b}}.
+## If two inputs and two outputs are given, return the derivative of the
+## polynomial quotient @math{@var{b}/@var{a}}.  The quotient numerator is
+## in @var{q} and the denominator in @var{d}.
+## @seealso{poly, polyint, polyreduce, roots, conv, deconv, residue,
+## filter, polygcd, polyval, polyvalm}
 ## @end deftypefn
 
-## Author: John W. Eaton
+## Author: Tony Richardson <arichard@stark.cc.oh.us>
+## Created: June 1994
+## Adapted-By: jwe
 
 function [q, d] = polyder (p, a)
 
-  if (nargin == 1)
-    q = polyderiv (p);
-  elseif (nargin == 2)
-    if (nargout == 2)
-      [q, d] = polyderiv (p, a);
+  if (nargin == 1 || nargin == 2)
+    if (! isvector (p))
+      error ("polyder: argument must be a vector");
+    endif
+    if (nargin == 2)
+      if (! isvector (a))
+        error ("polyder: argument must be a vector");
+      endif
+      if (nargout == 1)
+        ## derivative of p*a returns a single polynomial
+        q = polyder (conv (p, a));
+      else
+        ## derivative of p/a returns numerator and denominator
+        d = conv (a, a);
+        if (numel (p) == 1)
+          q = -p * polyder (a);
+        elseif (numel (a) == 1)
+          q = a * polyder (p);
+        else
+          q = conv (polyder (p), a) - conv (p, polyder (a));
+          q = polyreduce (q);
+        endif
+
+        ## remove common factors from numerator and denominator
+        x = polygcd (q, d);
+        if (length(x) != 1)
+          q = deconv (q, x);
+          d = deconv (d, x);
+        endif
+
+        ## move all the gain into the numerator
+        q = q/d(1);
+        d = d/d(1);
+      endif
     else
-      q = polyderiv (p, a);
+      lp = numel (p);
+      if (lp == 1)
+        q = 0;
+        return;
+      elseif (lp == 0)
+        q = [];
+        return;
+      endif
+
+      ## Force P to be a row vector.
+      p = p(:).';
+
+      q = p(1:(lp-1)) .* [(lp-1):-1:1];
     endif
   else
     print_usage ();
   endif
 
 endfunction
+
+
+%!assert(all (all (polyder ([1, 2, 3]) == [2, 2])));
+%!assert(polyder (13) == 0);
+
+%!error polyder ([]);
+%!error polyder ([1, 2; 3, 4]);
+
--- a/scripts/polynomial/polyderiv.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,101 +0,0 @@
-## Copyright (C) 1994-2011 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn  {Function File} {} polyderiv (@var{p})
-## @deftypefnx {Function File} {[@var{k}] =} polyderiv (@var{a}, @var{b})
-## @deftypefnx {Function File} {[@var{q}, @var{d}] =} polyderiv (@var{b}, @var{a})
-## Return the coefficients of the derivative of the polynomial whose
-## coefficients are given by the vector @var{p}.  If a pair of polynomials
-## is given, return the derivative of the product @math{@var{a}*@var{b}}.
-## If two inputs and two outputs are given, return the derivative of the
-## polynomial quotient @math{@var{b}/@var{a}}.  The quotient numerator is
-## in @var{q} and the denominator in @var{d}.
-## @seealso{poly, polyint, polyreduce, roots, conv, deconv, residue,
-## filter, polygcd, polyval, polyvalm}
-## @end deftypefn
-
-## Author: Tony Richardson <arichard@stark.cc.oh.us>
-## Created: June 1994
-## Adapted-By: jwe
-
-function [q, d] = polyderiv (p, a)
-
-  if (nargin == 1 || nargin == 2)
-    if (! isvector (p))
-      error ("polyderiv: argument must be a vector");
-    endif
-    if (nargin == 2)
-      if (! isvector (a))
-        error ("polyderiv: argument must be a vector");
-      endif
-      if (nargout == 1)
-        ## derivative of p*a returns a single polynomial
-        q = polyderiv (conv (p, a));
-      else
-        ## derivative of p/a returns numerator and denominator
-        d = conv (a, a);
-        if (numel (p) == 1)
-          q = -p * polyderiv (a);
-        elseif (numel (a) == 1)
-          q = a * polyderiv (p);
-        else
-          q = conv (polyderiv (p), a) - conv (p, polyderiv (a));
-          q = polyreduce (q);
-        endif
-
-        ## remove common factors from numerator and denominator
-        x = polygcd (q, d);
-        if (length(x) != 1)
-          q = deconv (q, x);
-          d = deconv (d, x);
-        endif
-
-        ## move all the gain into the numerator
-        q = q/d(1);
-        d = d/d(1);
-      endif
-    else
-      lp = numel (p);
-      if (lp == 1)
-        q = 0;
-        return;
-      elseif (lp == 0)
-        q = [];
-        return;
-      endif
-
-      ## Force P to be a row vector.
-      p = p(:).';
-
-      q = p(1:(lp-1)) .* [(lp-1):-1:1];
-    endif
-  else
-    print_usage ();
-  endif
-
-endfunction
-
-%!assert(all (all (polyderiv ([1, 2, 3]) == [2, 2])));
-
-%!assert(polyderiv (13) == 0);
-
-%!error polyderiv ([]);
-
-%!error polyderiv ([1, 2; 3, 4]);
-
--- a/scripts/polynomial/polygcd.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/polynomial/polygcd.m	Tue Sep 20 15:38:24 2011 -0400
@@ -81,3 +81,24 @@
   endif
 
 endfunction
+
+
+%!test
+%! poly1 = [1 6 11 6]; % (x+1)(x+2)(x+3)
+%! poly2 = [1 3 2]; % (x+1)(x+2)
+%! poly3 = polygcd (poly1, poly2);
+%! assert (poly3, poly2, sqrt (eps))
+
+%!test
+%! assert (polygcd (poly(1:8), poly(3:12)), poly(3:8), sqrt (eps))
+
+%!test
+%! assert (deconv (poly(1:8), polygcd (poly(1:8), poly(3:12))), poly(1:2), sqrt (eps))
+
+%!test
+%! for ii=1:10
+%!   p  = (unique (randn (10, 1)) * 10).';
+%!   p1 = p(3:end);
+%!   p2 = p(1:end-2);
+%!   assert (polygcd (poly (-p1), poly (-p2)), poly (- intersect (p1, p2)), sqrt (eps))
+%! endfor
--- a/scripts/polynomial/polyint.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/polynomial/polyint.m	Tue Sep 20 15:38:24 2011 -0400
@@ -61,3 +61,18 @@
   retval = [(p ./ [lp:-1:1]), k];
 
 endfunction
+
+%!test
+%! A = [3, 2, 1];
+%! assert (polyint(A),polyint(A,0));
+%! assert (polyint(A),polyint(A'));
+%! assert (polyint(A),[1, 1, 1, 0]);
+%! assert (polyint(A,1),ones(1,4));
+
+%!test
+%! A = ones(1,8);
+%! B = [length(A):-1:1];
+%! assert (polyint(A),[1./B, 0]);
+
+%!error polyint()
+%!error polyint(ones(2,2))
--- a/scripts/polynomial/polyout.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/polynomial/polyout.m	Tue Sep 20 15:38:24 2011 -0400
@@ -97,3 +97,9 @@
     str = num2str (c, 5);
   endif
 endfunction
+
+%!assert (polyout ([3 2 1]), '3*s^2 + 2*s^1 + 1')
+%!assert (polyout ([3 2 1], 'x'), '3*x^2 + 2*x^1 + 1')
+%!assert (polyout ([3 2 1], 'wxyz'), '3*wxyz^2 + 2*wxyz^1 + 1')
+%!assert (polyout ([5 4 3 2 1], '1'),'5*1^4 + 4*1^3 + 3*1^2 + 2*1^1 + 1')
+%!error polyout ([])
--- a/scripts/polynomial/polyval.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/polynomial/polyval.m	Tue Sep 20 15:38:24 2011 -0400
@@ -20,7 +20,7 @@
 ## @deftypefn  {Function File} {@var{y} =} polyval (@var{p}, @var{x})
 ## @deftypefnx {Function File} {@var{y} =} polyval (@var{p}, @var{x}, [], @var{mu})
 ## Evaluate the polynomial @var{p} at the specified values of @var{x}.  When
-## @var{mu} is present evaluate the polynomial for
+## @var{mu} is present, evaluate the polynomial for
 ## (@var{x}-@var{mu}(1))/@var{mu}(2).
 ## If @var{x} is a vector or matrix, the polynomial is evaluated for each of
 ## the elements of @var{x}.
@@ -39,17 +39,19 @@
 ## Created: June 1994
 ## Adapted-By: jwe
 
-function [y, dy] = polyval (p, x, s, mu)
+function [y, dy] = polyval (p, x, s = [], mu)
 
   if (nargin < 2 || nargin > 4 || (nargout == 2 && nargin < 3))
     print_usage ();
   endif
 
-  if (nargin < 3)
-    s = [];
-  endif
-
-  if (! (isvector (p) || isempty (p)))
+  if (isempty (x))
+    y = [];
+    return;
+  elseif (isempty (p))
+    y = zeros (size (x));
+    return;
+  elseif (! isvector (p))
     error ("polyval: first argument must be a vector");
   endif
 
@@ -57,16 +59,6 @@
     x = (x - mu(1)) / mu(2);
   endif
 
-  if (isempty (x))
-    y = [];
-    return;
-  endif
-
-  if (length (p) == 0)
-    y = p;
-    return;
-  endif
-
   n = length (p) - 1;
   y = p(1) * ones (size (x));
   for i = 2:n+1
@@ -80,10 +72,23 @@
     ##   dy = t * sqrt (1 + sumsq (A/s.R, 2)) * s.normr / sqrt (s.df)
     ## If my inference is correct, then t must equal 1 for polyval.
     ## This is because finv (0.5, n, n) = 1.0 for any n.
-    k = numel (x);
-    A = (x(:) * ones (1, n+1)) .^ (ones (k, 1) * (n:-1:0));
-    dy = sqrt (1 + sumsq (A/s.R, 2)) * s.normr / sqrt (s.df);
-    dy = reshape (dy, size (x));
+    try
+      k = numel (x);
+      A = (x(:) * ones (1, n+1)) .^ (ones (k, 1) * (n:-1:0));
+      dy = sqrt (1 + sumsq (A/s.R, 2)) * s.normr / sqrt (s.df);
+      dy = reshape (dy, size (x));
+    catch
+      if (isempty (s))
+        error ("polyval: third input is required.")
+      elseif (isstruct (s)
+              && all (ismember ({"R", "normr", "df"}, fieldnames (s))))
+        error (lasterr ())
+      elseif (isstruct (s))
+        error ("polyval: third input is missing the required fields.");
+      else
+        error ("polyval: third input is not a structure.");
+      endif
+    end_try_catch
   endif
 
 endfunction
@@ -142,3 +147,6 @@
 %! assert (y, polyval(p,x), eps)
 %! x = reshape(x, [1, 1, 5, 2]);
 
+%!assert (zeros (1, 10), polyval ([], 1:10))
+%!assert ([], polyval (1, []))
+%!assert ([], polyval ([], []))
--- a/scripts/polynomial/ppder.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/polynomial/ppder.m	Tue Sep 20 15:38:24 2011 -0400
@@ -17,28 +17,54 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {@var{ppd} =} ppder (@var{pp})
-## Compute the piecewise derivative of the piecewise polynomial struct @var{pp}.
+## @deftypefn {Function File} {ppd =} ppder (pp, m)
+## Computes the piecewise @var{m}-th derivative of a piecewise polynomial
+## struct @var{pp}. If @var{m} is omitted the first derivate is
+## calculated.
 ## @seealso{mkpp, ppval, ppint}
 ## @end deftypefn
 
-function ppd = ppder (pp)
-  if (nargin != 1)
+function ppd = ppder (pp, m)
+
+  if ((nargin < 1) || (nargin > 2))
     print_usage ();
+  elseif (nargin == 1)
+    m = 1;
   endif
-  if (! isstruct (pp))
+
+  if !(isstruct (pp) && strcmp (pp.form, "pp"))
     error ("ppder: PP must be a structure");
   endif
 
   [x, p, n, k, d] = unmkpp (pp);
-  p = reshape (p, [], k);
-  if (k <= 1)
-    pd = zeros (rows (p), 1);
-    k = 1;
+
+  if (k - m <= 0)
+    x = [x(1) x(end)];
+    pd = zeros (prod (d), 1);
   else
-    k -= 1;
-    pd = p(:,1:k) * diag (k:-1:1);
+    f = k : -1 : 1;
+    ff = bincoeff (f, m + 1) .* factorial (m + 1) ./ f;
+    k -= m;
+    pd = p(:,1:k) * diag (ff(1:k));
   endif
+
   ppd = mkpp (x, pd, d);
 endfunction
 
+%!shared x,y,pp,ppd
+%! x=0:8;y=[x.^2;x.^3+1];pp=spline(x,y);
+%! ppd=ppder(pp);
+%!assert(ppval(ppd,x),[2*x;3*x.^2],1e-14)
+%!assert(ppd.order,3)
+%! ppd=ppder(pp,2);
+%!assert(ppval(ppd,x),[2*ones(size(x));6*x],1e-14)
+%!assert(ppd.order,2)
+%! ppd=ppder(pp,3);
+%!assert(ppd.order,1)
+%!assert(ppd.pieces,8)
+%!assert(size(ppd.coefs),[16,1])
+%! ppd=ppder(pp,4);
+%!assert(ppd.order,1)
+%!assert(ppd.pieces,1)
+%!assert(size(ppd.coefs),[2,1])
+%!assert(ppval(ppd,x),zeros(size(y)),1e-14)
--- a/scripts/polynomial/ppint.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/polynomial/ppint.m	Tue Sep 20 15:38:24 2011 -0400
@@ -28,7 +28,7 @@
   if (nargin < 1 || nargin > 2)
     print_usage ();
   endif
-  if (! isstruct (pp))
+  if (! isstruct (pp) && strcmp (pp.form, "pp"))
     error ("ppint: PP must be a structure");
   endif
 
@@ -39,17 +39,20 @@
   pi = p / diag (k:-1:1);
   k += 1;
   if (nargin == 1)
-    pi(:,k) = 0;
+    pi(:, k) = 0;
   else
-    pi(:,k) = repmat (c(:), n, 1);
+    pi(:, k) = repmat (c(:), n, 1);
   endif
 
   ppi = mkpp (x, pi, d);
 
-  ## Adjust constants so the the result is continuous.
-
-  jumps = reshape (ppjumps (ppi), prod (d), n-1);
-  ppi.P(:,2:n,k) -= cumsum (jumps, 2);
+  tmp = -cumsum (ppjumps (ppi), length (d) + 1);
+  ppi.coefs(prod(d)+1:end, k) = tmp(:);
 
 endfunction
 
+%!shared x,y,pp,ppi
+%! x=0:8;y=[ones(size(x));x+1];pp=spline(x,y);
+%! ppi=ppint(pp);
+%!assert(ppval(ppi,x),[x;0.5*x.^2+x],1e-14)
+%!assert(ppi.order,5)
--- a/scripts/polynomial/ppjumps.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/polynomial/ppjumps.m	Tue Sep 20 15:38:24 2011 -0400
@@ -28,29 +28,57 @@
   if (nargin != 1)
     print_usage ();
   endif
-  if (! isstruct (pp))
+
+  if (! isstruct (pp) && strcmp (pp.form, "pp"))
     error ("ppjumps: PP must be a structure");
   endif
 
   ## Extract info.
-  x = pp.x;
-  P = pp.P;
-  d = pp.d;
-  [nd, n, k] = size (P);
+  [x, P, n, k, d] = unmkpp(pp);
+  nd = length (d) + 1;
 
   ## Offsets.
-  dx = diff (x(1:n)).';
-  dx = dx(ones (1, nd), :); # spread (do nothing in 1D)
+  dx = diff(x(1:n));
+  dx = repmat (dx, [prod(d), 1]);
+  dx = reshape (dx, [d, n-1]);
+  dx = shiftdim (dx, nd - 1);
 
-  ## Use Horner scheme to get limits from the left.
-  llim = P(:,1:n-1,1);
-  for i = 2:k;
+  ## Use Horner scheme.
+  if (k>1)
+    llim = shiftdim (reshape (P(1:(n-1) * prod(d), 1), [d, n-1]), nd - 1);
+  endif
+
+  for i = 2 : k;
     llim .*= dx;
-    llim += P(:,1:n-1,i);
+    llim += shiftdim (reshape (P(1:(n-1) * prod (d), i), [d, n-1]), nd - 1);
   endfor
 
-  rlim = P(:,2:n,k); # limits from the right
-  jumps = reshape (rlim - llim, [d, n-1]);
-
+  rlim = shiftdim (ppval (pp, x(2:end-1)), nd - 1);
+  jumps = shiftdim (rlim - llim, 1);
 endfunction
 
+
+%!test
+%! p = [1 6 11 6];
+%! x = linspace (5, 6, 4);
+%! y = polyval (p, x);
+%! pp = spline (x, y);
+%! jj = ppjumps (pp);
+%! assert (jj, [0 0], eps)
+
+%!test
+%!
+%! breaks = [0 1 2];
+%! pp1 = poly (-[1 2 3]);
+%! pp2 = poly (-([1 2 3]+1));
+%! pp = mkpp (breaks, [pp1;pp2]);
+%! assert (ppjumps (pp), 0, eps)
+
+%!test
+%!
+%! breaks = [0 1 2];
+%! pp1 = poly (-[1 2 3]);
+%! pp2 = poly (([1 2 3]+1));
+%! pp = mkpp (breaks, [pp1;pp2]);
+%! j  = - 2 * polyval (pp1, 1);
+%! assert (ppjumps (pp), j, eps)
--- a/scripts/polynomial/ppval.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/polynomial/ppval.m	Tue Sep 20 15:38:24 2011 -0400
@@ -18,16 +18,18 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {@var{yi} =} ppval (@var{pp}, @var{xi})
-## Evaluate piecewise polynomial @var{pp} at the points @var{xi}.
-## If @var{pp} is scalar-valued, the result is an array of the same shape as
-## @var{xi}.
-## Otherwise, the size of the result is @code{[pp.d, length(@var{xi})]} if
-## @var{xi} is a vector, or @code{[pp.d, size(@var{xi})]} if it is a
-## multi-dimensional array.  If pp.orient is 1, the dimensions are permuted as
+## Evaluate piece-wise polynomial structure @var{pp} at the points @var{xi}.
+## If @var{pp} describes a scalar polynomial function, the result is an
+## array of the same shape as @var{xi}.
+## Otherwise, the size of the result is @code{[pp.dim, length(@var{xi})]} if
+## @var{xi} is a vector, or @code{[pp.dim, size(@var{xi})]} if it is a
+## multi-dimensional array.
+##
+##, the dimensions are permuted as
 ## in interp1, to
 ## @code{[pp.d, length(@var{xi})]} and @code{[pp.d, size(@var{xi})]}
 ## respectively.
-## @seealso{mkpp, unmkpp, spline}
+## @seealso{mkpp, unmkpp, spline, pchip, interp1}
 ## @end deftypefn
 
 function yi = ppval (pp, xi)
@@ -35,48 +37,85 @@
   if (nargin != 2)
     print_usage ();
   endif
-  if (! isstruct (pp))
-    error ("ppval: PP must be a structure");
+  if (! isstruct (pp) && strcmp (pp.form, "pp"))
+    error ("ppval: expects a pp-form structure");
   endif
 
   ## Extract info.
-  x = pp.x;
-  P = pp.P;
-  d = pp.d;
-  k = size (P, 3);
-  nd = size (P, 1);
+  [x, P, n, k, d] = unmkpp (pp);
 
-  ## Determine resulting shape.
-  if (d == 1) # scalar case
-    yisz = size (xi);
-  elseif (isvector (xi)) # this is special
-    yisz = [d, length(xi)];
-  else # general
-    yisz = [d, size(xi)];
+  ## dimension checks
+  sxi = size (xi);
+  if (isvector (xi))
+    xi = xi(:).';
   endif
 
+  nd = length (d);
+
   ## Determine intervals.
-  xi = xi(:);
   xn = numel (xi);
+  idx = lookup (x, xi, "lr");
 
-  idx = lookup (x, xi, "lr");
+  P = reshape (P, [d, n * k]);
+  P = shiftdim (P, nd);
+  P = reshape (P, [n, k, d]);
+  Pidx = P(idx(:), :);#2d matrix size x: coefs*prod(d) y: prod(sxi)
+
+  if (isvector(xi))
+    Pidx = reshape (Pidx, [xn, k, d]);
+    Pidx = shiftdim (Pidx, 1);
+    dimvec = [d, xn];
+  else
+    Pidx = reshape (Pidx, [sxi, k, d]);
+    Pidx = shiftdim (Pidx, length (sxi));
+    dimvec = [d, sxi];
+  end
+  ndv = length (dimvec);
 
   ## Offsets.
-  dx = (xi - x(idx)).';
-  dx = dx(ones (1, nd), :); # spread (do nothing in 1D)
+  dx = (xi - x(idx));
+  dx = repmat (dx, [prod(d), 1]);
+  dx = reshape (dx, dimvec);
+  dx = shiftdim (dx, ndv - 1);
 
   ## Use Horner scheme.
-  yi = P(:,idx,1);
-  for i = 2:k;
+  yi = Pidx;
+  if (k > 1)
+    yi = shiftdim (reshape (Pidx(1,:), dimvec), ndv - 1);
+  endif
+
+  for i = 2 : k;
     yi .*= dx;
-    yi += P(:,idx,i);
+    yi += shiftdim (reshape (Pidx(i,:), dimvec), ndv - 1);
   endfor
 
   ## Adjust shape.
-  yi = reshape (yi, yisz);
-  if (d != 1 && pp.orient == 1)
-    ## Switch dimensions to match interp1 order.
-    yi = shiftdim (yi, length (d));
+  if ((numel (xi) > 1) || (length (d) == 1))
+    yi = reshape (shiftdim (yi, 1), dimvec);
+  endif
+
+  if (isvector (xi) && (d == 1))
+    yi = reshape (yi, sxi);
+  elseif (isfield (pp, "orient") && strcmp (pp.orient, "first"))
+    yi = shiftdim(yi, nd);
   endif
 
+  ##
+  #if (d == 1)
+  #  yi = reshape (yi, sxi);
+  #endif
+
 endfunction
+
+%!shared b,c,pp,pp2,xi,abserr
+%! b = 1:3; c = ones(2); pp=mkpp(b,c);abserr = 1e-14;pp2=mkpp(b,[c;c],2);
+%! xi = [1.1 1.3 1.9 2.1];
+%!assert (ppval(pp,1.1), 1.1, abserr);
+%!assert (ppval(pp,2.1), 1.1, abserr);
+%!assert (ppval(pp,xi), [1.1 1.3 1.9 1.1], abserr);
+%!assert (ppval(pp,xi.'), [1.1 1.3 1.9 1.1].', abserr);
+%!assert (ppval(pp2,1.1), [1.1;1.1], abserr);
+%!assert (ppval(pp2,2.1), [1.1;1.1], abserr);
+%!assert (ppval(pp2,xi), [1.1 1.3 1.9 1.1;1.1 1.3 1.9 1.1], abserr);
+%!assert (ppval(pp2,xi'), [1.1 1.3 1.9 1.1;1.1 1.3 1.9 1.1], abserr);
+%!assert (size(ppval(pp2,[xi;xi])), [2 2 4]);
--- a/scripts/polynomial/spline.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/polynomial/spline.m	Tue Sep 20 15:38:24 2011 -0400
@@ -83,15 +83,15 @@
   ## Check the size and shape of y
   ndy = ndims (y);
   szy = size (y);
-  if (ndy == 2 && (szy(1) == 1 || szy(2) == 1))
-    if (szy(1) == 1)
+  if (ndy == 2 && (szy(1) == n || szy(2) == n))
+    if (szy(2) == n)
       a = y.';
     else
       a = y;
       szy = fliplr (szy);
     endif
   else
-    a = reshape (y, [prod(szy(1:end-1)), szy(end)]).';
+    a = shiftdim (reshape (y, [prod(szy(1:end-1)), szy(end)]), 1);
   endif
 
   for k = (1:columns (a))(any (isnan (a)))
@@ -120,9 +120,9 @@
 
     if (n == 2)
       d = (dfs + dfe) / (x(2) - x(1)) ^ 2 + ...
-	2 * (a(1,:) - a(2,:)) / (x(2) - x(1)) ^ 3;
+          2 * (a(1,:) - a(2,:)) / (x(2) - x(1)) ^ 3;
       c = (-2 * dfs - dfe) / (x(2) - x(1)) - ...
-	3 * (a(1,:) - a(2,:)) / (x(2) - x(1)) ^ 2;
+          3 * (a(1,:) - a(2,:)) / (x(2) - x(1)) ^ 2;
       b = dfs;
       a = a(1,:);
 
@@ -132,7 +132,7 @@
       a = a(1:n-1,:);
     else
       if (n == 3)
-	dg = 1.5 * h(1) - 0.5 * h(2);
+        dg = 1.5 * h(1) - 0.5 * h(2);
         c(2:n-1,:) = 1/dg(1);
       else
         dg = 2 * (h(1:n-2) .+ h(2:n-1));
@@ -153,9 +153,9 @@
       endif
 
       c(1,:) = (3 / h(1) * (a(2,:) - a(1,:)) - 3 * dfs
-		- c(2,:) * h(1)) / (2 * h(1));
+             - c(2,:) * h(1)) / (2 * h(1));
       c(n,:) = - (3 / h(n-1) * (a(n,:) - a(n-1,:)) - 3 * dfe
-		  + c(n-1,:) * h(n-1)) / (2 * h(n-1));
+             + c(n-1,:) * h(n-1)) / (2 * h(n-1));
       b(1:n-1,:) = diff (a) ./ h(1:n-1, idx) ...
         - h(1:n-1,idx) / 3 .* (c(2:n,:) + 2 * c(1:n-1,:));
       d = diff (c) ./ (3 * h(1:n-1, idx));
@@ -229,15 +229,14 @@
           - h(1:n-1, idx) / 3 .* (c(2:n,:) + 2 * c(1:n-1,:));
       d = diff (c) ./ (3 * h(1:n-1, idx));
 
-      d = d(1:n-1,:);
-      c = c(1:n-1,:);
-      b = b(1:n-1,:);
-      a = a(1:n-1,:);
+      d = d(1:n-1,:);d = d.'(:);
+      c = c(1:n-1,:);c = c.'(:);
+      b = b(1:n-1,:);b = b.'(:);
+      a = a(1:n-1,:);a = a.'(:);
     endif
 
   endif
-  coeffs = cat (3, d.', c.', b.', a.');
-  ret = mkpp (x, coeffs, szy(1:end-1));
+  ret = mkpp (x, cat (2, d, c, b, a), szy(1:end-1));
 
   if (nargin == 3)
     ret = ppval (ret, xi);
@@ -263,6 +262,9 @@
 %!assert (isempty(spline(x',y',[])));
 %!assert (isempty(spline(x,y,[])));
 %!assert (spline(x,[y;y],x), [spline(x,y,x);spline(x,y,x)],abserr)
+%!assert (spline(x,[y;y],x'), [spline(x,y,x);spline(x,y,x)],abserr)
+%!assert (spline(x',[y;y],x), [spline(x,y,x);spline(x,y,x)],abserr)
+%!assert (spline(x',[y;y],x'), [spline(x,y,x);spline(x,y,x)],abserr)
 %! y = cos(x) + i*sin(x);
 %!assert (spline(x,y,x), y, abserr)
 %!assert (real(spline(x,y,x)), real(y), abserr);
--- a/scripts/polynomial/unmkpp.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/polynomial/unmkpp.m	Tue Sep 20 15:38:24 2011 -0400
@@ -50,15 +50,13 @@
   if (nargin == 0)
     print_usage ();
   endif
-  if (! isstruct (pp))
+  if (! (isstruct (pp) && strcmp (pp.form, "pp")))
     error ("unmkpp: expecting piecewise polynomial structure");
   endif
-  x = pp.x;
-  P = pp.P;
-  n = size (P, 2);
-  k = size (P, 3);
-  d = pp.d;
-  if (d == 1)
-    P = reshape (P, n, k);
-  endif
+  x = pp.breaks;
+  P = pp.coefs;
+  n = pp.pieces;
+  k = pp.order;
+  d = pp.dim;
+
 endfunction
--- a/scripts/set/powerset.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/set/powerset.m	Tue Sep 20 15:38:24 2011 -0400
@@ -75,3 +75,9 @@
   endif
 
 endfunction
+
+
+%!test
+%! c = sort (cellstr ({ [], [1], [2], [3], [1, 2], [1, 3], [2, 3], [1, 2, 3]}));
+%! p = sort (cellstr (powerset ([1, 2, 3])));
+%! assert (p, c);
--- a/scripts/set/setxor.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/set/setxor.m	Tue Sep 20 15:38:24 2011 -0400
@@ -4,14 +4,14 @@
 ## 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 3 of the License, or (at
+## under the terms of the GNU General Public License as published by the
+## Free Software Foundation; either version 3 of the License, or (at
 ## your option) any later version.
 ##
-## 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.
+## 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, see
@@ -20,17 +20,16 @@
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {} setxor (@var{a}, @var{b})
 ## @deftypefnx {Function File} {} setxor (@var{a}, @var{b}, 'rows')
+## @deftypefnx {Function File} {[@var{c}, @var{ia}, @var{ib}] =} setxor (@var{a}, @var{b})
 ##
 ## Return the elements exclusive to @var{a} or @var{b}, sorted in ascending
 ## order.  If @var{a} and @var{b} are both column vectors return a column
 ## vector, otherwise return a row vector.
 ## @var{a}, @var{b} may be cell arrays of string(s).
 ##
-## @deftypefnx {Function File} {[@var{c}, @var{ia}, @var{ib}] =} setxor (@var{a}, @var{b})
-##
-## Return index vectors @var{ia} and @var{ib} such that @code{a(ia)} and
-## @code{b(ib)} are
-## disjoint sets whose union is @var{c}.
+## With three output arguments, return index vectors @var{ia} and @var{ib}
+## such that @code{a(ia)} and @code{b(ib)} are disjoint sets whose union
+## is @var{c}.
 ##
 ## @seealso{unique, union, intersect, setdiff, ismember}
 ## @end deftypefn
--- a/scripts/signal/autoreg_matrix.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/signal/autoreg_matrix.m	Tue Sep 20 15:38:24 2011 -0400
@@ -47,3 +47,16 @@
   endfor
 
 endfunction
+
+
+%!test
+%! K=4;
+%! A = zeros(1,K+1);
+%! A(1) = 1;
+%! B = eye(K+1);
+%! B(:,1) = 1;
+%! assert (autoreg_matrix(A,K),B);
+
+%!error autoreg_matrix()
+%!error autoreg_matrix(1)
+%!error autoreg_matrix(ones(4,1),5)
--- a/scripts/signal/bartlett.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/signal/bartlett.m	Tue Sep 20 15:38:24 2011 -0400
@@ -47,3 +47,17 @@
   endif
 
 endfunction
+
+%!assert (bartlett (1), 1);
+%!assert (bartlett (2), zeros (2,1));
+%!assert (bartlett (16), fliplr (bartlett (16)));
+%!assert (bartlett (15), fliplr (bartlett (15)));
+%!test
+%! N = 9;
+%! A = bartlett (N);
+%! assert (A (ceil (N/2)), 1);
+
+%!error bartlett ();
+%!error bartlett (0.5);
+%!error bartlett (-1);
+%!error bartlett (ones(1,4));
\ No newline at end of file
--- a/scripts/signal/blackman.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/signal/blackman.m	Tue Sep 20 15:38:24 2011 -0400
@@ -46,3 +46,18 @@
   endif
 
 endfunction
+
+%!assert (blackman (1), 1);
+%!assert (blackman (2), zeros(2,1), 1e-6);
+%!assert (blackman (16), fliplr (blackman (16)));
+%!assert (blackman (15), fliplr (blackman (15)));
+%!test
+%! N = 9;
+%! A = blackman (N);
+%! assert (A (ceil (N/2)), 1, 1e-6);
+%! assert ([A(1), A(length (A))], zeros (1, 2), 1e-6);
+
+%!error blackman ();
+%!error blackman (0.5);
+%!error blackman (-1);
+%!error blackman (ones(1,4));
--- a/scripts/signal/fftfilt.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/signal/fftfilt.m	Tue Sep 20 15:38:24 2011 -0400
@@ -54,8 +54,12 @@
   [r_x, c_x] = size (x);
   [r_b, c_b] = size (b);
 
-  if min ([r_b, c_b]) != 1
-    error ("fftfilt: B should be a vector");
+  if (! isvector (b))
+    error ("fftfilt: B must be a vector");
+  endif
+
+  if (ndims (x) != 2)
+    error ("fftfilt: X must be a 1-D or 2-D array");
   endif
 
   l_b = r_b * c_b;
@@ -64,18 +68,18 @@
   if (nargin == 2)
     ## Use FFT with the smallest power of 2 which is >= length (x) +
     ## length (b) - 1 as number of points ...
-    n = 2 ^ (ceil (log (r_x + l_b - 1) / log (2)));
+    n = 2 ^ nextpow2 (r_x + l_b - 1);
     B = fft (b, n);
-    y = ifft (fft (x, n) .* B(:,ones (1, c_x)));
+    y = ifft (fft (x, n) .* B(:, ones (1, c_x)));
   else
     ## Use overlap-add method ...
     if (! (isscalar (n)))
       error ("fftfilt: N has to be a scalar");
     endif
-    n = 2 ^ (ceil (log (max ([n, l_b])) / log (2)));
+    n = 2 ^ nextpow2 (max ([n, l_b]));
     L = n - l_b + 1;
     B = fft (b, n);
-    B = B(:,ones (c_x,1));
+    B = B(:, ones (c_x,1));
     R = ceil (r_x / L);
     y = zeros (r_x, c_x);
     for r = 1:R;
@@ -89,20 +93,59 @@
     endfor
   endif
 
-  y = y(1:r_x,:);
+  y = y(1:r_x, :);
   if (transpose)
     y = y.';
   endif
 
-  ## Final cleanups: if both x and b are real respectively integer, y
-  ## should also be
+  ## Final cleanups: If both x and b are real, y should be real.
+  ## If both x and b are integer, y should be integer.
 
   if (isreal (b) && isreal (x))
     y = real (y);
   endif
-  if (! any (b - round (b)))
-    idx = !any (x - round (x));
-    y(:,idx) = round (y(:,idx));
+  if (! any (b - fix (b)))
+    idx = !any (x - fix (x));
+    y(:, idx) = round (y(:, idx));
   endif
 
 endfunction
+
+
+%!shared b, x, r
+%!test
+%!  b = [1 1];
+%!  x = [1, zeros(1,9)];
+%!  assert(fftfilt(b,  x  ), [1 1 0 0 0 0 0 0 0 0]  , eps);
+%!  assert(fftfilt(b,  x.'), [1 1 0 0 0 0 0 0 0 0].', eps);
+%!  assert(fftfilt(b.',x  ), [1 1 0 0 0 0 0 0 0 0]  , eps);
+%!  assert(fftfilt(b.',x.'), [1 1 0 0 0 0 0 0 0 0].', eps);
+
+%!test
+%!  r = sqrt(1/2) * (1+i);
+%!  b = b*r;
+%!  assert(fftfilt(b, x  ), r*[1 1 0 0 0 0 0 0 0 0]  , eps);
+%!  assert(fftfilt(b, r*x), r*r*[1 1 0 0 0 0 0 0 0 0], eps);
+%!  assert(fftfilt(b, x.'), r*[1 1 0 0 0 0 0 0 0 0].', eps);
+
+%!test
+%!  b = [1 1];
+%!  x = zeros (10,3); x(1,1)=-1; x(1,2)=1;
+%!  y0 = zeros (10,3); y0(1:2,1)=-1; y0(1:2,2)=1;
+%!  y = fftfilt (b, x);
+%!  assert (y,y0);
+
+%!test
+%!  b  = rand (10, 1);
+%!  x  = rand (10, 1);
+%!  y0 = filter (b, 1, x);
+%!  y  = filter (b, 1, x);
+%!  assert (y, y0);
+
+%% Test input validation
+%!error fftfilt (1)
+%!error fftfilt (1, 2, 3, 4)
+%!error fftfilt (ones (2), 1)
+%!error fftfilt (2, ones (3,3,3))
+%!error fftfilt (2, 1, ones (2))
+
--- a/scripts/signal/fftshift.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/signal/fftshift.m	Tue Sep 20 15:38:24 2011 -0400
@@ -58,9 +58,7 @@
     sz = size (x);
     sz2 = ceil (sz(dim) / 2);
     idx = cell ();
-    for i = 1:nd
-      idx{i} = 1:sz(i);
-    endfor
+    idx = repmat ({':'}, nd, 1);
     idx{dim} = [sz2+1:sz(dim), 1:sz2];
     retval = x(idx{:});
   else
--- a/scripts/signal/hamming.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/signal/hamming.m	Tue Sep 20 15:38:24 2011 -0400
@@ -45,3 +45,17 @@
   endif
 
 endfunction
+
+%!assert (hamming (1), 1);
+%!assert (hamming (2), (0.54 - 0.46)*ones(2,1));
+%!assert (hamming (16), fliplr (hamming (16)));
+%!assert (hamming (15), fliplr (hamming (15)));
+%!test
+%! N = 15;
+%! A = hamming (N);
+%! assert (A (ceil (N/2)), 1);
+
+%!error hamming ();
+%!error hamming (0.5);
+%!error hamming (-1);
+%!error hamming (ones(1,4));
--- a/scripts/signal/hanning.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/signal/hanning.m	Tue Sep 20 15:38:24 2011 -0400
@@ -45,3 +45,17 @@
   endif
 
 endfunction
+
+%!assert (hanning (1), 1);
+%!assert (hanning (2), zeros(2,1));
+%!assert (hanning (16), fliplr (hanning (16)));
+%!assert (hanning (15), fliplr (hanning (15)));
+%!test
+%! N = 15;
+%! A = hanning (N);
+%! assert (A (ceil (N/2)), 1);
+
+%!error hanning ();
+%!error hanning (0.5);
+%!error hanning (-1);
+%!error hanning (ones(1,4));
--- a/scripts/signal/ifftshift.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/signal/ifftshift.m	Tue Sep 20 15:38:24 2011 -0400
@@ -45,10 +45,7 @@
     nd = ndims (x);
     sz = size (x);
     sz2 = floor (sz(dim) / 2);
-    idx = cell ();
-    for i = 1:nd
-      idx{i} = 1:sz(i);
-    endfor
+    idx = repmat ({':'}, nd, 1);
     idx{dim} = [sz2+1:sz(dim), 1:sz2];
     retval = x(idx{:});
   else
--- a/scripts/signal/sinc.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/signal/sinc.m	Tue Sep 20 15:38:24 2011 -0400
@@ -45,3 +45,10 @@
   endif
 
 endfunction
+
+
+%!assert (sinc (0), 1);
+%!assert (sinc (1), 0,1e-6);
+%!assert (sinc (1/2), 2/pi, 1e-6)
+
+%!error sinc()
--- a/scripts/signal/sinewave.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/signal/sinewave.m	Tue Sep 20 15:38:24 2011 -0400
@@ -43,3 +43,13 @@
   endif
 
 endfunction
+
+%!assert (sinewave (1), 0);
+%!assert (sinewave (1, 4, 1), 1);
+%!assert (sinewave (1, 12, 1), 1/2, 1e-6);
+%!assert (sinewave (1, 12, 2), sqrt (3)/2, 1e-6);
+%!assert (sinewave (1, 20, 1), (sqrt (5)-1)/4, 1e-6);
+%!assert (sinewave (1), sinewave (1, 1,0));
+%!assert (sinewave (3, 4), sinewave(3, 4, 0));
+
+%!error sinewave ();
--- a/scripts/signal/unwrap.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/signal/unwrap.m	Tue Sep 20 15:38:24 2011 -0400
@@ -55,11 +55,8 @@
       error ("unwrap: DIM must be an integer and a valid dimension");
     endif
   else
-    ## Find the first non-singleton dimension
-    dim = find (sz > 1, 1);
-    if (isempty (dim))
-      dim = 1;
-    endif
+    ## Find the first non-singleton dimension.
+    (dim = find (sz > 1, 1)) || (dim = 1);
   endif
 
   rng = 2*pi;
@@ -74,17 +71,14 @@
 
   ## Take first order difference to see so that wraps will show up
   ## as large values, and the sign will show direction.
-  idx = cell ();
-  for i = 1:nd
-    idx{i} = 1:sz(i);
-  endfor
+  idx = repmat ({':'}, nd, 1);
   idx{dim} = [1,1:m-1];
   d = x(idx{:}) - x;
 
-  ## Find only the peaks, and multiply them by the range so that there
-  ## are kronecker deltas at each wrap point multiplied by the range
-  ## value.
-  p =  rng * (((d > tol) > 0) - ((d < -tol) > 0));
+  ## Find only the peaks, and multiply them by the appropriate amount
+  ## of ranges so that there are kronecker deltas at each wrap point
+  ## multiplied by the appropriate amount of range values.
+  p =  ceil(abs(d)./rng) .* rng .* (((d > tol) > 0) - ((d < -tol) > 0));
 
   ## Now need to "integrate" this so that the deltas become steps.
   r = cumsum (p, dim);
@@ -134,4 +128,28 @@
 %! t(++i) = xassert(any(abs(r - unwrap(w,0.8)) > 100));
 %!
 %! assert(all(t));
-
+%!
+%!test
+%! A = [pi*(-4), pi*(-2+1/6), pi/4, pi*(2+1/3), pi*(4+1/2), pi*(8+2/3), pi*(16+1), pi*(32+3/2), pi*64];
+%! assert (unwrap(A), unwrap(A, pi));
+%! assert (unwrap(A, pi), unwrap(A, pi, 2));
+%! assert (unwrap(A', pi), unwrap(A', pi, 1));
+%!
+%!test
+%! A = [pi*(-4); pi*(2+1/3); pi*(16+1)];
+%! B = [pi*(-2+1/6); pi*(4+1/2); pi*(32+3/2)];
+%! C = [pi/4; pi*(8+2/3); pi*64];
+%! D = [pi*(-2+1/6); pi*(2+1/3); pi*(8+2/3)];
+%! E(:, :, 1) = [A, B, C, D];
+%! E(:, :, 2) = [A+B, B+C, C+D, D+A];
+%! F(:, :, 1) = [unwrap(A), unwrap(B), unwrap(C), unwrap(D)];
+%! F(:, :, 2) = [unwrap(A+B), unwrap(B+C), unwrap(C+D), unwrap(D+A)];
+%! assert (unwrap(E), F);
+%!
+%!test
+%! A = [0, 2*pi, 4*pi, 8*pi, 16*pi, 65536*pi];
+%! B = [pi*(-2+1/6), pi/4, pi*(2+1/3), pi*(4+1/2), pi*(8+2/3), pi*(16+1), pi*(32+3/2), pi*64];
+%! assert (unwrap(A), zeros(1, length(A)));
+%! assert (diff(unwrap(B), 1)<2*pi, true(1, length(B)-1));
+%!
+%!error unwrap()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/sparse/bicg.m	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,254 @@
+## Copyright (C) 2006   Sylvain Pelissier   <sylvain.pelissier@gmail.com>
+## Copyright (C) 2011   Carlo de Falco
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; If not, see <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+##
+## @deftypefn {Function File} {@var{x} =} bicg (@var{A}, @var{b}, @var{rtol}, @var{maxit}, @var{M1}, @var{M2}, @var{x0})
+## @deftypefnx {Function File} {@var{x} =} bicg (@var{A}, @var{b}, @var{rtol}, @var{maxit}, @var{P})
+## @deftypefnx {Function File} {[@var{x}, @var{flag}, @var{relres}, @var{iter}, @var{resvec}] =} bicg (@var{A}, @var{b}, ...)
+## Solve @code{A x = b} using the Bi-conjugate gradient iterative method.
+##
+## @itemize @minus
+## @item @var{rtol} is the relative tolerance, if not given
+## or set to [] the default value 1e-6 is used.
+## @item @var{maxit} the maximum number of outer iterations,
+## if not given or set to [] the default value
+## @code{min (20, numel (b))} is used.
+## @item @var{x0} the initial guess, if not given or set to []
+## the default value @code{zeros (size (b))} is used.
+## @end itemize
+##
+## @var{A} can be passed as a matrix or as a function handle or
+## inline function @code{f} such that @code{f(x, "notransp") = A*x}
+## and @code{f(x, "transp") = A'*x}.
+##
+## The preconditioner @var{P} is given as @code{P = M1 * M2}.
+## Both @var{M1} and @var{M2} can be passed as a matrix or as
+## a function handle or inline function @code{g} such that
+## @code{g(x, 'notransp') = M1 \ x} or @code{g(x, 'notransp') = M2 \ x} and
+## @code{g(x, 'transp') = M1' \ x} or @code{g(x, 'transp') = M2' \ x}.
+##
+## If colled with more than one output parameter
+##
+## @itemize @minus
+## @item @var{flag} indicates the exit status:
+## @itemize @minus
+## @item 0: iteration converged to the within the chosen tolerance
+## @item 1: the maximum number of iterations was reached before convergence
+## @item 3: the algorithm reached stagnation
+## @end itemize
+## (the value 2 is unused but skipped for compatibility).
+## @item @var{relres} is the final value of the relative residual.
+## @item @var{iter} is the number of iterations performed.
+## @item @var{resvec} is a vector containing the relative residual at each iteration.
+## @end itemize
+##
+## @seealso{bicgstab,cgs,gmres,pcg}
+##
+## @end deftypefn
+
+
+function [x, flag, res1, k, resvec] = bicg (A, b, tol, maxit, M1, M2, x0)
+
+  if (nargin >= 2 && isvector (full (b)))
+
+    if (ischar (A))
+      fun = str2func (A);
+      Ax  = @(x) feval (fun, x, "notransp");
+      Atx = @(x) feval (fun, x, "transp");
+    elseif (ismatrix (A))
+      Ax  = @(x) A  * x;
+      Atx = @(x) A' * x;
+    elseif (isa (A, "function_handle"))
+      Ax  = @(x) feval (A, x, "notransp");
+      Atx = @(x) feval (A, x, "transp");
+    else
+      error (["bicg: first argument is expected to " ...
+              "be a function or a square matrix"]);
+    endif
+
+    if (nargin < 3 || isempty (tol))
+      tol = 1e-6;
+    endif
+
+    if (nargin < 4 || isempty (maxit))
+      maxit = min (rows (b), 20);
+    endif
+
+    if (nargin < 5 || isempty (M1))
+      M1m1x = @(x, ignore) x;
+      M1tm1x = M1m1x;
+    elseif (ischar (M1))
+      fun = str2func (M1);
+      M1m1x  = @(x) feval (fun, x, "notransp");
+      M1tm1x = @(x) feval (fun, x, "transp");
+    elseif (ismatrix (M1))
+      M1m1x  = @(x) M1  \ x;
+      M1tm1x = @(x) M1' \ x;
+    elseif (isa (M1, "function_handle"))
+      M1m1x  = @(x) feval (M1, x, "notransp");
+      M1tm1x = @(x) feval (M1, x, "transp");
+    else
+      error (["bicg: preconditioner is expected to " ...
+              "be a function or matrix"]);
+    endif
+
+    if (nargin < 6 || isempty (M2))
+      M2m1x = @(x, ignore) x;
+      M2tm1x = M2m1x;
+    elseif (ischar (M2))
+      fun = str2func (M2);
+      M2m1x  = @(x) feval (fun, x, "notransp");
+      M2tm1x = @(x) feval (fun, x, "transp");
+    elseif (ismatrix (M2))
+      M2m1x  = @(x) M2  \ x;
+      M2tm1x = @(x) M2' \ x;
+    elseif (isa (M2, "function_handle"))
+      M2m1x  = @(x) feval (M2, x, "notransp");
+      M2tm1x = @(x) feval (M2, x, "transp");
+    else
+      error (["bicg: preconditioner is expected to " ...
+              "be a function or matrix"]);
+    endif
+
+    Pm1x  = @(x) M2m1x  (M1m1x (x));
+    Ptm1x = @(x) M1tm1x (M2tm1x (x));
+
+    if (nargin < 7 || isempty (x0))
+      x0 = zeros (size (b));
+    endif
+
+    y = x = x0;
+    c = b;
+
+    r0 = b - Ax (x);
+    s0 = c - Atx (y);
+
+    d = Pm1x (r0);
+    f = Ptm1x (s0);
+
+    bnorm = norm (b);
+    res0  = Inf;
+
+    if (any (r0 != 0))
+
+      for k = 1:maxit
+
+        a  = (s0' * Pm1x (r0)) ./ (f' * Ax (d));
+
+        x += a * d;
+        y += conj (a) * f;
+
+        r1 = r0 - a * Ax (d);
+        s1 = s0 - conj (a) * Atx (f);
+
+        beta = (s1' * Pm1x (r1)) ./ (s0' * Pm1x (r0));
+
+        d = Pm1x (r1) + beta * d;
+        f = Ptm1x (s1) + conj (beta) * f;
+
+        r0 = r1;
+        s0 = s1;
+
+        res1 = norm (b - Ax (x)) / bnorm;
+        if (res1 < tol)
+          flag = 0;
+          if (nargout < 2)
+            printf ("bicg converged at iteration %i ", k);
+            printf ("to a solution with relative residual %e\n", res1);
+          endif
+          break;
+        endif
+
+        if (res0 <= res1)
+          flag = 3;
+          printf ("bicg stopped at iteration %i ", k);
+          printf ("without converging to the desired tolerance %e\n", tol);
+          printf ("because the method stagnated.\n");
+          printf ("The iterate returned (number %i) ", k-1);
+          printf ("has relative residual %e\n", res0);
+          break
+        endif
+        res0 = res1;
+        if (nargout > 4)
+          resvec(k) = res0;
+        endif
+      endfor
+
+      if (k == maxit)
+        flag = 1;
+        printf ("bicg stopped at iteration %i ", maxit);
+        printf ("without converging to the desired tolerance %e\n", tol);
+        printf ("because the maximum number of iterations was reached. ");
+        printf ("The iterate returned (number %i) has ", maxit);
+        printf ("relative residual %e\n", res1);
+      endif
+
+    else
+      flag = 0;
+      if (nargout < 2)
+        printf ("bicg converged after 0 interations\n");
+      endif
+    endif
+
+  else
+    print_usage ();
+  endif
+
+endfunction;
+
+
+%!test
+%! n = 100;
+%! A = spdiags ([-2*ones(n,1) 4*ones(n,1) -ones(n,1)], -1:1, n, n);
+%! b = sum (A, 2);
+%! tol = 1e-8;
+%! maxit = 15;
+%! M1 = spdiags ([ones(n,1)/(-2) ones(n,1)],-1:0, n, n);
+%! M2 = spdiags ([4*ones(n,1) -ones(n,1)], 0:1, n, n);
+%! [x, flag, relres, iter, resvec] = bicg (A, b, tol, maxit, M1, M2);
+%! assert (x, ones (size (b)), 1e-7);
+%!
+%!test
+%! n = 100;
+%! A = spdiags ([-2*ones(n,1) 4*ones(n,1) -ones(n,1)], -1:1, n, n);
+%! b = sum (A, 2);
+%! tol = 1e-8;
+%! maxit = 15;
+%! M1 = spdiags ([ones(n,1)/(-2) ones(n,1)],-1:0, n, n);
+%! M2 = spdiags ([4*ones(n,1) -ones(n,1)], 0:1, n, n);
+%!
+%! function y = afun (x, t, a)
+%!  switch t
+%!   case "notransp"
+%!     y = a * x;
+%!   case "transp"
+%!     y = a' * x;
+%!  endswitch
+%! endfunction
+%!
+%! [x, flag, relres, iter, resvec] = bicg (@(x, t) afun (x, t, A),
+%!                                         b, tol, maxit, M1, M2);
+%! assert (x, ones (size (b)), 1e-7);
+
+%!test
+%! n = 100;
+%! tol = 1e-8;
+%! a = sprand (n, n, .1);
+%! A = a' * a + 100 * eye (n);
+%! b = sum (A, 2);
+%! [x, flag, relres, iter, resvec] = bicg (A, b, tol, [], diag (diag (A)));
+%! assert (x, ones (size (b)), 1e-7);
--- a/scripts/sparse/bicgstab.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/sparse/bicgstab.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,4 +1,5 @@
 ## Copyright (C) 2008-2011 Radek Salac
+## Copyright (C) 2011 Carlo de Falco
 ##
 ## This file is part of Octave.
 ##
@@ -17,155 +18,181 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} bicgstab (@var{A}, @var{b})
-## @deftypefnx {Function File} {} bicgstab (@var{A}, @var{b}, @var{tol}, @var{maxit}, @var{M1}, @var{M2}, @var{x0})
-## This procedure attempts to solve a system of linear equations A*x = b for x.
-## The @var{A} must be square, symmetric and positive definite real matrix N*N.
-## The @var{b} must be a one column vector with a length of N.
-## The @var{tol} specifies the tolerance of the method, the default value is
-## 1e-6.
-## The @var{maxit} specifies the maximum number of iterations, the default value
-## is min(20,N).
-## The @var{M1} specifies a preconditioner, can also be a function handler which
-## returns M\X.
-## The @var{M2} combined with @var{M1} defines preconditioner as
-## preconditioner=M1*M2.
-## The @var{x0} is the initial guess, the default value is zeros(N,1).
+##
+## @deftypefn {Function File} {@var{x} =} bicgstab (@var{A}, @var{b}, @var{rtol}, @var{maxit}, @var{M1}, @var{M2}, @var{x0})
+## @deftypefnx {Function File} {@var{x} =} bicgstab (@var{A}, @var{b}, @var{rtol}, @var{maxit}, @var{P})
+## @deftypefnx {Function File} {[@var{x}, @var{flag}, @var{relres}, @var{iter}, @var{resvec}] =} bicgstab (@var{A}, @var{b}, ...)
+## Solve @code{A x = b} using the stabilizied Bi-conjugate gradient iterative method.
+##
+## @itemize @minus
+## @item @var{rtol} is the relative tolerance, if not given or set to
+## [] the default value 1e-6 is used.
+## @item @var{maxit} the maximum number of outer iterations, if not
+## given or set to [] the default value @code{min (20, numel (b))} is
+## used.
+## @item @var{x0} the initial guess, if not given or set to [] the
+## default value @code{zeros (size (b))} is used.
+## @end itemize
+##
+## @var{A} can be passed as a matrix or as a function handle or
+## inline function @code{f} such that @code{f(x) = A*x}.
 ##
-## The value @var{x} is a computed result of this procedure.
-## The value @var{flag} can be 0 when we reach tolerance in @var{maxit}
-## iterations, 1 when
-## we don't reach tolerance in @var{maxit} iterations and 3 when the procedure
-## stagnates.
-## The value @var{relres} is a relative residual - norm(b-A*x)/norm(b).
-## The value @var{iter} is an iteration number in which x was computed.
-## The value @var{resvec} is a vector of @var{relres} for each iteration.
+## The preconditioner @var{P} is given as @code{P = M1 * M2}.
+## Both @var{M1} and @var{M2} can be passed as a matrix or as a function handle or
+## inline function @code{g} such that @code{g(x) = M1 \ x} or @code{g(x) = M2 \ x}.
+##
+## If called with more than one output parameter
+##
+## @itemize @minus
+## @item @var{flag} indicates the exit status:
+## @itemize @minus
+## @item 0: iteration converged to the within the chosen tolerance
+## @item 1: the maximum number of iterations was reached before convergence
+## @item 3: the algorithm reached stagnation
+## @end itemize
+## (the value 2 is unused but skipped for compatibility).
+## @item @var{relres} is the final value of the relative residual.
+## @item @var{iter} is the number of iterations performed.
+## @item @var{resvec} is a vector containing the relative residual at each iteration.
+## @end itemize
+##
+## @seealso{bicg,cgs,gmres,pcg}
 ##
 ## @end deftypefn
 
-function [x, flag, relres, iter, resvec] = bicgstab (A, b, tol, maxit, M1, M2, x0)
+function [x, flag, relres, iter, resvec] = bicgstab (A, b, tol, maxit,
+                                                     M1, M2, x0)
+
+  if (nargin >= 2 && nargin <= 7 && isvector (full (b)))
 
-  if (nargin < 2 || nargin > 7 || nargout > 5)
-    print_usage ();
-  elseif (!(isnumeric (A) && issquare (A)))
-    error ("bicgstab: A must be a square numeric matrix");
-  elseif (!isvector (b))
-    error ("bicgstab: B must be a vector");
-  elseif (!any (b))
-    error ("bicgstab: B must not be a vector of all zeros");
-  elseif (rows (A) != rows (b))
-    error ("bicgstab: A and B must have the same number of rows");
-  elseif (nargin > 2 && !isscalar (tol))
-    error ("bicgstab: TOL must be a scalar");
-  elseif (nargin > 3 && !isscalar (maxit))
-    error ("bicgstab: MAXIT must be a scalar");
-  elseif (nargin > 4 && ismatrix (M1) && (rows (M1) != rows (A) || columns (M1) != columns (A)))
-    error ("bicgstab: M1 must have the same number of rows and columns as A");
-  elseif (nargin > 5 && (!ismatrix (M2) || rows (M2) != rows (A) || columns (M2) != columns (A)))
-    error ("bicgstab: M2 must have the same number of rows and columns as A");
-  elseif (nargin > 6 && !isvector (x0))
-    error ("bicgstab: X0 must be a vector");
-  elseif (nargin > 6 && rows (x0) != rows (b))
-    error ("bicgstab: X0 must have the same number of rows as B");
-  endif
+    if (ischar (A))
+      A = str2func (A);
+    elseif (ismatrix (A))
+      Ax  = @(x) A  * x;
+    elseif (isa (A, "function_handle"))
+      Ax  = @(x) feval (A, x);
+    else
+      error (["bicgstab: first argument is expected " ...
+              "to be a function or a square matrix"]);
+    endif
 
-  ## Default tolerance.
-  if (nargin < 3)
-    tol = 1e-6;
-  endif
+    if (nargin < 3 || isempty (tol))
+      tol = 1e-6;
+    endif
 
-  ## Default maximum number of iteration.
-  if (nargin < 4)
-    maxit = min (rows (b), 20);
-  endif
+    if (nargin < 4 || isempty (maxit))
+      maxit = min (rows (b), 20);
+    endif
 
-  ## Left preconditioner.
-  if (nargin == 5)
-    if (isnumeric (M1))
-      precon = @(x) M1 \ x;
+    if (nargin < 5 || isempty (M1))
+      M1m1x = @(x) x;
+    elseif (ischar (M1))
+      M1m1x = str2func (M1);
+    elseif (ismatrix (M1))
+      M1m1x = @(x) M1  \ x;
+    elseif (isa (M1, "function_handle"))
+      M1m1x = @(x) feval (M1, x);
+    else
+      error (["bicgstab: preconditioner is " ...
+              "expected to be a function or matrix"]);
     endif
-  elseif (nargin > 5)
-    if (issparse (M1) && issparse (M2))
-      precon = @(x) M2 \ (M1 \ x);
-    else
-      M = M1*M2;
-      precon = @(x) M \ x;
-    endif
-  else
-    precon = @(x) x;
-  endif
 
-  ## specifies initial estimate x0
-  if (nargin < 7)
-    x = zeros (rows (b), 1);
-  else
-    x = x0;
-  endif
-
-  norm_b = norm (b);
-
-  res = b - A*x;
-  rr = res;
+    if (nargin < 6 || isempty (M2))
+      M2m1x = @(x) x;
+    elseif (ischar (M2))
+      M2m1x = str2func (M2);
+    elseif (ismatrix (M2))
+      M2m1x = @(x) M2  \ x;
+    elseif (isa (M2, "function_handle"))
+      M2m1x = @(x) feval (M2, x);
+    else
+      error (["bicgstab: preconditioner is "...
+              "expected to be a function or matrix"]);
+    endif
 
-  ## Vector of the residual norms for each iteration.
-  resvec = [norm(res)/norm_b];
+    precon = @(x) M2m1x (M1m1x (x));
 
-  ## Default behaviour we don't reach tolerance tol within maxit iterations.
-  flag = 1;
+    if (nargin < 7 || isempty (x0))
+      x0 = zeros (size (b));
+    endif
 
-  for iter = 1:maxit
-    rho_1 = res' * rr;
-
-    if (iter == 1)
-      p = res;
+    ## specifies initial estimate x0
+    if (nargin < 7)
+      x = zeros (rows (b), 1);
     else
-      beta = (rho_1 / rho_2) * (alpha / omega);
-      p = res + beta * (p - omega * v);
+      x = x0;
     endif
 
-    phat = precon (p);
+    norm_b = norm (b);
+
+    res = b - Ax (x);
+    rr = res;
 
-    v = A * phat;
-    alpha = rho_1 / (rr' * v);
-    s = res - alpha * v;
+    ## Vector of the residual norms for each iteration.
+    resvec = norm(res) / norm_b;
 
-    shat = precon (s);
+    ## Default behaviour we don't reach tolerance tol within maxit iterations.
+    flag = 1;
+
+    for iter = 1:maxit
+      rho_1 = res' * rr;
 
-    t = A * shat;
-    omega = (t' * s) / (t' * t);
-    x = x + alpha * phat + omega * shat;
-    res = s - omega * t;
-    rho_2 = rho_1;
+      if (iter == 1)
+        p = res;
+      else
+        beta = (rho_1 / rho_2) * (alpha / omega);
+        p = res + beta * (p - omega * v);
+      endif
+
+      phat = precon (p);
 
-    relres = norm (res) / norm_b;
-    resvec = [resvec; relres];
+      v = Ax (phat);
+      alpha = rho_1 / (rr' * v);
+      s = res - alpha * v;
+
+      shat = precon (s);
+
+      t = Ax (shat);
+      omega = (t' * s) / (t' * t);
+      x = x + alpha * phat + omega * shat;
+      res = s - omega * t;
+      rho_2 = rho_1;
 
-    if (relres <= tol)
-      ## We reach tolerance tol within maxit iterations.
-      flag = 0;
-      break;
-    elseif (resvec (end) == resvec (end - 1))
-      ## The method stagnates.
-      flag = 3;
-      break;
-    endif
-  endfor
+      relres = norm (res) / norm_b;
+      resvec = [resvec; relres];
+
+      if (relres <= tol)
+        ## We reach tolerance tol within maxit iterations.
+        flag = 0;
+        break;
+      elseif (resvec(end) == resvec(end - 1))
+        ## The method stagnates.
+        flag = 3;
+        break;
+      endif
+    endfor
 
-  if (nargout < 2)
-    if (flag == 0)
-      printf (["bicgstab converged at iteration %i ",
-      "to a solution with relative residual %e\n"],iter,relres);
-    elseif (flag == 3)
-      printf (["bicgstab stopped at iteration %i ",
-      "without converging to the desired tolerance %e\n",
-      "because the method stagnated.\n",
-      "The iterate returned (number %i) has relative residual %e\n"],iter,tol,iter,relres);
-    else
-      printf (["bicgstab stopped at iteration %i ",
-      "without converging to the desired toleranc %e\n",
-      "because the maximum number of iterations was reached.\n",
-      "The iterate returned (number %i) has relative residual %e\n"],iter,tol,iter,relres);
+    if (nargout < 2)
+      if (flag == 0)
+        printf ("bicgstab converged at iteration %i ", iter);
+        printf ("to a solution with relative residual %e\n", relres);
+      elseif (flag == 3)
+        printf ("bicgstab stopped at iteration %i ", iter);
+        printf ("without converging to the desired tolerance %e\n", tol);
+        printf ("because the method stagnated.\n");
+        printf ("The iterate returned (number %i) ", iter);
+        printf ("has relative residual %e\n", relres);
+      else
+        printf ("bicgstab stopped at iteration %i ", iter);
+        printf ("without converging to the desired toleranc %e\n", tol);
+        printf ("because the maximum number of iterations was reached.\n");
+        printf ("The iterate returned (number %i) ", iter);
+        printf ("has relative residual %e\n", relres);
+      endif
     endif
+
+  else
+    print_usage ();
   endif
 
 endfunction
@@ -176,3 +203,36 @@
 %! b = [7;-1;4]
 %! [x, flag, relres, iter, resvec] = bicgstab(A, b)
 
+%!shared A, b, n, M1, M2
+%!
+%!test
+%! n = 100;
+%! A = spdiags ([-2*ones(n,1) 4*ones(n,1) -ones(n,1)], -1:1, n, n);
+%! b = sum (A, 2);
+%! tol = 1e-8;
+%! maxit = 15;
+%! M1 = spdiags ([ones(n,1)/(-2) ones(n,1)],-1:0, n, n);
+%! M2 = spdiags ([4*ones(n,1) -ones(n,1)], 0:1, n, n);
+%! [x, flag, relres, iter, resvec] = bicgstab (A, b, tol, maxit, M1, M2);
+%! assert (x, ones (size (b)), 1e-7);
+%!
+%!test
+%! tol = 1e-8;
+%! maxit = 15;
+%!
+%! function y = afun (x, a)
+%!     y = a * x;
+%! endfunction
+%!
+%! [x, flag, relres, iter, resvec] = bicgstab (@(x) afun (x, A), b,
+%!                                             tol, maxit, M1, M2);
+%! assert (x, ones (size (b)), 1e-7);
+
+%!test
+%! n = 100;
+%! tol = 1e-8;
+%! a = sprand (n, n, .1);
+%! A = a'*a + 100 * eye (n);
+%! b = sum (A, 2);
+%! [x, flag, relres, iter, resvec] = bicgstab (A, b, tol, [], diag (diag (A)));
+%! assert (x, ones (size (b)), 1e-7);
--- a/scripts/sparse/cgs.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/sparse/cgs.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,4 +1,5 @@
 ## Copyright (C) 2008-2011 Radek Salac
+## Copyright (C) 2011 Carlo de Falco
 ##
 ## This file is part of Octave.
 ##
@@ -17,134 +18,165 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} cgs (@var{A}, @var{b})
-## @deftypefnx {Function File} {} cgs (@var{A}, @var{b}, @var{tol}, @var{maxit}, @var{M1}, @var{M2}, @var{x0})
-## This procedure attempts to solve a system of linear equations A*x = b for x.
-## The @var{A} must be square, symmetric and positive definite real matrix N*N.
-## The @var{b} must be a one column vector with a length of N.
-## The @var{tol} specifies the tolerance of the method, default value is 1e-6.
-## The @var{maxit} specifies the maximum number of iteration, default value is
-## MIN(20,N).
-## The @var{M1} specifies a preconditioner, can also be a function handler which
-## returns M\X.
-## The @var{M2} combined with @var{M1} defines preconditioner as
-## preconditioner=M1*M2.
-## The @var{x0} is initial guess, default value is zeros(N,1).
+##
+## @deftypefn {Function File} {@var{x} =} cgs (@var{A}, @var{b}, @var{rtol}, @var{maxit}, @var{M1}, @var{M2}, @var{x0})
+## @deftypefnx {Function File} {@var{x} =} cgs (@var{A}, @var{b}, @var{rtol}, @var{maxit}, @var{P})
+## @deftypefnx {Function File} {[@var{x}, @var{flag}, @var{relres}, @var{iter}, @var{resvec}] =} cgs (@var{A}, @var{b}, ...)
+## Solve @code{A x = b}, where @var{A} is a square matrix, using the
+## Conjugate Gradients Squared method.
+##
+## @itemize @minus
+## @item @var{rtol} is the relative tolerance, if not given or set to []
+## the default value 1e-6 is used.
+## @item @var{maxit} the maximum number of outer iterations, if not
+## given or set to [] the default value @code{min (20, numel (b))} is
+## used.
+## @item @var{x0} the initial guess, if not given or set to [] the
+## default value @code{zeros (size (b))} is used.
+## @end itemize
+##
+## @var{A} can be passed as a matrix or as a function handle or
+## inline function @code{f} such that @code{f(x) = A*x}.
 ##
+## The preconditioner @var{P} is given as @code{P = M1 * M2}.
+## Both @var{M1} and @var{M2} can be passed as a matrix or as a function
+## handle or inline function @code{g} such that @code{g(x) = M1 \ x} or
+## @code{g(x) = M2 \ x}.
+##
+## If called with more than one output parameter
+##
+## @itemize @minus
+## @item @var{flag} indicates the exit status:
+## @itemize @minus
+## @item 0: iteration converged to the within the chosen tolerance
+## @item 1: the maximum number of iterations was reached before convergence
+## @item 3: the algorithm reached stagnation
+## @end itemize
+## (the value 2 is unused but skipped for compatibility).
+## @item @var{relres} is the final value of the relative residual.
+## @item @var{iter} is the number of iterations performed.
+## @item @var{resvec} is a vector containing the relative residual at
+## each iteration.
+## @end itemize
+##
+## @seealso{pcg,bicgstab,bicg,gmres}
 ## @end deftypefn
 
 function [x, flag, relres, iter, resvec] = cgs (A, b, tol, maxit, M1, M2, x0)
 
-  if (nargin < 2 || nargin > 7 || nargout > 5)
-    print_usage ();
-  elseif (!(isnumeric (A) && issquare (A)))
-    error ("cgs: A must be a square numeric matrix");
-  elseif (!isvector (b))
-    error ("cgs: B must be a vector");
-  elseif (rows (A) != rows (b))
-    error ("cgs: A and B must have the same number of rows");
-  elseif (nargin > 2 && !isscalar (tol))
-    error ("cgs: TOL must be a scalar");
-  elseif (nargin > 3 && !isscalar (maxit))
-    error ("cgs: MAXIT must be a scalar");
-  elseif (nargin > 4 && ismatrix (M1) && (rows (M1) != rows (A) || columns (M1) != columns (A)))
-    error ("cgs: M1 must have the same number of rows and columns as A");
-  elseif (nargin > 5 && (!ismatrix (M2) || rows (M2) != rows (A) || columns (M2) != columns (A)))
-    error ("cgs: M2 must have the same number of rows and columns as A");
-  elseif (nargin > 6 && !isvector (x0))
-    error ("cgs: X0 must be a vector");
-  elseif (nargin > 6 && rows (x0) != rows (b))
-    error ("cgs: X0 must have the same number of rows as B");
-  endif
+  if (nargin >= 2 && nargin <= 7 && isvector (full (b)))
 
-  ## Default tolerance.
-  if (nargin < 3)
-    tol = 1e-6;
-  endif
+    if (ischar (A))
+      A = str2func (A);
+    elseif (ismatrix (A))
+      Ax = @(x) A * x;
+    elseif (isa (A, "function_handle"))
+      Ax = @(x) feval (A, x);
+    else
+      error (["cgs: first argument is expected to "...
+              "be a function or a square matrix"]);
+    endif
+
+    if (nargin < 3 || isempty (tol))
+      tol = 1e-6;
+    endif
+
+    if (nargin < 4 || isempty (maxit))
+      maxit = min (rows (b), 20);
+    endif
 
-  ## Default maximum number of iteration.
-  if (nargin < 4)
-    maxit = min (rows (b),20);
-  endif
-
-  ## Left preconditioner.
-  if (nargin == 5)
-    if (isnumeric (M1))
-      precon = @(x) M1 \ x;
-    endif
-  elseif (nargin > 5)
-    if (issparse (M1) && issparse (M2))
-      precon = @(x) M2 \ (M1 \ x);
+    if (nargin < 5 || isempty (M1))
+      M1m1x = @(x) x;
+    elseif (ischar (M1))
+      M1m1x = str2func (M1);
+    elseif (ismatrix (M1))
+      M1m1x = @(x) M1 \ x;
+    elseif (isa (M1, "function_handle"))
+      M1m1x = @(x) feval (M1, x);
     else
-      M = M1*M2;
-      precon = @(x) M \ x;
+      error ("cgs: preconditioner is expected to be a function or matrix");
     endif
-  else
-    precon = @(x) x;
-  endif
 
-  ## Specifies initial estimate x0.
-  if (nargin < 7)
-    x = zeros (rows (b), 1);
-  else
+    if (nargin < 6 || isempty (M2))
+      M2m1x = @(x) x;
+    elseif (ischar (M2))
+      M2m1x = str2func (M2);
+    elseif (ismatrix (M2))
+      M2m1x = @(x) M2 \ x;
+    elseif (isa (M2, "function_handle"))
+      M2m1x = @(x) feval (M2, x);
+    else
+      error ("cgs: preconditioner is expected to be a function or matrix");
+    endif
+
+    precon = @(x) M2m1x (M1m1x (x));
+
+    if (nargin < 7 || isempty (x0))
+      x0 = zeros (size (b));
+    endif
+
+
     x = x0;
-  endif
 
-  res = b - A * x;
-  norm_b = norm (b);
-  ## Vector of the residual norms for each iteration.
-  resvec = [ norm(res)/norm_b ];
-  ro = 0;
-  ## Default behavior we don't reach tolerance tol within maxit iterations.
-  flag = 1;
-  for iter = 1 : maxit
+    res = b - Ax (x);
+    norm_b = norm (b);
+    ## Vector of the residual norms for each iteration.
+    resvec = norm (res) / norm_b;
+    ro = 0;
+    ## Default behavior we don't reach tolerance tol within maxit iterations.
+    flag = 1;
+    for iter = 1:maxit
 
-    z = precon (res);
+      z = precon (res);
 
-    ## Cache.
-    ro_old = ro;
-    ro = res' * z;
-    if (iter == 1)
-      p = z;
-    else
-      beta = ro / ro_old;
-      p = z + beta * p;
-    endif
-    ## Cache.
-    q = A * p;
-    alpha = ro / (p' * q);
-    x = x + alpha * p;
+      ## Cache.
+      ro_old = ro;
+      ro = res' * z;
+      if (iter == 1)
+        p = z;
+      else
+        beta = ro / ro_old;
+        p = z + beta * p;
+      endif
+      ## Cache.
+      q = Ax (p);
+      alpha = ro / (p' * q);
+      x = x + alpha * p;
+
+      res = res - alpha * q;
+      relres = norm (res) / norm_b;
+      resvec = [resvec; relres];
 
-    res = res - alpha * q;
-    relres = norm(res) / norm_b;
-    resvec = [resvec;relres];
-
-    if (relres <= tol)
-      ## We reach tolerance tol within maxit iterations.
-      flag = 0;
-      break;
-    elseif (resvec (end) == resvec (end - 1))
-      ## The method stagnates.
-      flag = 3;
-      break;
-    endif
-  endfor;
+      if (relres <= tol)
+        ## We reach tolerance tol within maxit iterations.
+        flag = 0;
+        break
+      elseif (resvec (end) == resvec (end - 1))
+        ## The method stagnates.
+        flag = 3;
+        break
+      endif
+    endfor
 
-  if (nargout < 1)
-    if ( flag == 0 )
-      printf (["cgs converged at iteration %i ",
-      "to a solution with relative residual %e\n"],iter,relres);
-    elseif (flag == 3)
-      printf (["cgs stopped at iteration %i ",
-      "without converging to the desired tolerance %e\n",
-      "because the method stagnated.\n",
-      "The iterate returned (number %i) has relative residual %e\n"],iter,tol,iter,relres);
-    else
-      printf (["cgs stopped at iteration %i ",
-      "without converging to the desired tolerance %e\n",
-      "because the maximum number of iterations was reached.\n",
-      "The iterate returned (number %i) has relative residual %e\n"],iter,tol,iter,relres);
+    if (nargout < 1)
+      if (flag == 0)
+        printf ("cgs converged at iteration %i to a solution with relative residual %e\n",
+                iter, relres);
+      elseif (flag == 3)
+        printf (["cgs stopped at iteration %i without converging to the desired tolerance %e\n",
+                 "because the method stagnated.\n",
+                 "The iterate returned (number %i) has relative residual %e\n"],
+                iter, tol, iter, relres);
+      else
+        printf (["cgs stopped at iteration %i without converging to the desired tolerance %e\n",
+                 "because the maximum number of iterations was reached.\n",
+                 "The iterate returned (number %i) has relative residual %e\n"],
+                iter, tol, iter, relres);
+      endif
     endif
+
+  else
+    print_usage ();
   endif
 
 endfunction
@@ -156,3 +188,31 @@
 %! A=[5 -1 3;-1 2 -2;3 -2 3]
 %! b=[7;-1;4]
 %! [a,b,c,d,e]=cgs(A,b)
+
+%!shared A, b, n, M
+%!
+%!test
+%! n = 100;
+%! A = spdiags ([-ones(n,1) 4*ones(n,1) -ones(n,1)], -1:1, n, n);
+%! b = sum (A, 2);
+%! tol = 1e-8;
+%! maxit = 1000;
+%! M = 4*eye (n);
+%! [x, flag, relres, iter, resvec] = cgs (A, b, tol, maxit, M);
+%! assert (x, ones (size (b)), 1e-7);
+%!
+%!test
+%! tol = 1e-8;
+%! maxit = 15;
+%!
+%! [x, flag, relres, iter, resvec] = cgs (@(x) A * x, b, tol, maxit, M);
+%! assert (x, ones (size (b)), 1e-7);
+
+%!test
+%! n = 100;
+%! tol = 1e-8;
+%! a = sprand (n, n, .1);
+%! A = a'*a + 100 * eye (n);
+%! b = sum (A, 2);
+%! [x, flag, relres, iter, resvec] = cgs (A, b, tol, [], diag (diag (A)));
+%! assert (x, ones (size (b)), 1e-7);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/sparse/gmres.m	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,212 @@
+## Copyright (C) 2009-2011 Carlo de Falco
+##
+## 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 3 of the License, 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, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {Function File} {@var{x} =} gmres (@var{A}, @var{b}, @var{m}, @var{rtol}, @var{maxit}, @var{M1}, @var{M2}, @var{x0})
+## @deftypefnx {Function File} {@var{x} =} gmres (@var{A}, @var{b}, @var{m}, @var{rtol}, @var{maxit}, @var{P})
+## @deftypefnx {Function File} {[@var{x}, @var{flag}, @var{relres}, @var{iter}, @var{resvec}] =} gmres (@dots{})
+## Solve @code{A x = b} using the Preconditioned GMRES iterative method
+## with restart, a.k.a. PGMRES(m).
+##
+## @itemize @minus
+## @item @var{rtol} is the relative tolerance,
+## if not given or set to [] the default value 1e-6 is used.
+##
+## @item @var{maxit} is the maximum number of outer iterations,
+## if not given or set to [] the default value
+## @code{min (10, numel (b) / restart)} is used.
+##
+## @item @var{x0} is the initial guess,
+## if not given or set to [] the default value @code{zeros(size (b))} is used.
+##
+## @item @var{m} is the restart parameter,
+## if not given or set to [] the default value @code{numel (b)} is used.
+## @end itemize
+##
+## Argument @var{A} can be passed as a matrix, function handle, or
+## inline function @code{f} such that @code{f(x) = A*x}.
+##
+## The preconditioner @var{P} is given as @code{P = M1 * M2}.
+## Both @var{M1} and @var{M2} can be passed as a matrix, function handle, or
+## inline function @code{g} such that @code{g(x) = M1\x} or @code{g(x) = M2\x}.
+##
+## Besides the vector @var{x}, additional outputs are:
+##
+## @itemize @minus
+## @item @var{flag} indicates the exit status:
+## @table @asis
+## @item 0 : iteration converged to within the specified tolerance
+## @item 1 : maximum number of iterations exceeded
+## @item 2 : unused, but skipped for compatibility
+## @item 3 : algorithm reached stagnation
+## @end table
+## @item @var{relres} is the final value of the relative residual.
+## @item @var{iter} is a vector containing the number of outer iterations and
+## total iterations performed.
+## @item @var{resvec} is a vector containing the relative residual at each
+## iteration.
+## @end itemize
+##
+## @seealso{bicg, bicgstab, cgs, pcg}
+## @end deftypefn
+
+function [x, flag, presn, it] = gmres (A, b, restart, rtol, maxit, M1, M2, x0)
+
+  if (nargin < 2 || nargin > 8)
+    print_usage ();
+  endif
+
+  if (ischar (A))
+    Ax = str2func (A);
+  elseif (ismatrix (A))
+    Ax = @(x) A*x;
+  elseif (isa (A, "function_handle"))
+    Ax = A;
+  else
+    error ("gmres: A must be a function or matrix");
+  endif
+
+  if (nargin < 3 || isempty (restart))
+    restart = rows (b);
+  endif
+
+  if (nargin < 4 || isempty (rtol))
+    rtol = 1e-6;
+  endif
+
+  if (nargin < 5 || isempty (maxit))
+    maxit = min (rows (b)/restart, 10);
+  endif
+
+  if (nargin < 6 || isempty (M1))
+    M1m1x = @(x) x;
+  elseif (ischar (M1))
+    M1m1x = str2func (M1);
+  elseif (ismatrix (M1))
+    M1m1x = @(x) M1 \ x;
+  elseif (isa (M1, "function_handle"))
+    M1m1x = M1;
+  else
+    error ("gmres: preconditioner M1 must be a function or matrix");
+  endif
+
+  if (nargin < 7 || isempty (M2))
+    M2m1x = @(x) x;
+  elseif (ischar (M2))
+    M2m1x = str2func (M2);
+  elseif (ismatrix (M2))
+    M2m1x = @(x) M2 \ x;
+  elseif (isa (M2, "function_handle"))
+    M2m1x = M2;
+  else
+    error ("gmres: preconditioner M2 must be a function or matrix");
+  endif
+
+  Pm1x = @(x) M2m1x (M1m1x (x));
+
+  if (nargin < 8 || isempty (x0))
+    x0 = zeros (size (b));
+  endif
+
+  x_old = x0;
+  x = x_old;
+  prec_res = Pm1x (b - Ax (x_old));
+  presn = norm (prec_res, 2);
+
+  B = zeros (restart + 1, 1);
+  V = zeros (rows (x), restart);
+  H = zeros (restart + 1, restart);
+
+  ## begin loop
+  iter = 1;
+  restart_it  = restart + 1;
+  resids      = zeros (maxit, 1);
+  resids(1)   = presn;
+  prec_b_norm = norm (Pm1x (b), 2);
+  flag        = 1;
+
+  while (iter <= maxit * restart && presn > rtol * prec_b_norm)
+
+    ## restart
+    if (restart_it > restart)
+      restart_it = 1;
+      x_old = x;
+      prec_res = Pm1x (b - Ax (x_old));
+      presn = norm (prec_res, 2);
+      B(1) = presn;
+      H(:) = 0;
+      V(:, 1) = prec_res / presn;
+    endif
+
+    ## basic iteration
+    tmp = Pm1x (Ax (V(:, restart_it)));
+    [V(:,restart_it+1), H(1:restart_it+1, restart_it)] = ...
+        mgorth (tmp, V(:,1:restart_it));
+
+    Y = (H(1:restart_it+1, 1:restart_it) \ B (1:restart_it+1));
+
+    little_res = B(1:restart_it+1) - ...
+        H(1:restart_it+1, 1:restart_it) * Y(1:restart_it);
+
+    presn = norm (little_res, 2);
+
+    x = x_old + V(:, 1:restart_it) * Y(1:restart_it);
+
+    resids(iter) = presn;
+    if (norm (x - x_old, inf) <= eps)
+      flag = 3;
+      break
+    endif
+
+    restart_it++ ;
+    iter++;
+  endwhile
+
+  if (presn > rtol * prec_b_norm)
+    flag = 0;
+  endif
+
+  resids = resids(1:iter-1);
+  it = [floor(maxit/restart), rem(maxit, restart)];
+
+endfunction
+
+
+%!shared A, b, dim
+%! dim = 100;
+%!test
+%! A = spdiags ([-ones(dim,1) 2*ones(dim,1) ones(dim,1)], [-1:1], dim, dim);
+%! b = ones(dim, 1);
+%! x = gmres (A, b, 10, 1e-10, dim, @(x) x./diag(A), [],  b);
+%! assert(x, A\b, 1e-9*norm(x,inf));
+%!
+%!test
+%! x = gmres (A, b, dim, 1e-10, 1e4, @(x) diag(diag(A))\x, [],  b);
+%! assert(x, A\b, 1e-7*norm(x,inf));
+%!
+%!test
+%! A = spdiags ([[1./(2:2:2*(dim-1)) 0]; 1./(1:2:2*dim-1); [0 1./(2:2:2*(dim-1))]]', -1:1, dim, dim);
+%! A = A'*A;
+%! b = rand (dim, 1);
+%! [x, resids] = gmres (@(x) A*x, b, dim, 1e-10, dim, @(x) x./diag(A), [],  []);
+%! assert(x, A\b, 1e-9*norm(x,inf))
+%! x = gmres (@(x) A*x, b, dim, 1e-10, 1e6, @(x) diag(diag(A))\x, [],  []);
+%! assert(x, A\b, 1e-9*norm(x,inf));
+%!test
+%! x =  gmres (@(x) A*x, b, dim, 1e-10, 1e6, @(x) x./diag(A), [],  []);
+%! assert(x, A\b, 1e-7*norm(x,inf));
--- a/scripts/sparse/gplot.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/sparse/gplot.m	Tue Sep 20 15:38:24 2011 -0400
@@ -54,3 +54,31 @@
   endif
 
 endfunction
+
+
+%!demo
+%! ## Binary Tree Representation
+%! A = [0 1 0 0 0 0 0
+%!      1 0 1 1 0 0 0
+%!      0 1 0 0 0 0 0
+%!      0 1 0 0 1 0 0
+%!      0 0 0 1 0 1 1
+%!      0 0 0 0 1 0 0
+%!      0 0 0 0 1 0 0];
+%!
+%! xy = [1, 0
+%!       1.5, 1
+%!       2, 0
+%!       2.5, 2
+%!       3.5, 1
+%!       3, 0
+%!       4, 0];
+%!
+%! clf;
+%! gplot (A, xy, "o-");
+%! set (get (gca, ("children")), "markersize", 12);
+%! title ("gplot() of Binary Tree Adjacency matrix");
+
+%% Mark graphical function as tested by demo block
+%!assert (1);
+
--- a/scripts/sparse/module.mk	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/sparse/module.mk	Tue Sep 20 15:38:24 2011 -0400
@@ -1,10 +1,12 @@
 FCN_FILE_DIRS += sparse
 
 sparse_FCN_FILES = \
+  sparse/bicg.m \
   sparse/bicgstab.m \
   sparse/cgs.m \
   sparse/colperm.m \
   sparse/etreeplot.m \
+  sparse/gmres.m \
   sparse/gplot.m \
   sparse/nonzeros.m \
   sparse/pcg.m \
--- a/scripts/sparse/nonzeros.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/sparse/nonzeros.m	Tue Sep 20 15:38:24 2011 -0400
@@ -27,12 +27,13 @@
     print_usage ();
   endif
 
-  [i, j, t] = find (s);
+  [~, ~, t] = find (s);
 
   t = t(:);
 
 endfunction
 
+
 %!assert(nonzeros([1,2;3,0]),[1;3;2])
 %!assert(nonzeros([1,2,3,0]),[1;2;3])
 %!assert(nonzeros(sparse([1,2;3,0])),[1;3;2])
--- a/scripts/sparse/spconvert.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/sparse/spconvert.m	Tue Sep 20 15:38:24 2011 -0400
@@ -43,3 +43,25 @@
   endif
 
 endfunction
+
+
+%!test
+%! i = [1; 3; 5];
+%! j = [2; 4; 6];
+%! v = [7; 8; 9];
+%! s = spconvert ([i, j, v]);
+%! assert (issparse (s));
+%! [fi, fj, fv] = find (s);
+%! assert (isequal (i, fi) && isequal (j, fj) && isequal (v, fv));
+%! s = spconvert ([i, j, v, j]);
+%! [fi, fj, fv] = find (s);
+%! assert (isequal (i, fi) && isequal (j, fj) && isequal (complex (v, j), fv));
+%! assert (size (spconvert ([1, 1, 3; 5, 15, 0])), [5, 15]);
+
+%% Test input validation
+%!error spconvert ()
+%!error spconvert (1, 2)
+%!error spconvert ({[1 2 3]})
+%!error spconvert ([1 2])
+%!error spconvert ([1 2 3i])
+%!error spconvert ([1 2 3 4 5])
--- a/scripts/sparse/sprand.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/sparse/sprand.m	Tue Sep 20 15:38:24 2011 -0400
@@ -52,9 +52,9 @@
   endif
 
   if (nargin == 1)
-    [i, j, v] = find (m);
+    [i, j] = find (m);
     [nr, nc] = size (m);
-    S = sparse (i, j, rand (size (v)), nr, nc);
+    S = sparse (i, j, rand (size (i)), nr, nc);
     return;
   endif
 
@@ -92,3 +92,30 @@
 
 endfunction
 
+## FIXME: Test for density can't happen until code of sprand is improved
+%!test
+%! s = sprand (4, 10, 0.1);
+%! assert (size (s), [4, 10]);
+##%! assert (nnz (s) / numel (s), 0.1, .01);
+
+%% Test 1-input calling form
+%!test
+%! s = sprand (sparse ([1 2 3], [3 2 3], [2 2 2]));
+%! [i, j, v] = find (s);
+%! assert (sort (i), [1 2 3]');
+%! assert (sort (j), [2 3 3]');
+%! assert (all (v > 0 & v < 1));
+
+%% Test input validation
+%!error sprand ()
+%!error sprand (1, 2)
+%!error sprand (1, 2, 3, 4)
+%!error sprand (ones(3), 3, 0.5)
+%!error sprand (3.5, 3, 0.5)
+%!error sprand (0, 3, 0.5)
+%!error sprand (3, ones(3), 0.5)
+%!error sprand (3, 3.5, 0.5)
+%!error sprand (3, 0, 0.5)
+%!error sprand (3, 3, -1)
+%!error sprand (3, 3, 2)
+
--- a/scripts/sparse/sprandn.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/sparse/sprandn.m	Tue Sep 20 15:38:24 2011 -0400
@@ -38,30 +38,75 @@
 ## Author: Paul Kienzle <pkienzle@users.sf.net>
 
 function S = sprandn (m, n, d)
-  if (nargin == 1)
-    [i, j, v] = find (m);
-    [nr, nc] = size (m);
-    S = sparse (i, j, randn (size (v)), nr, nc);
-  elseif (nargin == 3)
-    mn = m*n;
-    k = round (d*mn);
-    idx = unique (fix (rand (min (k*1.01, k+10), 1) * mn)) + 1;
-    ## idx contains random numbers in [1,mn]
-    ## generate 1% or 10 more random values than necessary in order to
-    ## reduce the probability that there are less than k distinct
-    ## values; maybe a better strategy could be used but I don't think
-    ## it's worth the price.
 
-    ## actual number of entries in S
-    k = min (length (idx), k);
-    j = floor ((idx(1:k)-1)/m);
-    i = idx(1:k) - j*m;
-    if (isempty (i))
-      S = sparse (m, n);
-    else
-      S = sparse (i, j+1, randn (k, 1), m, n);
-    endif
-  else
+  if (nargin != 1 && nargin != 3)
     print_usage ();
   endif
+
+  if (nargin == 1)
+    [i, j] = find (m);
+    [nr, nc] = size (m);
+    S = sparse (i, j, randn (size (i)), nr, nc);
+    return;
+  endif
+
+  if (!(isscalar (m) && m == fix (m) && m > 0))
+    error ("sprand: M must be an integer greater than 0");
+  endif
+
+  if (!(isscalar (n) && n == fix (n) && n > 0))
+    error ("sprand: N must be an integer greater than 0");
+  endif
+
+  if (d < 0 || d > 1)
+    error ("sprand: density D must be between 0 and 1");
+  endif
+
+  mn = m*n;
+  k = round (d*mn);
+  idx = unique (fix (rand (min (k*1.01, k+10), 1) * mn)) + 1;
+  ## idx contains random numbers in [1,mn]
+  ## generate 1% or 10 more random values than necessary in order to
+  ## reduce the probability that there are less than k distinct
+  ## values; maybe a better strategy could be used but I don't think
+  ## it's worth the price.
+
+  ## actual number of entries in S
+  k = min (length (idx), k);
+  j = floor ((idx(1:k)-1)/m);
+  i = idx(1:k) - j*m;
+  if (isempty (i))
+    S = sparse (m, n);
+  else
+    S = sparse (i, j+1, randn (k, 1), m, n);
+  endif
+
 endfunction
+
+
+## FIXME: Test for density can't happen until code of sprandn is improved
+%!test
+%! s = sprandn (4, 10, 0.1);
+%! assert (size (s), [4, 10]);
+##%! assert (nnz (s) / numel (s), 0.1, .01);
+
+%% Test 1-input calling form
+%!test
+%! s = sprandn (sparse ([1 2 3], [3 2 3], [2 2 2]));
+%! [i, j] = find (s);
+%! assert (sort (i), [1 2 3]');
+%! assert (sort (j), [2 3 3]');
+
+%% Test input validation
+%!error sprandn ()
+%!error sprandn (1, 2)
+%!error sprandn (1, 2, 3, 4)
+%!error sprandn (ones(3), 3, 0.5)
+%!error sprandn (3.5, 3, 0.5)
+%!error sprandn (0, 3, 0.5)
+%!error sprandn (3, ones(3), 0.5)
+%!error sprandn (3, 3.5, 0.5)
+%!error sprandn (3, 0, 0.5)
+%!error sprandn (3, 3, -1)
+%!error sprandn (3, 3, 2)
+
--- a/scripts/sparse/sprandsym.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/sparse/sprandsym.m	Tue Sep 20 15:38:24 2011 -0400
@@ -34,44 +34,83 @@
 ## @end deftypefn
 
 function S = sprandsym (n, d)
-  if (nargin == 1)
-    [i, j, v] = find (tril (n));
-    [nr, nc] = size (n);
-    S = sparse (i, j, randn (size (v)), nr, nc);
-    S = S + tril (S, -1)';
-  elseif (nargin == 2)
-    m1 = floor (n/2);
-    n1 = m1 + rem (n, 2);
-    mn1 = m1*n1;
-    k1 = round (d*mn1);
-    idx1 = unique (fix (rand (min (k1*1.01, k1+10), 1) * mn1)) + 1;
-    ## idx contains random numbers in [1,mn] generate 1% or 10 more
-    ## random values than necessary in order to reduce the probability
-    ## that there are less than k distinct values; maybe a better
-    ## strategy could be used but I don't think it's worth the price.
 
-    ## Actual number of entries in S.
-    k1 = min (length (idx1), k1);
-    j1 = floor ((idx1(1:k1)-1)/m1);
-    i1 = idx1(1:k1) - j1*m1;
-
-    n2 = ceil (n/2);
-    nn2 = n2*n2;
-    k2 = round (d*nn2);
-    idx2 = unique (fix (rand (min (k2*1.01, k1+10), 1) * nn2)) + 1;
-    k2 = min (length (idx2), k2);
-    j2 = floor ((idx2(1:k2)-1)/n2);
-    i2 = idx2(1:k2) - j2*n2;
-
-    if (isempty (i1) && isempty (i2))
-      S = sparse (n, n);
-    else
-      S1 = sparse (i1, j1+1, randn (k1, 1), m1, n1);
-      S = [tril(S1), sparse(m1,m1); ...
-           sparse(i2,j2+1,randn(k2,1),n2,n2), triu(S1,1)'];
-      S = S + tril (S, -1)';
-    endif
-  else
+  if (nargin != 1 && nargin != 2)
     print_usage ();
   endif
+
+  if (nargin == 1)
+    [i, j] = find (tril (n));
+    [nr, nc] = size (n);
+    S = sparse (i, j, randn (size (i)), nr, nc);
+    S = S + tril (S, -1)';
+    return;
+  endif
+
+  if (!(isscalar (n) && n == fix (n) && n > 0))
+    error ("sprand: N must be an integer greater than 0");
+  endif
+
+  if (d < 0 || d > 1)
+    error ("sprand: density D must be between 0 and 1");
+  endif
+
+  m1 = floor (n/2);
+  n1 = m1 + rem (n, 2);
+  mn1 = m1*n1;
+  k1 = round (d*mn1);
+  idx1 = unique (fix (rand (min (k1*1.01, k1+10), 1) * mn1)) + 1;
+  ## idx contains random numbers in [1,mn] generate 1% or 10 more
+  ## random values than necessary in order to reduce the probability
+  ## that there are less than k distinct values; maybe a better
+  ## strategy could be used but I don't think it's worth the price.
+
+  ## Actual number of entries in S.
+  k1 = min (length (idx1), k1);
+  j1 = floor ((idx1(1:k1)-1)/m1);
+  i1 = idx1(1:k1) - j1*m1;
+
+  n2 = ceil (n/2);
+  nn2 = n2*n2;
+  k2 = round (d*nn2);
+  idx2 = unique (fix (rand (min (k2*1.01, k1+10), 1) * nn2)) + 1;
+  k2 = min (length (idx2), k2);
+  j2 = floor ((idx2(1:k2)-1)/n2);
+  i2 = idx2(1:k2) - j2*n2;
+
+  if (isempty (i1) && isempty (i2))
+    S = sparse (n, n);
+  else
+    S1 = sparse (i1, j1+1, randn (k1, 1), m1, n1);
+    S = [tril(S1), sparse(m1,m1); ...
+         sparse(i2,j2+1,randn(k2,1),n2,n2), triu(S1,1)'];
+    S = S + tril (S, -1)';
+  endif
+
 endfunction
+
+
+## FIXME: Test for density can't happen until code of sprandsym is improved
+%!test
+%! s = sprandsym (10, 0.1);
+%! assert (issparse (s));
+%! assert (issymmetric (s));
+%! assert (size (s), [10, 10]);
+##%! assert (nnz (s) / numel (s), 0.1, .01);
+
+%% Test 1-input calling form
+%!test
+%! s = sprandsym (sparse ([1 2 3], [3 2 3], [2 2 2]));
+%! [i, j] = find (s);
+%! assert (sort (i), [2 3]');
+%! assert (sort (j), [2 3]');
+
+%% Test input validation
+%!error sprandsym ()
+%!error sprandsym (1, 2, 3)
+%!error sprandsym (ones(3), 0.5)
+%!error sprandsym (3.5, 0.5)
+%!error sprandsym (0, 0.5)
+%!error sprandsym (3, -1)
+%!error sprandsym (3, 2)
+
--- a/scripts/sparse/spy.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/sparse/spy.m	Tue Sep 20 15:38:24 2011 -0400
@@ -61,3 +61,11 @@
   axis ([0, n+1, 0, m+1], "ij");
 
 endfunction
+
+
+%!demo
+%! clf;
+%! spy (sprand (10,10, 0.2));
+
+%% Mark graphical function as tested by demo block
+%!assert (1);
--- a/scripts/sparse/svds.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/sparse/svds.m	Tue Sep 20 15:38:24 2011 -0400
@@ -150,6 +150,8 @@
     ## Scale everything by the 1-norm to make things more stable.
     b = A / max_a;
     b_opts = opts;
+    ## Call to eigs is always a symmetric matrix by construction
+    b_opts.issym = true;
     b_opts.tol = opts.tol / max_a;
     b_sigma = sigma;
     if (!ischar (b_sigma))
--- a/scripts/sparse/treelayout.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/sparse/treelayout.m	Tue Sep 20 15:38:24 2011 -0400
@@ -202,10 +202,26 @@
   endif
 endfunction
 
-%!demo
+%!test
 %! % Compute a simple tree layout
-%! [x,y,h,s]=treelayout([0 1 2 2])
+%! [x, y, h, s] = treelayout ([0, 1, 2, 2]);
+%! assert (x, [1.5, 1.5, 2, 1]);
+%! assert (y, [3, 2, 1, 1]);
+%! assert (h, 2);
+%! assert (s, 2);
 
-%!demo
+%!test
 %! % Compute a simple tree layout with defined postorder permutation
-%! [x,y,h,s]=treelayout([0 1 2 2],[1 2 3 4])
+%! [x, y, h, s] = treelayout ([0, 1, 2, 2], [1, 2, 4, 3]);
+%! assert (x, [1.5, 1.5, 1, 2]);
+%! assert (y, [3, 2, 1, 1]);
+%! assert (h, 2);
+%! assert (s, 2);
+
+%!test
+%! % Compute a simple tree layout with defined postorder permutation
+%! [x, y, h, s] = treelayout ([0, 1, 2, 2], [4, 2, 3, 1]);
+%! assert (x, [0, 0, 0, 1]);
+%! assert (y, [0, 0, 0, 3]);
+%! assert (h, 0);
+%! assert (s, 1);
--- a/scripts/specfun/bessel.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/specfun/bessel.m	Tue Sep 20 15:38:24 2011 -0400
@@ -91,3 +91,4 @@
   error ("bessel: you must use besselj, bessely, besseli, or besselk");
 endfunction
 
+%!error bessel ()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/specfun/lcm.m	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,61 @@
+## Copyright (C) 1994-2011 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 3 of the License, 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, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {Mapping Function} {} lcm (@var{x}, @var{y})
+## @deftypefnx {Mapping Function} {} lcm (@var{x}, @var{y}, @dots{})
+## Compute the least common multiple of @var{x} and @var{y},
+## or of the list of all arguments.  All elements must be the same size or
+## scalar.
+## @seealso{factor, gcd}
+## @end deftypefn
+
+## Author: KH <Kurt.Hornik@wu-wien.ac.at>
+## Created: 16 September 1994
+## Adapted-By: jwe
+
+function l = lcm (varargin)
+
+  if (nargin > 1)
+    if (common_size (varargin{:}) != 0)
+      error ("lcm: all args must be of the same size or scalar");
+    elseif (! all (cellfun ("isnumeric", varargin)))
+      error ("lcm: all arguments must be numeric");
+    endif
+
+    l = varargin{1};
+    for i = 2:nargin
+      x = varargin{i};
+      msk = l == 0 & x == 0;
+      l .*= x ./ gcd (l, x);
+      l(msk) = 0;
+    endfor
+  else
+    print_usage ();
+  endif
+
+endfunction
+
+%!assert(lcm (3, 5, 7, 15) == 105);
+
+%!error lcm ();
+
+%!test
+%! s.a = 1;
+%! fail("lcm (s)");
+
--- a/scripts/specfun/module.mk	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/specfun/module.mk	Tue Sep 20 15:38:24 2011 -0400
@@ -7,6 +7,7 @@
   specfun/factor.m \
   specfun/factorial.m \
   specfun/isprime.m \
+  specfun/lcm.m \
   specfun/legendre.m \
   specfun/nchoosek.m \
   specfun/nthroot.m \
--- a/scripts/specfun/nthroot.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/specfun/nthroot.m	Tue Sep 20 15:38:24 2011 -0400
@@ -35,8 +35,9 @@
 ## @end group
 ## @end example
 ##
-## @var{n} must be a scalar.  If @var{n} is not an even integer and @var{X} has
-## negative entries, an error is produced.
+## @var{x} must have all real entries.  @var{n} must be a scalar.
+## If @var{n} is an even integer and @var{X} has negative entries, an
+## error is produced.
 ## @seealso{realsqrt, sqrt, cbrt}
 ## @end deftypefn
 
@@ -46,7 +47,11 @@
     print_usage ();
   endif
 
-  if (! isscalar (n))
+  if (any (iscomplex (x(:))))
+    error ("nthroot: X must not contain complex values");
+  endif
+
+  if (! isscalar (n) || n == 0)
     error ("nthroot: N must be a nonzero scalar");
   endif
 
@@ -58,7 +63,7 @@
     y = 1 ./ nthroot (x, -n);
   else
     ## Compute using power.
-    if (n == round (n) && mod (n, 2) == 1)
+    if (n == fix (n) && mod (n, 2) == 1)
       y = abs (x) .^ (1/n) .* sign (x);
     elseif (any (x(:) < 0))
       error ("nthroot: if X contains negative values, N must be an odd integer");
@@ -66,7 +71,7 @@
       y = x .^ (1/n);
     endif
 
-    if (finite (n) && n > 0 && n == round (n))
+    if (finite (n) && n > 0 && n == fix (n))
       ## Correction.
       y = ((n-1)*y + x ./ (y.^(n-1))) / n;
       y = merge (finite (y), y, x);
@@ -76,8 +81,18 @@
 
 endfunction
 
-%!assert(nthroot(-32,5), -2);
-%!assert(nthroot(81,4), 3);
-%!assert(nthroot(Inf,4), Inf);
-%!assert(nthroot(-Inf,7), -Inf);
-%!assert(nthroot(-Inf,-7), 0);
+%!assert (nthroot(-32,5), -2);
+%!assert (nthroot(81,4), 3);
+%!assert (nthroot(Inf,4), Inf);
+%!assert (nthroot(-Inf,7), -Inf);
+%!assert (nthroot(-Inf,-7), 0);
+
+%% Test input validation
+%!error (nthroot ())
+%!error (nthroot (1))
+%!error (nthroot (1,2,3))
+%!error (nthroot (1+j,2))
+%!error (nthroot (1,[1 2]))
+%!error (nthroot (1,0))
+%!error (nthroot (-1,2))
+
--- a/scripts/specfun/perms.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/specfun/perms.m	Tue Sep 20 15:38:24 2011 -0400
@@ -63,3 +63,11 @@
     endfor
   endif
 endfunction
+
+%!error perms ();
+%!error perms (1, 2);
+
+%!assert (perms ([1,2,3]), [1,2,3;2,1,3;1,3,2;2,3,1;3,1,2;3,2,1]);
+%!assert (perms (1:3), perms ([1,2,3]));
+
+%!assert (perms (int8([1,2,3])), int8([1,2,3;2,1,3;1,3,2;2,3,1;3,1,2;3,2,1]));
--- a/scripts/specfun/primes.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/specfun/primes.m	Tue Sep 20 15:38:24 2011 -0400
@@ -92,3 +92,11 @@
   endif
 
 endfunction
+
+%!error primes ();
+%!error primes (1, 2);
+
+%!assert (size (primes (350)), [1, 70]);
+%!assert (size (primes (350)), [1, 70]);
+
+%!assert (primes (357)(end), 353);
--- a/scripts/special-matrix/module.mk	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/special-matrix/module.mk	Tue Sep 20 15:38:24 2011 -0400
@@ -8,7 +8,6 @@
   special-matrix/magic.m \
   special-matrix/pascal.m \
   special-matrix/rosser.m \
-  special-matrix/sylvester_matrix.m \
   special-matrix/toeplitz.m \
   special-matrix/vander.m \
   special-matrix/wilkinson.m
--- a/scripts/special-matrix/sylvester_matrix.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-## Copyright (C) 1996-2011 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} {} sylvester_matrix (@var{k})
-## Return the Sylvester matrix of order
-## @tex
-## $n = 2^k$.
-## @end tex
-## @ifnottex
-## n = 2^@var{k}.
-## @end ifnottex
-##
-## @seealso{toeplitz, hankel}
-## @end deftypefn
-
-## Author: jwe
-
-function retval = sylvester_matrix (k)
-
-  if (nargin != 1)
-    print_usage ();
-  endif
-
-  if (isscalar (k))
-    if (k < 1)
-      retval = 1;
-    else
-      tmp = sylvester_matrix (k-1);
-      retval = [tmp, tmp; tmp, -tmp];
-    endif
-  else
-    error ("sylvester_matrix: expecting scalar argument");
-  endif
-
-endfunction
-
-%!assert((sylvester_matrix (1) == [1, 1; 1, -1]
-%! && (sylvester_matrix (2)
-%! == [1, 1, 1, 1; 1, -1, 1, -1; 1, 1, -1, -1; 1, -1, -1, 1])));
-
-%!error sylvester_matrix ([1, 2; 3, 4]);
-
-%!error sylvester_matrix ();
-
-%!error sylvester_matrix (1, 2);
-
--- a/scripts/startup/__finish__.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/startup/__finish__.m	Tue Sep 20 15:38:24 2011 -0400
@@ -36,3 +36,5 @@
 
 endfunction
 
+## No test needed for internal helper function.
+%!assert (1)
--- a/scripts/statistics/base/center.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/base/center.m	Tue Sep 20 15:38:24 2011 -0400
@@ -23,7 +23,7 @@
 ## If @var{x} is a vector, subtract its mean.
 ## If @var{x} is a matrix, do the above for each column.
 ## If the optional argument @var{dim} is given, operate along this dimension.
-## @seealso{studentize}
+## @seealso{zscore}
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
@@ -35,7 +35,7 @@
     print_usage ();
   endif
 
-  if (!isnumeric (x))
+  if (! (isnumeric (x) || islogical (x)))
     error ("center: X must be a numeric vector or matrix");
   endif
 
@@ -47,10 +47,7 @@
   sz = size (x);
   if (nargin != 2)
     ## Find the first non-singleton dimension.
-    dim = find (sz > 1, 1);
-    if (isempty (dim))
-      dim = 1;
-    endif
+    (dim = find (sz > 1, 1)) || (dim = 1);
   else
     if (!(isscalar (dim) && dim == fix (dim))
         || !(1 <= dim && dim <= nd))
@@ -58,25 +55,28 @@
     endif
   endif
 
-  n = size (x, dim);
+  n = sz(dim);
 
   if (n == 0)
     retval = x;
   else
-    retval = bsxfun (@minus, x, sum (x, dim) / n);
+    retval = bsxfun (@minus, x, mean (x, dim));
   endif
 
 endfunction
 
 %!assert(center ([1,2,3]), [-1,0,1])
+%!assert(center (single([1,2,3])), single([-1,0,1]))
 %!assert(center (int8 ([1,2,3])), [-1,0,1])
+%!assert(center (logical ([1, 0, 0, 1])), [0.5, -0.5, -0.5, 0.5])
 %!assert(center (ones (3,2,0,2)), zeros (3,2,0,2))
+%!assert(center (ones (3,2,0,2, 'single')), zeros (3,2,0,2, 'single'))
 %!assert(center (magic (3)), [3,-4,1;-2,0,2;-1,4,-3])
+%!assert(center ([1 2 3; 6 5 4], 2), [-1 0 1; 1 0 -1])
 
 %% Test input validation
 %!error center ()
 %!error center (1, 2, 3)
-%!error center ([true true])
 %!error center (1, ones(2,2))
 %!error center (1, 1.5)
 %!error center (1, 0)
--- a/scripts/statistics/base/cor.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-## Copyright (C) 1995-2011 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn  {Function File} {} cor (@var{x})
-## @deftypefnx {Function File} {} cor (@var{x}, @var{y})
-## Compute matrix of correlation coefficients.
-##
-## This is an alias for @code{corrcoef}.
-## @seealso{corrcoef}
-## @end deftypefn
-
-function retval = cor (x, y = x)
-
-  if (nargin < 1 || nargin > 2)
-    print_usage ();
-  endif
-
-  retval = corrcoef (x, y);
-
-endfunction
-
-%!test
-%! x = rand (10, 2);
-%! assert (cor (x), corrcoef (x), 5*eps);
-%! assert (cor (x(:,1), x(:,2)) == corrcoef (x(:,1), x(:,2)));
-
-%% Test input validation
-%!error corrcoef ();
-%!error corrcoef (1, 2, 3);
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/statistics/base/corr.m	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,112 @@
+## Copyright (C) 1996-2011 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 3 of the License, 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, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {Function File} {} corr (@var{x})
+## @deftypefnx {Function File} {} corr (@var{x}, @var{y})
+## Compute matrix of correlation coefficients.
+##
+## If each row of @var{x} and @var{y} is an observation and each column is
+## a variable, then the @w{(@var{i}, @var{j})-th} entry of
+## @code{corr (@var{x}, @var{y})} is the correlation between the
+## @var{i}-th variable in @var{x} and the @var{j}-th variable in @var{y}.
+## @tex
+## $$
+## {\rm corr}(x,y) = {{\rm cov}(x,y) \over {\rm std}(x) {\rm std}(y)}
+## $$
+## @end tex
+## @ifnottex
+##
+## @example
+## corr(x,y) = cov(x,y)/(std(x)*std(y))
+## @end example
+##
+## @end ifnottex
+## If called with one argument, compute @code{corr (@var{x}, @var{x})},
+## the correlation between the columns of @var{x}.
+## @seealso{cov}
+## @end deftypefn
+
+## Author: Kurt Hornik <hornik@wu-wien.ac.at>
+## Created: March 1993
+## Adapted-By: jwe
+
+function retval = corr (x, y = [])
+
+  if (nargin < 1 || nargin > 2)
+    print_usage ();
+  endif
+
+  ## Input validation is done by cov.m.  Don't repeat tests here
+
+  ## Special case, scalar is always 100% correlated with itself
+  if (isscalar (x))
+    if (isa (x, 'single'))
+      retval = single (1);
+    else
+      retval = 1;
+    endif
+    return;
+  endif
+
+  ## No check for division by zero error, which happens only when
+  ## there is a constant vector and should be rare.
+  if (nargin == 2)
+    c = cov (x, y);
+    s = std (x)' * std (y);
+    retval = c ./ s;
+  else
+    c = cov (x);
+    s = sqrt (diag (c));
+    retval = c ./ (s * s');
+  endif
+
+endfunction
+
+
+%!test
+%! x = rand (10);
+%! cc1 = corr (x);
+%! cc2 = corr (x, x);
+%! assert (size (cc1) == [10, 10] && size (cc2) == [10, 10]);
+%! assert (cc1, cc2, sqrt (eps));
+
+%!test
+%! x = [1:3]';
+%! y = [3:-1:1]';
+%! assert (corr (x,y), -1, 5*eps)
+%! assert (corr (x,flipud (y)), 1, 5*eps)
+%! assert (corr ([x, y]), [1 -1; -1 1], 5*eps)
+
+%!test
+%! x = single ([1:3]');
+%! y = single ([3:-1:1]');
+%! assert (corr (x,y), single (-1), 5*eps)
+%! assert (corr (x,flipud (y)), single (1), 5*eps)
+%! assert (corr ([x, y]), single ([1 -1; -1 1]), 5*eps)
+
+%!assert (corr (5), 1);
+%!assert (corr (single(5)), single(1));
+
+%% Test input validation
+%!error corr ();
+%!error corr (1, 2, 3);
+%!error corr ([1; 2], ["A", "B"]);
+%!error corr (ones (2,2,2));
+%!error corr (ones (2,2), ones (2,2,2));
+
--- a/scripts/statistics/base/corrcoef.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,98 +0,0 @@
-## Copyright (C) 1996-2011 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn  {Function File} {} corrcoef (@var{x})
-## @deftypefnx {Function File} {} corrcoef (@var{x}, @var{y})
-## Compute matrix of correlation coefficients.
-##
-## If each row of @var{x} and @var{y} is an observation and each column is
-## a variable, then the @w{(@var{i}, @var{j})-th} entry of
-## @code{corrcoef (@var{x}, @var{y})} is the correlation between the
-## @var{i}-th variable in @var{x} and the @var{j}-th variable in @var{y}.
-## @tex
-## $$
-## {\rm corrcoef}(x,y) = {{\rm cov}(x,y) \over {\rm std}(x) {\rm std}(y)}
-## $$
-## @end tex
-## @ifnottex
-##
-## @example
-## corrcoef(x,y) = cov(x,y)/(std(x)*std(y))
-## @end example
-##
-## @end ifnottex
-## If called with one argument, compute @code{corrcoef (@var{x}, @var{x})},
-## the correlation between the columns of @var{x}.
-## @seealso{cov}
-## @end deftypefn
-
-## Author: Kurt Hornik <hornik@wu-wien.ac.at>
-## Created: March 1993
-## Adapted-By: jwe
-
-function retval = corrcoef (x, y = [])
-
-  if (nargin < 1 || nargin > 2)
-    print_usage ();
-  endif
-
-  if (! (isnumeric (x) && isnumeric (y)))
-    error ("corrcoef: X and Y must be numeric matrices or vectors");
-  endif
-
-  if (ndims (x) != 2 || ndims (y) != 2)
-    error ("corrcoef: X and Y must be 2-D matrices or vectors");
-  endif
-
-  if (isscalar (x))
-    retval = 1;
-    return;
-  endif
-
-  ## No check for division by zero error, which happens only when
-  ## there is a constant vector and should be rare.
-  if (nargin == 2)
-    c = cov (x, y);
-    s = std (x)' * std (y);
-    retval = c ./ s;
-  else
-    c = cov (x);
-    s = sqrt (diag (c));
-    retval = c ./ (s * s');
-  endif
-
-endfunction
-
-%!test
-%! x = rand (10);
-%! cc1 = corrcoef (x);
-%! cc2 = corrcoef (x, x);
-%! assert((size (cc1) == [10, 10] && size (cc2) == [10, 10]
-%! && abs (cc1 - cc2) < sqrt (eps)));
-
-%!assert(corrcoef (5), 1);
-
-%% Test input validation
-%!error corrcoef ();
-%!error corrcoef (1, 2, 3);
-%!error corrcoef ([true, true]);
-%!error corrcoef ([1, 2], [true, true]);
-%!error corrcoef (ones (2,2,2));
-%!error corrcoef (ones (2,2), ones (2,2,2));
-
--- a/scripts/statistics/base/cov.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/base/cov.m	Tue Sep 20 15:38:24 2011 -0400
@@ -55,7 +55,7 @@
 ## @item 1:
 ##   normalize with @math{N}, this provides the second moment around the mean
 ## @end table
-## @seealso{corrcoef, cor}
+## @seealso{corr}
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
@@ -67,7 +67,8 @@
     print_usage ();
   endif
 
-  if (! (isnumeric (x) && isnumeric (y)))
+  if (   ! (isnumeric (x) || islogical (x))
+      || ! (isnumeric (y) || islogical (y)))
     error ("cov: X and Y must be numeric matrices or vectors");
   endif
 
@@ -75,7 +76,7 @@
     error ("cov: X and Y must be 2-D matrices or vectors");
   endif
 
-  if (nargin == 2 && isscalar(y))
+  if (nargin == 2 && isscalar (y))
     opt = y;
   endif
 
@@ -83,22 +84,27 @@
     error ("cov: normalization OPT must be 0 or 1");
   endif
 
+  ## Special case, scalar has zero covariance
   if (isscalar (x))
-    c = 0;
+    if (isa (x, 'single'))
+      c = single (0);
+    else
+      c = 0;
+    endif
     return;
   endif
 
-  if (rows (x) == 1)
-    x = x';
+  if (isrow (x))
+    x = x.';
   endif
   n = rows (x);
 
-  if (nargin == 1 || isscalar(y))
+  if (nargin == 1 || isscalar (y))
     x = center (x, 1);
     c = conj (x' * x / (n - 1 + opt));
   else
-    if (rows (y) == 1)
-      y = y';
+    if (isrow (y))
+      y = y.';
     endif
     if (rows (y) != n)
       error ("cov: X and Y must have the same number of observations");
@@ -110,17 +116,36 @@
 
 endfunction
 
+
 %!test
 %! x = rand (10);
 %! cx1 = cov (x);
 %! cx2 = cov (x, x);
-%! assert(size (cx1) == [10, 10] && size (cx2) == [10, 10] && norm(cx1-cx2) < 1e1*eps);
+%! assert(size (cx1) == [10, 10] && size (cx2) == [10, 10]);
+%! assert(cx1, cx2, 1e1*eps);
+
+%!test
+%! x = [1:3]';
+%! y = [3:-1:1]';
+%! assert (cov (x,y), -1, 5*eps)
+%! assert (cov (x,flipud (y)), 1, 5*eps)
+%! assert (cov ([x, y]), [1 -1; -1 1], 5*eps)
+
+%!test
+%! x = single ([1:3]');
+%! y = single ([3:-1:1]');
+%! assert (cov (x,y), single (-1), 5*eps)
+%! assert (cov (x,flipud (y)), single (1), 5*eps)
+%! assert (cov ([x, y]), single ([1 -1; -1 1]), 5*eps)
 
 %!test
 %! x = [1:5];
 %! c = cov (x);
-%! assert(isscalar (c));
-%! assert(c, 2.5);
+%! assert (isscalar (c));
+%! assert (c, 2.5);
+
+%!assert(cov (5), 0);
+%!assert(cov (single(5)), single(0));
 
 %!test
 %! x = [1:5];
@@ -129,13 +154,10 @@
 %! c = cov (x, 1);
 %! assert(c, 2);
 
-%!assert(cov (5), 0);
-
 %% Test input validation
 %!error cov ();
 %!error cov (1, 2, 3, 4);
-%!error cov ([true, true]);
-%!error cov ([1, 2], [true, true]);
+%!error cov ([1; 2], ["A", "B"]);
 %!error cov (ones (2,2,2));
 %!error cov (ones (2,2), ones (2,2,2));
 %!error cov (1, 3);
--- a/scripts/statistics/base/cut.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-## Copyright (C) 1996-2011 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} {} cut (@var{x}, @var{breaks})
-## Create categorical data from numerical or continuous data by
-## cutting into intervals.
-##
-## If @var{breaks} is a scalar, the data is cut into that many
-## equal-width intervals.  If @var{breaks} is a vector of break points,
-## the category has @code{length (@var{breaks}) - 1} groups.
-##
-## The returned value is a vector of the same size as @var{x} telling
-## which group each point in @var{x} belongs to.  Groups are labelled
-## from 1 to the number of groups; points outside the range of
-## @var{breaks} are labelled by @code{NaN}.
-## @seealso{histc}
-## @end deftypefn
-
-## Author: KH <Kurt.Hornik@wu-wien.ac.at>
-## Description: Cut data into intervals
-
-function group = cut (x, breaks)
-
-  if (nargin != 2)
-    print_usage ();
-  endif
-
-  if (!isvector (x))
-    error ("cut: X must be a vector");
-  endif
-  if isscalar (breaks)
-    breaks = linspace (min (x), max (x), breaks + 1);
-    breaks(1) = breaks(1) - 1;
-  elseif isvector (breaks)
-    breaks = sort (breaks);
-  else
-    error ("cut: BREAKS must be a scalar or vector");
-  endif
-
-  group = NaN (size (x));
-  m = length (breaks);
-  if any (k = find ((x >= min (breaks)) & (x < max (breaks))))
-    n = length (k);
-    group(k) = sum ((ones (m, 1) * reshape (x(k), 1, n))
-                    >= (reshape (breaks, m, 1) * ones (1, n)));
-  endif
-
-endfunction
--- a/scripts/statistics/base/gls.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/base/gls.m	Tue Sep 20 15:38:24 2011 -0400
@@ -82,10 +82,21 @@
   if (rx != ry)
     error ("gls: number of rows of X and Y must be equal");
   endif
-  if (!issquare(o) || ro != ry*cy)
+  if (!issquare (o) || ro != ry*cy)
     error ("gls: matrix O must be square matrix with rows = rows (Y) * cols (Y)");
   endif
 
+  if (isinteger (x))
+    x = double (x);
+  endif
+  if (isinteger (y))
+    y = double (y);
+  endif
+  if (isinteger (o))
+    o = double (o);
+  endif
+
+  ## Start of algorithm
   o = o^(-1/2);
   z = kron (eye (cy), x);
   z = o * z;
@@ -116,7 +127,7 @@
 %! y = 3*x + 2;
 %! x = [x, ones(5,1)];
 %! o = diag (ones (5,1));
-%! assert (gls (y,x,o), [3; 2], 50*eps)
+%! assert (gls (y,x,o), [3; 2], 50*eps);
 
 %% Test input validation
 %!error gls ()
--- a/scripts/statistics/base/histc.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/base/histc.m	Tue Sep 20 15:38:24 2011 -0400
@@ -61,7 +61,7 @@
     error ("histc: EDGES must be real-valued, not complex");
   else
     ## Make sure 'edges' is sorted
-    edges = edges (:);
+    edges = edges(:);
     if (!issorted (edges) || edges(1) > edges(end))
       warning ("histc: edge values not sorted on input");
       edges = sort (edges);
@@ -72,10 +72,7 @@
   sz = size (x);
   if (nargin < 3)
     ## Find the first non-singleton dimension.
-    dim = find (sz > 1, 1);
-    if (isempty (dim))
-      dim = 1;
-    endif
+    (dim = find (sz > 1, 1)) || (dim = 1);
   else
     if (!(isscalar (dim) && dim == fix (dim))
         || !(1 <= dim && dim <= nd))
@@ -103,25 +100,25 @@
     ## Prepare indices
     idx1 = cell (1, dim-1);
     for k = 1:length (idx1)
-      idx1 {k} = 1:sz(k);
+      idx1{k} = 1:sz(k);
     endfor
     idx2 = cell (length (sz) - dim);
     for k = 1:length (idx2)
-      idx2 {k} = 1:sz(k+dim);
+      idx2{k} = 1:sz(k+dim);
     endfor
 
     ## Compute the histograms
     for k = 1:num_edges-1
       b = (edges (k) <= x & x < edges (k+1));
-      n (idx1 {:}, k, idx2 {:}) = sum (b, dim);
+      n(idx1{:}, k, idx2{:}) = sum (b, dim);
       if (nargout > 1)
-        idx (b) = k;
+        idx(b) = k;
       endif
     endfor
     b = (x == edges (end));
-    n (idx1 {:}, num_edges, idx2 {:}) = sum (b, dim);
+    n(idx1{:}, num_edges, idx2{:}) = sum (b, dim);
     if (nargout > 1)
-      idx (b) = num_edges;
+      idx(b) = num_edges;
     endif
 
   else
@@ -160,6 +157,7 @@
 
 endfunction
 
+
 %!test
 %! x = linspace (0, 10, 1001);
 %! n = histc (x, 0:10);
--- a/scripts/statistics/base/iqr.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/base/iqr.m	Tue Sep 20 15:38:24 2011 -0400
@@ -39,7 +39,7 @@
     print_usage ();
   endif
 
-  if (!(ismatrix (x) && isnumeric (x)) || isscalar(x))
+  if (! (isnumeric (x) || islogical (x)))
     error ("iqr: X must be a numeric vector or matrix");
   endif
 
@@ -48,10 +48,7 @@
   nel = numel (x);
   if (nargin != 2)
     ## Find the first non-singleton dimension.
-    dim = find (sz > 1, 1);
-    if (isempty (dim))
-      dim = 1;
-    endif
+    (dim = find (sz > 1, 1)) || (dim = 1);
   else
     if (!(isscalar (dim) && dim == fix (dim))
         || !(1 <= dim && dim <= nd))
@@ -60,27 +57,33 @@
   endif
 
   ## This code is a bit heavy, but is needed until empirical_inv
-  ## takes other than vector arguments.
-  c = sz(dim);
+  ## can take a matrix, rather than just a vector argument.
+  n = sz(dim);
   sz(dim) = 1;
-  y = zeros (sz);
+  if (isa (x, 'single'))
+    y = zeros (sz, 'single');
+  else
+    y = zeros (sz);
+  endif
   stride = prod (sz(1:dim-1));
-  for i = 1 : nel / c;
+  for i = 1 : nel / n;
     offset = i;
     offset2 = 0;
     while (offset > stride)
       offset -= stride;
       offset2++;
     endwhile
-    offset += offset2 * stride * c;
-    rng = [0 : c-1] * stride + offset;
+    offset += offset2 * stride * n;
+    rng = [0 : n-1] * stride + offset;
 
-    y (i) = empirical_inv (3/4, x(rng)) - empirical_inv (1/4, x(rng));
+    y(i) = diff (empirical_inv ([1/4, 3/4], x(rng)));
   endfor
 
 endfunction
 
+
 %!assert (iqr (1:101), 50);
+%!assert (iqr (single(1:101)), single(50));
 
 %%!test
 %%! x = [1:100];
@@ -90,5 +93,6 @@
 %!error iqr ();
 %!error iqr (1, 2, 3);
 %!error iqr (1);
-%!error iqr ([true, true]);
+%!error iqr (['A'; 'B']);
 %!error iqr (1:10, 3);
+
--- a/scripts/statistics/base/kendall.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/base/kendall.m	Tue Sep 20 15:38:24 2011 -0400
@@ -74,7 +74,8 @@
     print_usage ();
   endif
 
-  if (! (isnumeric (x) && isnumeric (y)))
+  if (   ! (isnumeric (x) || islogical (x))
+      || ! (isnumeric (y) || islogical (y)))
     error ("kendall: X and Y must be numeric matrices or vectors");
   endif
 
@@ -82,14 +83,14 @@
     error ("kendall: X and Y must be 2-D matrices or vectors");
   endif
 
-  if (rows (x) == 1)
-    x = x';
+  if (isrow (x))
+    x = x.';
   endif
   [n, c] = size (x);
 
   if (nargin == 2)
-    if (rows (y) == 1)
-      y = y';
+    if (isrow (y))
+      y = y.';
     endif
     if (rows (y) != n)
       error ("kendall: X and Y must have the same number of observations");
@@ -98,22 +99,36 @@
     endif
   endif
 
+  if (isa (x, 'single') || isa (y, 'single'))
+    cls = 'single';
+  else
+    cls = 'double';
+  endif
   r   = ranks (x);
-  m   = sign (kron (r, ones (n, 1)) - kron (ones (n, 1), r));
-  tau = corrcoef (m);
+  m   = sign (kron (r, ones (n, 1, cls)) - kron (ones (n, 1, cls), r));
+  tau = corr (m);
 
   if (nargin == 2)
-    tau = tau (1 : c, (c + 1) : columns (x));
+    tau = tau(1 : c, (c + 1) : columns (x));
   endif
 
 endfunction
 
 
+%!test
+%! x = [1:2:10];
+%! y = [100:10:149];
+%! assert (kendall (x,y), 1, 5*eps);
+%! assert (kendall (x,fliplr (y)), -1, 5*eps);
+
+%!assert (kendall (logical(1)), 1);
+%!assert (kendall (single(1)), single(1));
+
 %% Test input validation
 %!error kendall ();
 %!error kendall (1, 2, 3);
-%!error kendall ([true, true]);
-%!error kendall (ones(1,2), [true, true]);
+%!error kendall (['A'; 'B']);
+%!error kendall (ones(2,1), ['A'; 'B']);
 %!error kendall (ones (2,2,2));
 %!error kendall (ones (2,2), ones (2,2,2));
 %!error kendall (ones (2,2), ones (3,2));
--- a/scripts/statistics/base/kurtosis.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/base/kurtosis.m	Tue Sep 20 15:38:24 2011 -0400
@@ -54,7 +54,7 @@
     print_usage ();
   endif
 
-  if (!isnumeric (x))
+  if (! (isnumeric (x) || islogical (x)))
     error ("kurtosis: X must be a numeric vector or matrix");
   endif
 
@@ -62,10 +62,7 @@
   sz = size (x);
   if (nargin != 2)
     ## Find the first non-singleton dimension.
-    dim = find (sz > 1, 1);
-    if (isempty (dim))
-      dim = 1;
-    endif
+    (dim = find (sz > 1, 1)) || (dim = 1);
   else
     if (!(isscalar (dim) && dim == fix (dim))
         || !(1 <= dim && dim <= nd))
@@ -73,16 +70,14 @@
     endif
   endif
 
-  c = sz(dim);
+  n = sz(dim);
   sz(dim) = 1;
-  idx = ones (1, nd);
-  idx(dim) = c;
-  x = x - repmat (mean (x, dim), idx);
+  x = center (x, dim);  # center also promotes integer to double for next line
   retval = zeros (sz, class (x));
   s = std (x, [], dim);
+  idx = find (s > 0);
   x = sum (x.^4, dim);
-  ind = find (s > 0);
-  retval(ind) = x(ind) ./ (c * s(ind) .^ 4) - 3;
+  retval(idx) = x(idx) ./ (n * s(idx) .^ 4) - 3;
 
 endfunction
 
@@ -90,12 +85,14 @@
 %!test
 %! x = [-1; 0; 0; 0; 1];
 %! y = [x, 2*x];
-%! assert(all (abs (kurtosis (y) - [-1.4, -1.4]) < sqrt (eps)));
+%! assert (kurtosis (y), [-1.4, -1.4], sqrt (eps));
+
+%!assert (kurtosis (single(1)), single(0));
 
 %% Test input validation
 %!error kurtosis ()
 %!error kurtosis (1, 2, 3)
-%!error kurtosis (true(1,2))
+%!error kurtosis (['A'; 'B'])
 %!error kurtosis (1, ones(2,2))
 %!error kurtosis (1, 1.5)
 %!error kurtosis (1, 0)
--- a/scripts/statistics/base/logit.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/base/logit.m	Tue Sep 20 15:38:24 2011 -0400
@@ -47,6 +47,7 @@
 
 endfunction
 
+
 %!test
 %! p = [0.01:0.01:0.99];
 %! assert(logit (p), log (p ./ (1-p)), 25*eps)
--- a/scripts/statistics/base/mahalanobis.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/base/mahalanobis.m	Tue Sep 20 15:38:24 2011 -0400
@@ -34,7 +34,8 @@
     print_usage ();
   endif
 
-  if (! (isnumeric (x) && isnumeric (y)))
+  if (   ! (isnumeric (x) || islogical (x))
+      || ! (isnumeric (y) || islogical (y)))
     error ("mahalanobis: X and Y must be numeric matrices or vectors");
   endif
 
@@ -49,11 +50,16 @@
     error ("mahalanobis: X and Y must have the same number of columns");
   endif
 
+  if (isinteger (x))
+    x = double (x);
+  endif
+
   xm = mean (x);
   ym = mean (y);
 
-  x = x - ones (xr, 1) * xm;
-  y = y - ones (yr, 1) * ym;
+  ## Center data by subtracting means
+  x = bsxfun (@minus, x, xm);
+  y = bsxfun (@minus, y, ym);
 
   w = (x' * x + y' * y) / (xr + yr - 2);
 
@@ -63,11 +69,12 @@
 
 endfunction
 
+
 %% Test input validation
 %!error mahalanobis ();
 %!error mahalanobis (1, 2, 3);
-%!error mahalanobis ([true], [true]);
-%!error mahalanobis ([1, 2], [true, true]);
+%!error mahalanobis ('A', 'B');
+%!error mahalanobis ([1, 2], ['A', 'B']);
 %!error mahalanobis (ones (2,2,2));
 %!error mahalanobis (ones (2,2), ones (2,2,2));
 %!error mahalanobis (ones (2,2), ones (2,3));
--- a/scripts/statistics/base/mean.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/base/mean.m	Tue Sep 20 15:38:24 2011 -0400
@@ -69,15 +69,15 @@
     error ("mean: X must be a numeric vector or matrix");
   endif
 
-  need_dim = 0;
+  need_dim = false;
 
   if (nargin == 1)
     opt = "a";
-    need_dim = 1;
+    need_dim = true;
   elseif (nargin == 2)
     if (ischar (opt1))
       opt = opt1;
-      need_dim = 1;
+      need_dim = true;
     else
       dim = opt1;
       opt = "a";
@@ -100,22 +100,15 @@
   sz = size (x);
   if (need_dim)
     ## Find the first non-singleton dimension.
-    dim = find (sz > 1, 1);
-    if (isempty (dim))
-      dim = 1;
+    (dim = find (sz > 1, 1)) || (dim = 1);
+  else
+    if (!(isscalar (dim) && dim == fix (dim))
+      || !(1 <= dim && dim <= nd))
+      error ("mean: DIM must be an integer and a valid dimension");
     endif
   endif
 
-  if (!(isscalar (dim) && dim == fix (dim))
-      || !(1 <= dim && dim <= nd))
-    error ("mean: DIM must be an integer and a valid dimension");
-  endif
-
-  if (dim > nd)
-    n = 1;
-  else
-    n = sz(dim);
-  endif
+  n = sz(dim);
 
   if (strcmp (opt, "a"))
     y = sum (x, dim) / n;
@@ -129,6 +122,7 @@
 
 endfunction
 
+
 %!test
 %! x = -10:10;
 %! y = x';
@@ -137,9 +131,12 @@
 %! assert(mean (y) == 0);
 %! assert(mean (z) == [0, 10]);
 
+%!assert(mean (magic(3), 1), [5, 5, 5]);
+%!assert(mean (magic(3), 2), [5; 5; 5]);
 %!assert(mean ([2 8], 'g'), 4);
 %!assert(mean ([4 4 2], 'h'), 3);
 %!assert(mean (logical ([1 0 1 1])), 0.75);
+%!assert(mean (single ([1 0 1 1])), single (0.75));
 
 %% Test input validation
 %!error mean ();
--- a/scripts/statistics/base/meansq.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/base/meansq.m	Tue Sep 20 15:38:24 2011 -0400
@@ -52,7 +52,7 @@
     print_usage ();
   endif
 
-  if (!isnumeric (x))
+  if (! (isnumeric (x) || islogical (x)))
     error ("mean: X must be a numeric vector or matrix");
   endif
 
@@ -60,29 +60,28 @@
   sz = size (x);
   if (nargin < 2)
     ## Find the first non-singleton dimension.
-    dim = find (sz > 1, 1);
-    if (isempty (dim))
-      dim = 1;
+    (dim = find (sz > 1, 1)) || (dim = 1);
+  else
+    if (!(isscalar (dim) && dim == fix (dim))
+        || !(1 <= dim && dim <= nd))
+      error ("mean: DIM must be an integer and a valid dimension");
     endif
   endif
 
-  if (!(isscalar (dim) && dim == fix (dim))
-      || !(1 <= dim && dim <= nd))
-    error ("mean: DIM must be an integer and a valid dimension");
-  endif
-
-  y = sumsq (x, dim) / size (x, dim);
+  y = sumsq (x, dim) / sz(dim);
 
 endfunction
 
 
-%!assert(meansq (1:5), 11)
-%!assert(meansq (magic (4)), [94.5, 92.5, 92.5, 94.5])
+%!assert(meansq (1:5), 11);
+%!assert(meansq (single(1:5)), single(11));
+%!assert(meansq (magic (4)), [94.5, 92.5, 92.5, 94.5]);
+%!assert(meansq (magic (4), 2), [109.5; 77.5; 77.5; 109.5]);
 
 %% Test input validation
 %!error meansq ()
 %!error meansq (1, 2, 3)
-%!error kurtosis ([true true])
+%!error meansq (['A'; 'B']);
 %!error meansq (1, ones(2,2))
 %!error meansq (1, 1.5)
 %!error meansq (1, 0)
--- a/scripts/statistics/base/median.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/base/median.m	Tue Sep 20 15:38:24 2011 -0400
@@ -55,18 +55,19 @@
     print_usage ();
   endif
 
-  if (!isnumeric (x))
+  if (! (isnumeric (x) || islogical (x)))
     error ("median: X must be a numeric vector or matrix");
   endif
 
+  if (isempty (x))
+    error ("median: X cannot be an empty matrix");
+  endif
+
   nd = ndims (x);
   sz = size (x);
-  if (nargin != 2)
+  if (nargin < 2)
     ## Find the first non-singleton dimension.
-    dim = find (sz > 1, 1);
-    if (isempty (dim))
-      dim = 1;
-    endif
+    (dim = find (sz > 1, 1)) || (dim = 1);
   else
     if (!(isscalar (dim) && dim == fix (dim))
         || !(1 <= dim && dim <= nd))
@@ -74,22 +75,19 @@
     endif
   endif
 
-  if (numel (x) > 0)
-    n = size (x, dim);
-    k = floor ((n+1) / 2);
-    if (mod (n, 2) == 1)
-      retval = nth_element (x, k, dim);
-    else
-      retval = mean (nth_element (x, k:k+1, dim), dim);
-    endif
-    ## Inject NaNs where needed, to be consistent with Matlab.
-    retval(any (isnan (x), dim)) = NaN;
+  n = sz(dim);
+  k = floor ((n+1) / 2);
+  if (mod (n, 2) == 1)
+    retval = nth_element (x, k, dim);
   else
-    error ("median: invalid matrix argument");
+    retval = mean (nth_element (x, k:k+1, dim), dim);
   endif
+  ## Inject NaNs where needed, to be consistent with Matlab.
+  retval(any (isnan (x), dim)) = NaN;
 
 endfunction
 
+
 %!test
 %! x = [1, 2, 3, 4, 5, 6];
 %! x2 = x';
@@ -101,13 +99,14 @@
 %! assert(median ([x2, 2*x2]) == [3.5, 7]);
 %! assert(median ([y2, 3*y2]) == [4, 12]);
 
+%!assert(median (single([1,2,3])), single(2));
 %!assert(median ([1,2,NaN;4,5,6;NaN,8,9]), [NaN, 5, NaN]);
 
 %% Test input validation
 %!error median ();
 %!error median (1, 2, 3);
 %!error median ({1:5});
-%!error median (true(1,5));
+%!error median (['A'; 'B']);
 %!error median (1, ones(2,2));
 %!error median (1, 1.5);
 %!error median (1, 0);
--- a/scripts/statistics/base/mode.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/base/mode.m	Tue Sep 20 15:38:24 2011 -0400
@@ -39,18 +39,15 @@
     print_usage ();
   endif
 
-  if (!isnumeric(x))
+  if (! (isnumeric (x) || islogical (x)))
     error ("mode: X must be a numeric vector or matrix");
   endif
 
   nd = ndims (x);
   sz = size (x);
-  if (nargin != 2)
+  if (nargin < 2)
     ## Find the first non-singleton dimension.
-    dim = find (sz > 1, 1);
-    if (isempty (dim))
-      dim = 1;
-    endif
+    (dim = find (sz > 1, 1)) || (dim = 1);
   else
     if (!(isscalar (dim) && dim == round (dim))
         || !(1 <= dim && dim <= nd))
@@ -78,11 +75,11 @@
   t = cat (dim, true (sz2), diff (xs, 1, dim) != 0);
 
   if (dim != 1)
-    t2 (permute (t != 0, perm)) = diff ([find(permute (t, perm))(:); prod(sz)+1]);
+    t2(permute (t != 0, perm)) = diff ([find(permute (t, perm))(:); prod(sz)+1]);
     f = max (ipermute (t2, perm), [], dim);
     xs = permute (xs, perm);
   else
-    t2 (t) = diff ([find(t)(:); prod(sz)+1]);
+    t2(t) = diff ([find(t)(:); prod(sz)+1]);
     f = max (t2, [], dim);
   endif
 
@@ -90,14 +87,15 @@
   if (issparse (x))
     m = sparse (sz2(1), sz2(2));
   else
-    m = zeros (sz2);
+    m = zeros (sz2, class (x));
   endif
   for i = 1 : prod (sz2)
-    c{i} = xs (t2 (:, i) == f(i), i);
-    m (i) = c{i}(1);
+    c{i} = xs(t2(:, i) == f(i), i);
+    m(i) = c{i}(1);
   endfor
 endfunction
 
+
 %!test
 %! [m, f, c] = mode (toeplitz (1:5));
 %! assert (m, [1,2,2,2,1]);
@@ -114,15 +112,19 @@
 %! [m2, f2, c2] = mode (full (a));
 %! assert (m, sparse (m2));
 %! assert (f, sparse (f2));
-%! assert (c, cellfun (@(x) sparse (0), c2, 'uniformoutput', false));
+%! c_exp(1:length(a)) = { sparse (0) };
+%! assert (c ,c_exp);
+%! assert (c2,c_exp );
 
-%!assert(mode([2,3,1,2,3,4],1),[2,3,1,2,3,4])
-%!assert(mode([2,3,1,2,3,4],2),2)
-%!assert(mode([2,3,1,2,3,4]),2)
+%!assert(mode ([2,3,1,2,3,4],1),[2,3,1,2,3,4]);
+%!assert(mode ([2,3,1,2,3,4],2),2);
+%!assert(mode ([2,3,1,2,3,4]),2);
+%!assert(mode (single([2,3,1,2,3,4])), single(2));
+%!assert(mode (int8([2,3,1,2,3,4])), int8(2));
 
-%!assert(mode([2;3;1;2;3;4],1),2)
-%!assert(mode([2;3;1;2;3;4],2),[2;3;1;2;3;4])
-%!assert(mode([2;3;1;2;3;4]),2)
+%!assert(mode ([2;3;1;2;3;4],1),2);
+%!assert(mode ([2;3;1;2;3;4],2),[2;3;1;2;3;4]);
+%!assert(mode ([2;3;1;2;3;4]),2);
 
 %!shared x
 %! x(:,:,1) = toeplitz (1:3);
@@ -157,7 +159,7 @@
 %!error mode ()
 %!error mode (1, 2, 3)
 %!error mode ({1 2 3})
-%!error mode (true(1,3))
+%!error mode (['A'; 'B'])
 %!error mode (1, ones(2,2))
 %!error mode (1, 1.5)
 %!error mode (1, 0)
--- a/scripts/statistics/base/module.mk	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/base/module.mk	Tue Sep 20 15:38:24 2011 -0400
@@ -3,10 +3,8 @@
 statistics_base_FCN_FILES = \
   statistics/base/center.m \
   statistics/base/cloglog.m \
-  statistics/base/cor.m \
-  statistics/base/corrcoef.m \
+  statistics/base/corr.m \
   statistics/base/cov.m \
-  statistics/base/cut.m \
   statistics/base/gls.m \
   statistics/base/histc.m \
   statistics/base/iqr.m \
@@ -33,9 +31,9 @@
   statistics/base/spearman.m \
   statistics/base/statistics.m \
   statistics/base/std.m \
-  statistics/base/studentize.m \
   statistics/base/table.m \
-  statistics/base/var.m
+  statistics/base/var.m \
+  statistics/base/zscore.m
 
 FCN_FILES += $(statistics_base_FCN_FILES)
 
--- a/scripts/statistics/base/moment.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/base/moment.m	Tue Sep 20 15:38:24 2011 -0400
@@ -110,27 +110,27 @@
 
 function m = moment (x, p, opt1, opt2)
 
-  if ((nargin < 2) || (nargin > 4))
+  if (nargin < 2 || nargin > 4)
     print_usage ();
   endif
 
-  if (!isnumeric(x) || isempty(x) )
+  if (!(isnumeric (x) || islogical (x)) || isempty (x))
     error ("moment: X must be a non-empty numeric matrix or vector");
   endif
 
-  if (!(isnumeric(p) && isscalar(p)))
+  if (! (isnumeric (p) && isscalar (p)))
     error ("moment: P must be a numeric scalar");
   endif
 
-  need_dim = 0;
+  need_dim = false;
 
   if (nargin == 2)
     type = "";
-    need_dim = 1;
+    need_dim = true;
   elseif (nargin == 3)
     if (ischar (opt1))
       type = opt1;
-      need_dim = 1;
+      need_dim = true;
     else
       dim = opt1;
       type = "";
@@ -151,10 +151,7 @@
   sz = size (x);
   if (need_dim)
     ## Find the first non-singleton dimension.
-    dim = find (sz > 1, 1);
-    if (isempty (dim))
-      dim = 1;
-    endif
+    (dim = find (sz > 1, 1)) || (dim = 1);
   else
     if (!(isscalar (dim) && dim == fix (dim)) ||
         !(1 <= dim && dim <= nd))
@@ -164,10 +161,8 @@
 
   n = sz(dim);
 
-  if any (type == "c")
-    rng = ones (1, length (sz));
-    rng(dim) = sz(dim);
-    x = x - repmat (sum (x, dim), rng) / n;
+  if (any (type == "c"))
+    x = center (x, dim);
   endif
   if any (type == "a")
     x = abs (x);
@@ -178,11 +173,21 @@
 endfunction
 
 
+%!test
+%! x = rand (10);
+%! assert (moment (x,1), mean (x), 1e1*eps);
+%! assert (moment (x,2), meansq (x), 1e1*eps);
+%! assert (moment (x,1,2), mean (x,2), 1e1*eps);
+%! assert (moment (x,1,'c'), mean (center (x)), 1e1*eps);
+%! assert (moment (x,1,'a'), mean (abs (x)), 1e1*eps);
+
+%!assert (moment (single([1 2 3]),1), single(2));
+
 %% Test input validation
 %!error moment ()
 %!error moment (1)
 %!error moment (1, 2, 3, 4, 5)
-%!error moment ([true true], 2)
+%!error moment (['A'; 'B'], 2)
 %!error moment (ones(2,0,3), 2)
 %!error moment (1, true)
 %!error moment (1, ones(2,2))
--- a/scripts/statistics/base/ols.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/base/ols.m	Tue Sep 20 15:38:24 2011 -0400
@@ -100,6 +100,14 @@
     error ("ols: number of rows of X and Y must be equal");
   endif
 
+  if (isinteger (x))
+    x = double (x);
+  endif
+  if (isinteger (y))
+    y = double (y);
+  endif
+
+  ## Start of algorithm
   z = x' * x;
   rnk = rank (z);
 
@@ -118,6 +126,7 @@
 
 endfunction
 
+
 %!test
 %! x = [1:5]';
 %! y = 3*x + 2;
--- a/scripts/statistics/base/ppplot.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/base/ppplot.m	Tue Sep 20 15:38:24 2011 -0400
@@ -77,6 +77,7 @@
 
 endfunction
 
+
 %% Test input validation
 %!error ppplot ();
 %!error ppplot (ones(2,2));
--- a/scripts/statistics/base/prctile.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/base/prctile.m	Tue Sep 20 15:38:24 2011 -0400
@@ -40,52 +40,48 @@
 ## Author: Ben Abbott <bpabbott@mac.com>
 ## Description: Matlab style prctile function.
 
-function q = prctile (x, p, dim)
+function q = prctile (x, p = [], dim)
 
   if (nargin < 1 || nargin > 3)
     print_usage ();
   endif
 
-  if (!isnumeric(x))
+  if (! (isnumeric (x) || islogical (x)))
     error ("prctile: X must be a numeric vector or matrix");
   endif
-  if (!isnumeric(p))
-    error ("prctile: P must be a numeric vector");
+
+  if (isempty (p))
+    p = [0, 25, 50, 75, 100];
   endif
 
-  if (nargin == 1)
-    p = [0, 25, 50, 75, 100];
+  if (! (isnumeric (p) && isvector (p)))
+    error ("prctile: P must be a numeric vector");
   endif
 
   nd = ndims (x);
   if (nargin == 2)
     if (nd == 2)
-      ## If a matrix or vector, use the 1st dimension.
+      ## If a matrix or vector, always use 1st dimension.
       dim = 1;
     else
       ## If an N-d array, find the first non-singleton dimension.
-      dim = find (size(v) > 1, 1);
-      if (isempty (dim))
-        dim = 1;
-      endif
+      (dim = find (sz > 1, 1)) || (dim = 1);
     endif
   else
-    if (!(isscalar (dim) && dim == fix (dim)) ||
-        !(1 <= dim && dim <= nd))
+    if (!(isscalar (dim) && dim == fix (dim))
+        || !(1 <= dim && dim <= nd))
       error ("prctile: DIM must be an integer and a valid dimension");
     endif
   endif
 
   ## Convert from percent to decimal.
-  p = p / 100;
+  p /= 100;
 
-  ## The 5th method is compatible with Matlab.
-  method = 5;
-
-  q = quantile (x, p, dim, method);
+  q = quantile (x, p, dim);
 
 endfunction
 
+
 %!test
 %! pct = 50;
 %! q = prctile (1:4, pct, 1);
@@ -171,8 +167,9 @@
 %% Test input validation
 %!error prctile ()
 %!error prctile (1, 2, 3, 4)
-%!error prctile ([true, false], 10)
+%!error prctile (['A'; 'B'], 10)
 %!error prctile (1:10, [true, false])
+%!error prctile (1:10, ones (2,2))
 %!error prctile (1, 1, 1.5)
 %!error prctile (1, 1, 0)
 %!error prctile (1, 1, 3)
--- a/scripts/statistics/base/probit.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/base/probit.m	Tue Sep 20 15:38:24 2011 -0400
@@ -27,10 +27,18 @@
 
 function y = probit (p)
 
-  if (nargin == 1)
-    y = stdnormal_inv (p);
-  else
+
+  if (nargin != 1)
     print_usage ();
   endif
 
+  y = stdnormal_inv (p);
+
 endfunction
+
+%!assert(probit([-1, 0, 0.5, 1, 2]), [NaN, -Inf, 0, Inf, NaN]);
+
+%% Test input validation
+%!error probit ()
+%!error probit (1, 2)
+
--- a/scripts/statistics/base/quantile.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/base/quantile.m	Tue Sep 20 15:38:24 2011 -0400
@@ -90,31 +90,40 @@
 ##
 ## Examples:
 ##
-## @example
+## @c Set example in small font to prevent overfull line
+## @smallexample
 ## @group
-## x = randi (1000, [10, 1]);  # Create random empirical data in range 1-1000
-## q = quantile (x, [0, 1]);   # Return minimum, maximum of empirical distribution
-## q = quantile (x, [0.25 0.5 0.75]); # Return quartiles of empirical distribution
+## x = randi (1000, [10, 1]);  # Create empirical data in range 1-1000
+## q = quantile (x, [0, 1]);   # Return minimum, maximum of distribution
+## q = quantile (x, [0.25 0.5 0.75]); # Return quartiles of distribution
 ## @end group
-## @end example
+## @end smallexample
 ## @seealso{prctile}
 ## @end deftypefn
 
 ## Author: Ben Abbott <bpabbott@mac.com>
 ## Description: Matlab style quantile function of a discrete/continuous distribution
 
-function q = quantile (x, p, dim = 1, method = 5)
+function q = quantile (x, p = [], dim = 1, method = 5)
 
   if (nargin < 1 || nargin > 4)
     print_usage ();
   endif
 
-  if (nargin < 2)
+  if (! (isnumeric (x) || islogical (x)))
+    error ("quantile: X must be a numeric vector or matrix");
+  endif
+
+  if (isempty (p))
     p = [0.00 0.25, 0.50, 0.75, 1.00];
   endif
 
-  if (!(isscalar (dim) && dim == fix (dim)) ||
-      !(1 <= dim && dim <= ndims (x)))
+  if (! (isnumeric (p) && isvector (p)))
+    error ("quantile: P must be a numeric vector");
+  endif
+
+  if (!(isscalar (dim) && dim == fix (dim))
+      || !(1 <= dim && dim <= ndims (x)))
     error ("quantile: DIM must be an integer and a valid dimension");
   endif
 
@@ -143,6 +152,7 @@
 
 endfunction
 
+
 %!test
 %! p = 0.5;
 %! x = sort (rand (11));
@@ -282,9 +292,14 @@
 %% Test input validation
 %!error quantile ()
 %!error quantile (1, 2, 3, 4, 5)
+%!error quantile (['A'; 'B'], 10)
+%!error quantile (1:10, [true, false])
+%!error quantile (1:10, ones (2,2))
 %!error quantile (1, 1, 1.5)
 %!error quantile (1, 1, 0)
 %!error quantile (1, 1, 3)
+%!error quantile ((1:5)', 0.5, 1, 0)
+%!error quantile ((1:5)', 0.5, 1, 10)
 
 ## For the cumulative probability values in @var{p}, compute the
 ## quantiles, @var{q} (the inverse of the cdf), for the sample, @var{x}.
@@ -304,37 +319,35 @@
     print_usage ();
   endif
 
-  if (!isnumeric (x))
-    error ("quantile: X must be a numeric vector or matrix");
+  if (isinteger (x) || islogical (x))
+    x = double (x);
   endif
 
-  ## Save length and set shape of quantiles.
-  n = numel (p);
+  ## set shape of quantiles to column vector.
   p = p(:);
 
   ## Save length and set shape of samples.
   ## FIXME: does sort guarantee that NaN's come at the end?
   x = sort (x);
   m = sum (! isnan (x));
-  mx = size (x, 1);
-  nx = size (x, 2);
+  [xr, xc] = size (x);
 
   ## Initialize output values.
-  inv = Inf*(-(p < 0) + (p > 1));
-  inv = repmat (inv, 1, nx);
+  inv = Inf (class (x)) * (-(p < 0) + (p > 1));
+  inv = repmat (inv, 1, xc);
 
   ## Do the work.
-  if (any(k = find((p >= 0) & (p <= 1))))
+  if (any (k = find ((p >= 0) & (p <= 1))))
     n = length (k);
-    p = p (k);
-    ## Special case.
-    if (mx == 1)
+    p = p(k);
+    ## Special case of 1 row.
+    if (xr == 1)
       inv(k,:) = repmat (x, n, 1);
-      return
+      return;
     endif
 
     ## The column-distribution indices.
-    pcd = kron (ones (n, 1), mx*(0:nx-1));
+    pcd = kron (ones (n, 1), xr*(0:xc-1));
     mm = kron (ones (n, 1), m);
     switch (method)
       case {1, 2, 3}
@@ -375,7 +388,7 @@
             p = kron (p, m-1) + 1;
 
           case 8
-            ## Median unbiased .
+            ## Median unbiased.
             p = kron (p, m+1/3) + 1/3;
 
           case 9
@@ -387,7 +400,7 @@
         endswitch
 
         ## Duplicate single values.
-        imm1 = mm == 1;
+        imm1 = (mm == 1);
         x(2,imm1) = x(1,imm1);
 
         ## Interval indices.
--- a/scripts/statistics/base/range.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/base/range.m	Tue Sep 20 15:38:24 2011 -0400
@@ -37,20 +37,24 @@
 
 function y = range (x, dim)
 
+  if (nargin < 1 || nargin > 2)
+    print_usage ();
+  endif
+
   if (nargin == 1)
     y = max (x) - min (x);
-  elseif (nargin == 2)
+  else
     y = max (x, [], dim) - min (x, [], dim);
-  else
-    print_usage ();
   endif
 
 endfunction
 
-%!assert(range (1:10), 9)
-%!assert(range (magic (3)), [5, 8, 5])
-%!assert(range (magic (3), 2), [7; 4; 7])
-%!assert(range (2), 0)
+
+%!assert(range (1:10), 9);
+%!assert(range (single(1:10)), single(9));
+%!assert(range (magic (3)), [5, 8, 5]);
+%!assert(range (magic (3), 2), [7; 4; 7]);
+%!assert(range (2), 0);
 
 %% Test input validation
 %!error range ()
--- a/scripts/statistics/base/ranks.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/base/ranks.m	Tue Sep 20 15:38:24 2011 -0400
@@ -37,7 +37,7 @@
     print_usage ();
   endif
 
-  if (!isnumeric(x))
+  if (! (isnumeric (x) || islogical (x)))
     error ("ranks: X must be a numeric vector or matrix");
   endif
 
@@ -45,10 +45,7 @@
   sz = size (x);
   if (nargin != 2)
     ## Find the first non-singleton dimension.
-    dim = find (sz > 1, 1);
-    if (isempty (dim))
-      dim = 1;
-    endif
+    (dim = find (sz > 1, 1)) || (dim = 1);
   else
     if (!(isscalar (dim) && dim == fix (dim))
         || !(1 <= dim && dim <= nd))
@@ -89,18 +86,18 @@
 endfunction
 
 
-%!assert(ranks (1:2:10), 1:5)
-%!assert(ranks (10:-2:1), 5:-1:1)
-%!assert(ranks ([2, 1, 2, 4]), [2.5, 1, 2.5, 4])
-%!assert(ranks (ones(1, 5)), 3*ones(1, 5))
-%!assert(ranks (1e6*ones(1, 5)), 3*ones(1, 5))
-%!assert(ranks (rand (1, 5), 1), ones(1, 5))
+%!assert(ranks (1:2:10), 1:5);
+%!assert(ranks (10:-2:1), 5:-1:1);
+%!assert(ranks ([2, 1, 2, 4]), [2.5, 1, 2.5, 4]);
+%!assert(ranks (ones(1, 5)), 3*ones(1, 5));
+%!assert(ranks (1e6*ones(1, 5)), 3*ones(1, 5));
+%!assert(ranks (rand (1, 5), 1), ones(1, 5));
 
 %% Test input validation
 %!error ranks ()
 %!error ranks (1, 2, 3)
 %!error ranks ({1, 2})
-%!error ranks (true(2,1))
+%!error ranks (['A'; 'B'])
 %!error ranks (1, 1.5)
 %!error ranks (1, 0)
 %!error ranks (1, 3)
--- a/scripts/statistics/base/run_count.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/base/run_count.m	Tue Sep 20 15:38:24 2011 -0400
@@ -36,7 +36,7 @@
     print_usage ();
   endif
 
-  if (!isnumeric(x))
+  if (! (isnumeric (x) || islogical (x)))
     error ("run_count: X must be a numeric vector or matrix");
   endif
 
@@ -48,10 +48,7 @@
   sz = size (x);
   if (nargin != 3)
     ## Find the first non-singleton dimension.
-    dim = find (sz > 1, 1);
-    if (isempty (dim))
-      dim = 1;
-    endif
+    (dim = find (sz > 1, 1)) || (dim = 1);
   else
     if (!(isscalar (dim) && dim == fix (dim))
         || !(1 <= dim && dim <= nd))
@@ -59,6 +56,7 @@
     endif
   endif
 
+  ## Algorithm works on rows.  Permute array if necessary, ipermute back at end
   if (dim != 1)
     perm = [1 : nd];
     perm(1) = dim;
@@ -76,7 +74,7 @@
   infvec = Inf ([1, sz(2 : end)]);
 
   ind = find (diff ([infvec; x; -infvec]) < 0);
-  tmp(ind(2:end) - 1) = diff(ind);
+  tmp(ind(2:end) - 1) = diff (ind);
   tmp = tmp(idx{:});
 
   sz(1) = n;
@@ -86,7 +84,7 @@
     retval(idx{:}) = sum (tmp == k);
   endfor
   idx{1} = n;
-  retval (idx{:}) = sum (tmp >= n);
+  retval(idx{:}) = sum (tmp >= n);
 
   if (dim != 1)
     retval = ipermute (retval, perm);
@@ -105,7 +103,7 @@
 %!error run_count (1)
 %!error run_count (1, 2, 3, 4)
 %!error run_count ({1, 2}, 3)
-%!error run_count (true(3), 3)
+%!error run_count (['A'; 'A'; 'B'], 3)
 %!error run_count (1:5, ones(2,2))
 %!error run_count (1:5, 1.5)
 %!error run_count (1:5, -2)
--- a/scripts/statistics/base/runlength.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/base/runlength.m	Tue Sep 20 15:38:24 2011 -0400
@@ -30,11 +30,12 @@
 ## @end deftypefn
 
 function [count, value] = runlength (x)
+
   if (nargin != 1)
     print_usage ();
   endif
 
-  if (!isnumeric (x) || !isvector (x))
+  if (!(isnumeric (x) || islogical (x)) || !isvector (x))
     error ("runlength: X must be a numeric vector");
   endif
 
@@ -47,8 +48,10 @@
   if (nargout == 2)
     value = x(idx);
   endif
+
 endfunction
 
+
 %!assert (runlength([2 2 0 4 4 4 0 1 1 1 1]), [2 1 3 1 4]);
 %!assert (runlength([2 2 0 4 4 4 0 1 1 1 1]'), [2 1 3 1 4]);
 %!test
@@ -59,5 +62,5 @@
 %% Test input validation
 %!error runlength ()
 %!error runlength (1, 2)
-%!error runlength (true(1,2))
+%!error runlength (['A'; 'B'])
 %!error runlength (ones(2,2))
--- a/scripts/statistics/base/skewness.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/base/skewness.m	Tue Sep 20 15:38:24 2011 -0400
@@ -51,7 +51,7 @@
     print_usage ();
   endif
 
-  if (!isnumeric(x))
+  if (! (isnumeric (x) || islogical (x)))
     error ("skewness: X must be a numeric vector or matrix");
   endif
 
@@ -59,10 +59,7 @@
   sz = size (x);
   if (nargin != 2)
     ## Find the first non-singleton dimension.
-    dim = find (sz > 1, 1);
-    if (isempty (dim))
-      dim = 1;
-    endif
+    (dim = find (sz > 1, 1)) || (dim = 1);
   else
     if (!(isscalar (dim) && dim == round (dim))
         || !(1 <= dim && dim <= nd))
@@ -70,19 +67,18 @@
     endif
   endif
 
-  c = sz(dim);
-  idx = ones (1, nd);
-  idx(dim) = c;
-  x = x - repmat (mean (x, dim), idx);
+  n = sz(dim);
   sz(dim) = 1;
+  x = center (x, dim);  # center also promotes integer to double for next line
   retval = zeros (sz, class (x));
   s = std (x, [], dim);
-  ind = find (s > 0);
+  idx = find (s > 0);
   x = sum (x .^ 3, dim);
-  retval(ind) = x(ind) ./ (c * s(ind) .^ 3);
+  retval(idx) = x(idx) ./ (n * s(idx) .^ 3);
 
 endfunction
 
+
 %!assert(skewness ([-1,0,1]), 0);
 %!assert(skewness ([-2,0,1]) < 0);
 %!assert(skewness ([-1,0,2]) > 0);
@@ -92,10 +88,12 @@
 %! y = [x, 2*x];
 %! assert(all (abs (skewness (y) - [0.75, 0.75]) < sqrt (eps)));
 
+%!assert (skewness (single(1)), single(0));
+
 %% Test input validation
 %!error skewness ()
 %!error skewness (1, 2, 3)
-%!error skewness ([true true])
+%!error skewness (['A'; 'B'])
 %!error skewness (1, ones(2,2))
 %!error skewness (1, 1.5)
 %!error skewness (1, 0)
--- a/scripts/statistics/base/spearman.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/base/spearman.m	Tue Sep 20 15:38:24 2011 -0400
@@ -39,11 +39,12 @@
 
 function rho = spearman (x, y = [])
 
-  if ((nargin < 1) || (nargin > 2))
+  if (nargin < 1 || nargin > 2)
     print_usage ();
   endif
 
-  if (! (isnumeric (x) && isnumeric (y)))
+  if (   ! (isnumeric (x) || islogical (x))
+      || ! (isnumeric (y) || islogical (y)))
     error ("spearman: X and Y must be numeric matrices or vectors");
   endif
 
@@ -51,30 +52,43 @@
     error ("spearman: X and Y must be 2-D matrices or vectors");
   endif
 
-  if (rows (x) == 1)
-    x = x';
+  if (isrow (x))
+    x = x.';
   endif
-  n = rows (x);
 
   if (nargin == 1)
-    rho = corrcoef (ranks (x));
+    rho = corr (ranks (x));
   else
-    if (rows (y) == 1)
-      y = y';
+    if (isrow (y))
+      y = y.';
     endif
-    if (rows (y) != n)
+    if (rows (x) != rows (y))
       error ("spearman: X and Y must have the same number of observations");
     endif
-    rho = corrcoef (ranks (x), ranks (y));
+    rho = corr (ranks (x), ranks (y));
+  endif
+
+  ## Restore class cleared by ranks
+  if (isa (x, 'single') || isa (y, 'single'))
+    rho = single (rho);
   endif
 
 endfunction
 
+
+%!test
+%! x = 1:10;
+%! y = exp (x);
+%! assert (spearman (x,y), 1, 5*eps);
+%! assert (spearman (x,-y), -1, 5*eps);
+
+%!assert(spearman ([1 2 3], [-1 1 -2]), -0.5, 5*eps)
+
 %% Test input validation
 %!error spearman ();
 %!error spearman (1, 2, 3);
-%!error spearman ([true, true]);
-%!error spearman (ones(1,2), [true, true]);
+%!error spearman (['A'; 'B']);
+%!error spearman (ones(1,2), {1, 2});
 %!error spearman (ones (2,2,2));
 %!error spearman (ones (2,2), ones (2,2,2));
 %!error spearman (ones (2,2), ones (3,2));
--- a/scripts/statistics/base/statistics.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/base/statistics.m	Tue Sep 20 15:38:24 2011 -0400
@@ -38,7 +38,7 @@
     print_usage ();
   endif
 
-  if (!isnumeric(x))
+  if (! (isnumeric (x) || islogical (x)))
     error ("statistics: X must be a numeric vector or matrix");
   endif
 
@@ -46,10 +46,7 @@
   sz = size (x);
   if (nargin != 2)
     ## Find the first non-singleton dimension.
-    dim = find (sz > 1, 1);
-    if (isempty (dim))
-      dim = 1;
-    endif
+    (dim = find (sz > 1, 1)) || (dim = 1);
   else
     if (!(isscalar (dim) && dim == round (dim))
         || !(1 <= dim && dim <= nd))
@@ -68,16 +65,22 @@
 
 endfunction
 
+
 %!test
-%! x = rand(7,5);
+%! x = rand (7,5);
 %! s = statistics (x);
-%! m = median (x);
-%! assert (m, s(3,:), eps);
+%! assert (min (x), s(1,:), eps);
+%! assert (median (x), s(3,:), eps);
+%! assert (max (x), s(5,:), eps);
+%! assert (mean (x), s(6,:), eps);
+%! assert (std (x), s(7,:), eps);
+%! assert (skewness (x), s(8,:), eps);
+%! assert (kurtosis (x), s(9,:), eps);
 
 %% Test input validation
 %!error statistics ()
 %!error statistics (1, 2, 3)
-%!error statistics ([true true])
+%!error statistics (['A'; 'B'])
 %!error statistics (1, ones(2,2))
 %!error statistics (1, 1.5)
 %!error statistics (1, 0)
--- a/scripts/statistics/base/std.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/base/std.m	Tue Sep 20 15:38:24 2011 -0400
@@ -67,7 +67,7 @@
     print_usage ();
   endif
 
-  if (! (isnumeric (x)))
+  if (! (isnumeric (x) || islogical (x)))
     error ("std: X must be a numeric vector or matrix");
   endif
 
@@ -78,22 +78,27 @@
     error ("std: normalization OPT must be 0 or 1");
   endif
 
+  nd = ndims (x);
   sz = size (x);
   if (nargin < 3)
     ## Find the first non-singleton dimension.
-    dim = find (sz > 1, 1);
-    if (isempty (dim))
-      dim = 1;
+    (dim = find (sz > 1, 1)) || (dim = 1);
+  else
+    if (!(isscalar (dim) && dim == fix (dim))
+        || !(1 <= dim && dim <= nd))
+      error ("std: DIM must be an integer and a valid dimension");
     endif
   endif
 
-  n = size (x, dim);
-  if (n == 1)
-    retval = zeros (sz);
-  elseif (numel (x) > 0)
+  n = sz(dim);
+  if (n == 1 || isempty (x))
+    if (isa (x, 'single'))
+      retval = zeros (sz, 'single');
+    else
+      retval = zeros (sz);
+    endif
+  else
     retval = sqrt (sumsq (center (x, dim), dim) / (n - 1 + opt));
-  else
-    error ("std: X must not be empty");
   endif
 
 endfunction
@@ -102,14 +107,21 @@
 %!test
 %! x = ones (10, 2);
 %! y = [1, 3];
-%! assert(std (x) == [0, 0] && abs (std (y) - sqrt (2)) < sqrt (eps));
-%! assert (std (x, 0, 3), zeros (10, 2))
-%! assert (std (ones (3, 1, 2), 0, 2), zeros (3, 1, 2))
+%! assert(std (x) == [0, 0]);
+%! assert(std (y), sqrt (2), sqrt (eps));
+%! assert(std (x, 0, 2), zeros (10, 1));
+
+%!assert(std (ones (3, 1, 2), 0, 2), zeros (3, 1, 2));
+%!assert(std ([1 2], 0), sqrt(2)/2, 5*eps);
+%!assert(std ([1 2], 1), 0.5, 5*eps);
+%!assert(std(1), 0);
+%!assert(std(single(1)), single(0));
+%!assert(std([]), []);
+%!assert(std(ones (1,3,0,2)), ones (1,3,0,2));
 
 %% Test input validation
 %!error std ();
 %!error std (1, 2, 3, 4);
-%!error std (true(1,2))
+%!error std (['A'; 'B'])
 %!error std (1, -1);
-%!error std ([], 1);
 
--- a/scripts/statistics/base/studentize.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-## Copyright (C) 1995-2011 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn  {Function File} {} studentize (@var{x})
-## @deftypefnx {Function File} {} studentize (@var{x}, @var{dim})
-## If @var{x} is a vector, subtract its mean and divide by its standard
-## deviation.
-##
-## If @var{x} is a matrix, do the above along the first non-singleton
-## dimension.
-## If the optional argument @var{dim} is given, operate along this dimension.
-## @seealso{center}
-## @end deftypefn
-
-## Author: KH <Kurt.Hornik@wu-wien.ac.at>
-## Description: Subtract mean and divide by standard deviation
-
-function t = studentize (x, dim)
-
-  if (nargin != 1 && nargin != 2)
-    print_usage ();
-  endif
-
-  if (! isnumeric(x))
-    error ("studentize: X must be a numeric vector or matrix");
-  endif
-
-  if (isinteger (x))
-    x = double (x);
-  endif
-
-  nd = ndims (x);
-  sz = size (x);
-  if (nargin != 2)
-    ## Find the first non-singleton dimension.
-    dim = find (sz > 1, 1);
-    if (isempty (dim))
-      dim = 1;
-    endif
-  else
-    if (!(isscalar (dim) && dim == fix (dim))
-        || !(1 <= dim && dim <= nd))
-      error ("studentize: DIM must be an integer and a valid dimension");
-    endif
-  endif
-
-  c = sz(dim);
-  if (c == 0)
-    t = x;
-  else
-    idx = ones (1, nd);
-    idx(dim) = c;
-    t = x - repmat (mean (x, dim), idx);
-    t = t ./ repmat (max (cat (dim, std(t, [], dim), ! any (t, dim)), [], dim), idx);
-  endif
-
-endfunction
-
-%!assert(studentize ([1,2,3]), [-1,0,1])
-%!assert(studentize (int8 ([1,2,3])), [-1,0,1])
-#%!assert(studentize (ones (3,2,0,2)), zeros (3,2,0,2))
-%!assert(studentize ([2,0,-2;0,2,0;-2,-2,2]), [1,0,-1;0,1,0;-1,-1,1])
-
-%% Test input validation
-%!error studentize ()
-%!error studentize (1, 2, 3)
-%!error studentize ([true true])
-%!error studentize (1, ones(2,2))
-%!error studentize (1, 1.5)
-%!error studentize (1, 0)
-%!error studentize (1, 3)
-
--- a/scripts/statistics/base/table.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/base/table.m	Tue Sep 20 15:38:24 2011 -0400
@@ -60,6 +60,7 @@
 
 endfunction
 
+
 %% Test input validation
 %!error table ()
 %!error table (1, 2, 3)
--- a/scripts/statistics/base/var.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/base/var.m	Tue Sep 20 15:38:24 2011 -0400
@@ -64,7 +64,7 @@
     print_usage ();
   endif
 
-  if (!isnumeric (x))
+  if (! (isnumeric (x) || islogical (x)))
     error ("var: X must be a numeric vector or matrix");
   endif
 
@@ -75,16 +75,25 @@
     error ("var: normalization OPT must be 0 or 1");
   endif
 
+  nd = ndims (x);
+  sz = size (x);
   if (nargin < 3)
-    dim = find (size (x) > 1, 1);
-    if (isempty (dim))
-      dim = 1;
+    ## Find the first non-singleton dimension.
+    (dim = find (sz > 1, 1)) || (dim = 1);
+  else
+    if (!(isscalar (dim) && dim == fix (dim))
+        || !(1 <= dim && dim <= nd))
+      error ("var: DIM must be an integer and a valid dimension");
     endif
   endif
 
-  n = size (x, dim);
+  n = sz(dim);
   if (n == 1)
-    retval = zeros (size (x), class (x));
+    if (isa (x, 'single'))
+      retval = zeros (sz, 'single');
+    else
+      retval = zeros (sz);
+    endif
   elseif (numel (x) > 0)
     retval = sumsq (center (x, dim), dim) / (n - 1 + opt);
   else
@@ -93,15 +102,17 @@
 
 endfunction
 
-%!assert (var (13), 0)
-%!assert (var ([1,2,3]), 1)
-%!assert (var ([1,2,3], 1), 2/3, eps)
-%!assert (var ([1,2,3], [], 1), [0,0,0])
+
+%!assert(var (13), 0);
+%!assert(var (single(13)), single(0));
+%!assert(var ([1,2,3]), 1);
+%!assert(var ([1,2,3], 1), 2/3, eps);
+%!assert(var ([1,2,3], [], 1), [0,0,0]);
 
 %% Test input validation
 %!error var ()
 %!error var (1,2,3,4)
-%!error var (true(1,2))
+%!error var (['A'; 'B'])
 %!error var (1, -1);
 %!error var ([],1)
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/statistics/base/zscore.m	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,84 @@
+## Copyright (C) 1995-2011 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 3 of the License, 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, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {Function File} {} zscore (@var{x})
+## @deftypefnx {Function File} {} zscore (@var{x}, @var{dim})
+## If @var{x} is a vector, subtract its mean and divide by its standard
+## deviation.
+##
+## If @var{x} is a matrix, do the above along the first non-singleton
+## dimension.
+## If the optional argument @var{dim} is given, operate along this dimension.
+## @seealso{center}
+## @end deftypefn
+
+## Author: KH <Kurt.Hornik@wu-wien.ac.at>
+## Description: Subtract mean and divide by standard deviation
+
+function z = zscore (x, dim)
+
+  if (nargin != 1 && nargin != 2)
+    print_usage ();
+  endif
+
+  if (! (isnumeric (x) || islogical (x)))
+    error ("zscore: X must be a numeric vector or matrix");
+  endif
+
+  nd = ndims (x);
+  sz = size (x);
+  if (nargin != 2)
+    ## Find the first non-singleton dimension.
+    (dim = find (sz > 1, 1)) || (dim = 1);
+  else
+    if (!(isscalar (dim) && dim == fix (dim))
+        || !(1 <= dim && dim <= nd))
+      error ("zscore: DIM must be an integer and a valid dimension");
+    endif
+  endif
+
+  n = sz(dim);
+  if (n == 0)
+    z = x;
+  else
+    x = center (x, dim); # center also promotes integer to double for next line
+    z = zeros (sz, class (x));
+    s = std (x, [], dim);
+    s(s==0) = 1;
+    z = bsxfun (@rdivide, x, s);
+  endif
+
+endfunction
+
+
+%!assert(zscore ([1,2,3]), [-1,0,1])
+%!assert(zscore (single([1,2,3])), single([-1,0,1]))
+%!assert(zscore (int8([1,2,3])), [-1,0,1])
+%!assert(zscore (ones (3,2,2,2)), zeros (3,2,2,2))
+%!assert(zscore ([2,0,-2;0,2,0;-2,-2,2]), [1,0,-1;0,1,0;-1,-1,1])
+
+%% Test input validation
+%!error zscore ()
+%!error zscore (1, 2, 3)
+%!error zscore (['A'; 'B'])
+%!error zscore (1, ones(2,2))
+%!error zscore (1, 1.5)
+%!error zscore (1, 0)
+%!error zscore (1, 3)
+
--- a/scripts/statistics/distributions/betacdf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/betacdf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -18,9 +19,9 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} betacdf (@var{x}, @var{a}, @var{b})
-## For each element of @var{x}, returns the CDF at @var{x} of the beta
-## distribution with parameters @var{a} and @var{b}, i.e.,
-## PROB (beta (@var{a}, @var{b}) @leq{} @var{x}).
+## For each element of @var{x}, compute the cumulative distribution function
+## (CDF) at @var{x} of the Beta distribution with parameters @var{a} and
+## @var{b}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
@@ -32,33 +33,61 @@
     print_usage ();
   endif
 
-  if (!isscalar (a) || !isscalar(b))
+  if (!isscalar (a) || !isscalar (b))
     [retval, x, a, b] = common_size (x, a, b);
     if (retval > 0)
-      error ("betacdf: X, A and B must be of common size or scalar");
+      error ("betacdf: X, A, and B must be of common size or scalars");
     endif
   endif
 
-  sz = size(x);
-  cdf = zeros (sz);
+  if (iscomplex (x) || iscomplex (a) || iscomplex (b))
+    error ("betacdf: X, A, and B must not be complex");
+  endif
 
-  k = find (!(a > 0) | !(b > 0) | isnan (x));
-  if (any (k))
-    cdf (k) = NaN;
+  if (isa (x, "single") || isa (a, "single") || isa (b, "single"))
+    cdf = zeros (size (x), "single");
+  else
+    cdf = zeros (size (x));
   endif
 
-  k = find ((x >= 1) & (a > 0) & (b > 0));
-  if (any (k))
-    cdf (k) = 1;
-  endif
+  k = isnan (x) | !(a > 0) | !(b > 0);
+  cdf(k) = NaN;
+
+  k = (x >= 1) & (a > 0) & (b > 0);
+  cdf(k) = 1;
 
-  k = find ((x > 0) & (x < 1) & (a > 0) & (b > 0));
-  if (any (k))
-    if (isscalar (a) && isscalar(b))
-      cdf (k) = betainc (x(k), a, b);
-    else
-      cdf (k) = betainc (x(k), a(k), b(k));
-    endif
+  k = (x > 0) & (x < 1) & (a > 0) & (b > 0);
+  if (isscalar (a) && isscalar (b))
+    cdf(k) = betainc (x(k), a, b);
+  else
+    cdf(k) = betainc (x(k), a(k), b(k));
   endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 0.5 1 2];
+%! y = [0 0 0.75 1 1];
+%!assert(betacdf (x, ones(1,5), 2*ones(1,5)), y);
+%!assert(betacdf (x, 1, 2*ones(1,5)), y);
+%!assert(betacdf (x, ones(1,5), 2), y);
+%!assert(betacdf (x, [0 1 NaN 1 1], 2), [NaN 0 NaN 1 1]);
+%!assert(betacdf (x, 1, 2*[0 1 NaN 1 1]), [NaN 0 NaN 1 1]);
+%!assert(betacdf ([x(1:2) NaN x(4:5)], 1, 2), [y(1:2) NaN y(4:5)]);
+
+%% Test class of input preserved
+%!assert(betacdf ([x, NaN], 1, 2), [y, NaN]);
+%!assert(betacdf (single([x, NaN]), 1, 2), single([y, NaN]));
+%!assert(betacdf ([x, NaN], single(1), 2), single([y, NaN]));
+%!assert(betacdf ([x, NaN], 1, single(2)), single([y, NaN]));
+
+%% Test input validation
+%!error betacdf ()
+%!error betacdf (1)
+%!error betacdf (1,2)
+%!error betacdf (1,2,3,4)
+%!error betacdf (ones(3),ones(2),ones(2))
+%!error betacdf (ones(2),ones(3),ones(2))
+%!error betacdf (ones(2),ones(2),ones(3))
+
--- a/scripts/statistics/distributions/betainv.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/betainv.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -18,7 +19,7 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} betainv (@var{x}, @var{a}, @var{b})
-## For each component of @var{x}, compute the quantile (the inverse of
+## For each element of @var{x}, compute the quantile (the inverse of
 ## the CDF) at @var{x} of the Beta distribution with parameters @var{a}
 ## and @var{b}.
 ## @end deftypefn
@@ -32,36 +33,39 @@
     print_usage ();
   endif
 
-  if (!isscalar (a) || !isscalar(b))
+  if (!isscalar (a) || !isscalar (b))
     [retval, x, a, b] = common_size (x, a, b);
     if (retval > 0)
-      error ("betainv: X, A and B must be of common size or scalars");
+      error ("betainv: X, A, and B must be of common size or scalars");
     endif
   endif
 
-  sz = size (x);
-  inv = zeros (sz);
-
-  k = find ((x < 0) | (x > 1) | !(a > 0) | !(b > 0) | isnan (x));
-  if (any (k))
-    inv (k) = NaN;
+  if (iscomplex (x) || iscomplex (a) || iscomplex (b))
+    error ("betainv: X, A, and B must not be complex");
   endif
 
-  k = find ((x == 1) & (a > 0) & (b > 0));
-  if (any (k))
-    inv (k) = 1;
+  if (isa (x, "single") || isa (a, "single") || isa (b, "single"))
+    inv = zeros (size (x), "single");
+  else
+    inv = zeros (size (x));
   endif
 
+  k = (x < 0) | (x > 1) | !(a > 0) | !(b > 0) | isnan (x);
+  inv(k) = NaN;
+
+  k = (x == 1) & (a > 0) & (b > 0);
+  inv(k) = 1;
+
   k = find ((x > 0) & (x < 1) & (a > 0) & (b > 0));
   if (any (k))
-    if (!isscalar(a) || !isscalar(b))
-      a = a (k);
-      b = b (k);
+    if (!isscalar (a) || !isscalar (b))
+      a = a(k);
+      b = b(k);
       y = a ./ (a + b);
     else
       y = a / (a + b) * ones (size (k));
     endif
-    x = x (k);
+    x = x(k);
 
     if (isa (y, "single"))
       myeps = eps ("single");
@@ -97,7 +101,36 @@
       y_old = y_new;
     endfor
 
-    inv (k) = y_new;
+    inv(k) = y_new;
   endif
 
 endfunction
+
+
+%!shared x
+%! x = [-1 0 0.75 1 2];
+%!assert(betainv (x, ones(1,5), 2*ones(1,5)), [NaN 0 0.5 1 NaN]);
+%!assert(betainv (x, 1, 2*ones(1,5)), [NaN 0 0.5 1 NaN]);
+%!assert(betainv (x, ones(1,5), 2), [NaN 0 0.5 1 NaN]);
+%!assert(betainv (x, [1 0 NaN 1 1], 2), [NaN NaN NaN 1 NaN]);
+%!assert(betainv (x, 1, 2*[1 0 NaN 1 1]), [NaN NaN NaN 1 NaN]);
+%!assert(betainv ([x(1:2) NaN x(4:5)], 1, 2), [NaN 0 NaN 1 NaN]);
+
+%% Test class of input preserved
+%!assert(betainv ([x, NaN], 1, 2), [NaN 0 0.5 1 NaN NaN]);
+%!assert(betainv (single([x, NaN]), 1, 2), single([NaN 0 0.5 1 NaN NaN]));
+%!assert(betainv ([x, NaN], single(1), 2), single([NaN 0 0.5 1 NaN NaN]));
+%!assert(betainv ([x, NaN], 1, single(2)), single([NaN 0 0.5 1 NaN NaN]));
+
+%% Test input validation
+%!error betainv ()
+%!error betainv (1)
+%!error betainv (1,2)
+%!error betainv (1,2,3,4)
+%!error betainv (ones(3),ones(2),ones(2))
+%!error betainv (ones(2),ones(3),ones(2))
+%!error betainv (ones(2),ones(2),ones(3))
+%!error betainv (i, 2, 2)
+%!error betainv (2, i, 2)
+%!error betainv (2, 2, i)
+
--- a/scripts/statistics/distributions/betapdf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/betapdf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ## Copyright (C) 2010 Christos Dimitrakakis
 ##
@@ -19,8 +20,8 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} betapdf (@var{x}, @var{a}, @var{b})
-## For each element of @var{x}, returns the PDF at @var{x} of the beta
-## distribution with parameters @var{a} and @var{b}.
+## For each element of @var{x}, compute the probability density function (PDF)
+## at @var{x} of the Beta distribution with parameters @var{a} and @var{b}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>, CD <christos.dimitrakakis@gmail.com>
@@ -32,70 +33,98 @@
     print_usage ();
   endif
 
-  if (!isscalar (a) || !isscalar(b))
+  if (!isscalar (a) || !isscalar (b))
     [retval, x, a, b] = common_size (x, a, b);
     if (retval > 0)
-      error ("betapdf: X, A and B must be of common size or scalar");
+      error ("betapdf: X, A, and B must be of common size or scalars");
     endif
   endif
 
-  sz = size (x);
-  pdf = zeros (sz);
+  if (iscomplex (x) || iscomplex (a) || iscomplex (b))
+    error ("betapdf: X, A, and B must not be complex");
+  endif
 
-  k = find (!(a > 0) | !(b > 0) | isnan (x));
-  if (any (k))
-    pdf (k) = NaN;
+  if (isa (x, "single") || isa (a, "single") || isa (b, "single"));
+    pdf = zeros (size (x), "single");
+  else
+    pdf = zeros (size (x));
   endif
 
-  k = find ((x > 0) & (x < 1) & (a > 0) & (b > 0) & ((a != 1) | (b != 1)));
-  if (any (k))
-    if (isscalar(a) && isscalar(b))
-      pdf(k) = exp ((a - 1) .* log (x(k))
-                            + (b - 1) .* log (1 - x(k))
-                    + lgamma(a + b) - lgamma(a) - lgamma(b));
-    else
-      pdf(k) = exp ((a(k) - 1) .* log (x(k))
-                            + (b(k) - 1) .* log (1 - x(k))
-                    + lgamma(a(k) + b(k)) - lgamma(a(k)) - lgamma(b(k)));
-    endif
+  k = !(a > 0) | !(b > 0) | isnan (x);
+  pdf(k) = NaN;
+
+  k = (x > 0) & (x < 1) & (a > 0) & (b > 0) & ((a != 1) | (b != 1));
+  if (isscalar (a) && isscalar (b))
+    pdf(k) = exp ((a - 1) * log (x(k))
+                  + (b - 1) * log (1 - x(k))
+                  + lgamma (a + b) - lgamma (a) - lgamma (b));
+  else
+    pdf(k) = exp ((a(k) - 1) .* log (x(k))
+                  + (b(k) - 1) .* log (1 - x(k))
+                  + lgamma (a(k) + b(k)) - lgamma (a(k)) - lgamma (b(k)));
   endif
 
   ## Most important special cases when the density is finite.
-  k = find ((x == 0) & (a == 1) & (b > 0) & (b != 1));
-  if (any (k))
-    if (isscalar(a) && isscalar(b))
-      pdf(k) = exp(lgamma(a + b) - lgamma(a) - lgamma(b));
-    else
-      pdf(k) = exp(lgamma(a(k) + b(k)) - lgamma(a(k)) - lgamma(b(k)));
-    endif
+  k = (x == 0) & (a == 1) & (b > 0) & (b != 1);
+  if (isscalar (a) && isscalar (b))
+    pdf(k) = exp (lgamma (a + b) - lgamma (a) - lgamma (b));
+  else
+    pdf(k) = exp (lgamma (a(k) + b(k)) - lgamma (a(k)) - lgamma (b(k)));
   endif
 
-  k = find ((x == 1) & (b == 1) & (a > 0) & (a != 1));
-  if (any (k))
-    if (isscalar(a) && isscalar(b))
-      pdf(k) = exp(lgamma(a + b) - lgamma(a) - lgamma(b));
-    else
-      pdf(k) = exp(lgamma(a(k) + b(k)) - lgamma(a(k)) - lgamma(b(k)));
-    endif
+  k = (x == 1) & (b == 1) & (a > 0) & (a != 1);
+  if (isscalar (a) && isscalar (b))
+    pdf(k) = exp (lgamma (a + b) - lgamma (a) - lgamma (b));
+  else
+    pdf(k) = exp (lgamma (a(k) + b(k)) - lgamma (a(k)) - lgamma (b(k)));
   endif
 
-  k = find ((x >= 0) & (x <= 1) & (a == 1) & (b == 1));
-  if (any (k))
-    pdf(k) = 1;
-  endif
+  k = (x >= 0) & (x <= 1) & (a == 1) & (b == 1);
+  pdf(k) = 1;
 
   ## Other special case when the density at the boundary is infinite.
-  k = find ((x == 0) & (a < 1));
-  if (any (k))
-    pdf(k) = Inf;
-  endif
+  k = (x == 0) & (a < 1);
+  pdf(k) = Inf;
 
-  k = find ((x == 1) & (b < 1));
-  if (any (k))
-    pdf(k) = Inf;
-  endif
+  k = (x == 1) & (b < 1);
+  pdf(k) = Inf;
 
 endfunction
 
-%% Test large values for betapdf
+
+%!shared x,y
+%! x = [-1 0 0.5 1 2];
+%! y = [0 2 1 0 0];
+%!assert(betapdf (x, ones(1,5), 2*ones(1,5)), y);
+%!assert(betapdf (x, 1, 2*ones(1,5)), y);
+%!assert(betapdf (x, ones(1,5), 2), y);
+%!assert(betapdf (x, [0 NaN 1 1 1], 2), [NaN NaN y(3:5)]);
+%!assert(betapdf (x, 1, 2*[0 NaN 1 1 1]), [NaN NaN y(3:5)]);
+%!assert(betapdf ([x, NaN], 1, 2), [y, NaN]);
+
+%% Test class of input preserved
+%!assert(betapdf (single([x, NaN]), 1, 2), single([y, NaN]));
+%!assert(betapdf ([x, NaN], single(1), 2), single([y, NaN]));
+%!assert(betapdf ([x, NaN], 1, single(2)), single([y, NaN]));
+
+%% Beta (1/2,1/2) == arcsine distribution
+%!test
+%! x = rand (10,1);
+%! y = 1./(pi * sqrt (x.*(1-x)));
+%! assert(betapdf (x, 1/2, 1/2), y, 50*eps);
+
+%% Test large input values to betapdf
 %!assert (betapdf(0.5, 1000, 1000), 35.678, 1e-3)
+
+%% Test input validation
+%!error betapdf ()
+%!error betapdf (1)
+%!error betapdf (1,2)
+%!error betapdf (1,2,3,4)
+%!error betapdf (ones(3),ones(2),ones(2))
+%!error betapdf (ones(2),ones(3),ones(2))
+%!error betapdf (ones(2),ones(2),ones(3))
+%!error betapdf (i, 2, 2)
+%!error betapdf (2, i, 2)
+%!error betapdf (2, 2, i)
+
--- a/scripts/statistics/distributions/betarnd.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/betarnd.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,83 +18,120 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} betarnd (@var{a}, @var{b}, @var{r}, @var{c})
-## @deftypefnx {Function File} {} betarnd (@var{a}, @var{b}, @var{sz})
-## Return an @var{r} by @var{c} or @code{size (@var{sz})} matrix of
-## random samples from the Beta distribution with parameters @var{a} and
-## @var{b}.  Both @var{a} and @var{b} must be scalar or of size @var{r}
-##  by @var{c}.
+## @deftypefn  {Function File} {} betarnd (@var{a}, @var{b})
+## @deftypefnx {Function File} {} betarnd (@var{a}, @var{b}, @var{r})
+## @deftypefnx {Function File} {} betarnd (@var{a}, @var{b}, @var{r}, @var{c}, @dots{})
+## @deftypefnx {Function File} {} betarnd (@var{a}, @var{b}, [@var{sz}])
+## Return a matrix of random samples from the Beta distribution with parameters
+## @var{a} and @var{b}.
 ##
-## If @var{r} and @var{c} are omitted, the size of the result matrix is
-## the common size of @var{a} and @var{b}.
+## When called with a single size argument, return a square matrix with
+## the dimension specified.  When called with more than one scalar argument the
+## first two arguments are taken as the number of rows and columns and any
+## further arguments specify additional matrix dimensions.  The size may also
+## be specified with a vector of dimensions @var{sz}.
+## 
+## If no size arguments are given then the result matrix is the common size of
+## @var{a} and @var{b}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Random deviates from the Beta distribution
 
-function rnd = betarnd (a, b, r, c)
+function rnd = betarnd (a, b, varargin)
 
-  if (nargin > 1)
-    if (!isscalar(a) || !isscalar(b))
-      [retval, a, b] = common_size (a, b);
-      if (retval > 0)
-        error ("betarnd: A and B must be of common size or scalar");
-      endif
+  if (nargin < 2)
+    print_usage ();
+  endif
+
+  if (!isscalar (a) || !isscalar (b))
+    [retval, a, b] = common_size (a, b);
+    if (retval > 0)
+      error ("betarnd: A and B must be of common size or scalars");
     endif
   endif
 
-  if (nargin == 4)
-    if (! (isscalar (r) && (r > 0) && (r == round (r))))
-      error ("betarnd: R must be a positive integer");
-    endif
-    if (! (isscalar (c) && (c > 0) && (c == round (c))))
-      error ("betarnd: C must be a positive integer");
-    endif
-    sz = [r, c];
+  if (iscomplex (a) || iscomplex (b))
+    error ("betarnd: A and B must not be complex");
+  endif
 
-    if (any (size (a) != 1)
-        && (length (size (a)) != length (sz) || any (size (a) != sz)))
-      error ("betarnd: A and B must be scalar or of size [R,C]");
-    endif
+  if (nargin == 2)
+    sz = size (a);
   elseif (nargin == 3)
-    if (isscalar (r) && (r > 0))
-      sz = [r, r];
-    elseif (isvector(r) && all (r > 0))
-      sz = r(:)';
+    if (isscalar (varargin{1}) && varargin{1} >= 0)
+      sz = [varargin{1}, varargin{1}];
+    elseif (isrow (varargin{1}) && all (varargin{1} >= 0))
+      sz = varargin{1};
     else
-      error ("betarnd: R must be a positive integer or vector");
+      error ("betarnd: dimension vector must be row vector of non-negative integers");
     endif
-
-    if (any (size (a) != 1)
-        && (length (size (a)) != length (sz) || any (size (a) != sz)))
-      error ("betarnd: A and B must be scalar or of size SZ");
+  elseif (nargin > 3)
+    if (any (cellfun (@(x) (!isscalar (x) || x < 0), varargin)))
+      error ("betarnd: dimensions must be non-negative integers");
     endif
-  elseif (nargin == 2)
-    sz = size(a);
-  else
-    print_usage ();
+    sz = [varargin{:}];
   endif
 
-  if (isscalar(a) && isscalar(b))
-    if (find (!(a > 0) | !(a < Inf) | !(b > 0) | !(b < Inf)))
-      rnd = NaN (sz);
+  if (!isscalar (a) && !isequal (size (a), sz))
+    error ("betarnd: A and B must be scalar or of size SZ");
+  endif
+
+  if (isa (a, "single") || isa (b, "single"))
+    cls = "single";
+  else
+    cls = "double";
+  endif
+
+  if (isscalar (a) && isscalar (b))
+    if ((a > 0) && (a < Inf) && (b > 0) && (b < Inf))
+      r = randg (a, sz);
+      rnd = r ./ (r + randg (b, sz));
+      if (strcmp (cls, "single"))
+        rnd = single (rnd);
+      endif
     else
-      r1 = randg(a,sz);
-      rnd = r1 ./ (r1 + randg(b,sz));
+      rnd = NaN (sz, cls);
     endif
   else
-    rnd = zeros (sz);
+    rnd = NaN (sz, cls);
 
-    k = find (!(a > 0) | !(a < Inf) | !(b > 0) | !(b < Inf));
-    if (any (k))
-      rnd(k) = NaN (size (k));
-    endif
-
-    k = find ((a > 0) & (a < Inf) & (b > 0) & (b < Inf));
-    if (any (k))
-      r1 = randg(a(k),size(k));
-      rnd(k) = r1 ./ (r1 + randg(b(k),size(k)));
-    endif
+    k = (a > 0) & (a < Inf) & (b > 0) & (b < Inf);
+    r = randg (a(k));
+    rnd(k) = r ./ (r + randg (b(k)));
   endif
 
 endfunction
+
+
+%!assert(size (betarnd (1,2)), [1, 1]);
+%!assert(size (betarnd (ones(2,1), 2)), [2, 1]);
+%!assert(size (betarnd (ones(2,2), 2)), [2, 2]);
+%!assert(size (betarnd (1, 2*ones(2,1))), [2, 1]);
+%!assert(size (betarnd (1, 2*ones(2,2))), [2, 2]);
+%!assert(size (betarnd (1, 2, 3)), [3, 3]);
+%!assert(size (betarnd (1, 2, [4 1])), [4, 1]);
+%!assert(size (betarnd (1, 2, 4, 1)), [4, 1]);
+
+%% Test class of input preserved
+%!assert(class (betarnd (1, 2)), "double");
+%!assert(class (betarnd (single(1), 2)), "single");
+%!assert(class (betarnd (single([1 1]), 2)), "single");
+%!assert(class (betarnd (1, single(2))), "single");
+%!assert(class (betarnd (1, single([2 2]))), "single");
+
+%% Test input validation
+%!error betarnd ()
+%!error betarnd (1)
+%!error betarnd (ones(3),ones(2))
+%!error betarnd (ones(2),ones(3))
+%!error betarnd (i, 2)
+%!error betarnd (2, i)
+%!error betarnd (1,2, -1)
+%!error betarnd (1,2, ones(2))
+%!error binornd (1,2, [2 -1 2])
+%!error betarnd (1,2, 1, ones(2))
+%!error betarnd (1,2, 1, -1)
+%!error betarnd (ones(2,2), 2, 3)
+%!error betarnd (ones(2,2), 2, [3, 2])
+%!error betarnd (ones(2,2), 2, 2, 3)
+
--- a/scripts/statistics/distributions/binocdf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/binocdf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -18,8 +19,9 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} binocdf (@var{x}, @var{n}, @var{p})
-## For each element of @var{x}, compute the CDF at @var{x} of the
-## binomial distribution with parameters @var{n} and @var{p}.
+## For each element of @var{x}, compute the cumulative distribution function
+## (CDF) at @var{x} of the binomial distribution with parameters @var{n} and
+## @var{p}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
@@ -34,34 +36,62 @@
   if (!isscalar (n) || !isscalar (p))
     [retval, x, n, p] = common_size (x, n, p);
     if (retval > 0)
-      error ("binocdf: X, N and P must be of common size or scalar");
+      error ("binocdf: X, N, and P must be of common size or scalars");
     endif
   endif
 
-  sz = size (x);
-  cdf = zeros (sz);
+  if (iscomplex (x) || iscomplex (n) || iscomplex (p))
+    error ("binocdf: X, N, and P must not be complex");
+  endif
 
-  k = find (isnan (x) | !(n >= 0) | (n != round (n))
-            | !(p >= 0) | !(p <= 1));
-  if (any (k))
-    cdf(k) = NaN;
+  if (isa (x, "single") || isa (n, "single") || isa (p, "single"));
+    cdf = zeros (size (x), "single");
+  else
+    cdf = zeros (size (x));
   endif
 
-  k = find ((x >= n) & (n >= 0) & (n == round (n))
-            & (p >= 0) & (p <= 1));
-  if (any (k))
-    cdf(k) = 1;
-  endif
+  k = isnan (x) | !(n >= 0) | (n != fix (n)) | !(p >= 0) | !(p <= 1);
+  cdf(k) = NaN;
+
+  k = (x >= n) & (n >= 0) & (n == fix (n) & (p >= 0) & (p <= 1));
+  cdf(k) = 1;
 
-  k = find ((x >= 0) & (x < n) & (n == round (n))
-            & (p >= 0) & (p <= 1));
-  if (any (k))
-    tmp = floor (x(k));
-    if (isscalar (n) && isscalar (p))
-      cdf(k) = 1 - betainc (p, tmp + 1, n - tmp);
-    else
-      cdf(k) = 1 - betainc (p(k), tmp + 1, n(k) - tmp);
-    endif
+  k = (x >= 0) & (x < n) & (n == fix (n)) & (p >= 0) & (p <= 1);
+  tmp = floor (x(k));
+  if (isscalar (n) && isscalar (p))
+    cdf(k) = 1 - betainc (p, tmp + 1, n - tmp);
+  else
+    cdf(k) = 1 - betainc (p(k), tmp + 1, n(k) - tmp);
   endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 1 2 3];
+%! y = [0 1/4 3/4 1 1];
+%!assert(binocdf (x, 2*ones(1,5), 0.5*ones(1,5)), y);
+%!assert(binocdf (x, 2, 0.5*ones(1,5)), y);
+%!assert(binocdf (x, 2*ones(1,5), 0.5), y);
+%!assert(binocdf (x, 2*[0 -1 NaN 1.1 1], 0.5), [0 NaN NaN NaN 1]);
+%!assert(binocdf (x, 2, 0.5*[0 -1 NaN 3 1]), [0 NaN NaN NaN 1]);
+%!assert(binocdf ([x(1:2) NaN x(4:5)], 2, 0.5), [y(1:2) NaN y(4:5)]);
+
+%% Test class of input preserved
+%!assert(binocdf ([x, NaN], 2, 0.5), [y, NaN]);
+%!assert(binocdf (single([x, NaN]), 2, 0.5), single([y, NaN]));
+%!assert(binocdf ([x, NaN], single(2), 0.5), single([y, NaN]));
+%!assert(binocdf ([x, NaN], 2, single(0.5)), single([y, NaN]));
+
+%% Test input validation
+%!error binocdf ()
+%!error binocdf (1)
+%!error binocdf (1,2)
+%!error binocdf (1,2,3,4)
+%!error binocdf (ones(3),ones(2),ones(2))
+%!error binocdf (ones(2),ones(3),ones(2))
+%!error binocdf (ones(2),ones(2),ones(3))
+%!error binocdf (i, 2, 2)
+%!error binocdf (2, i, 2)
+%!error binocdf (2, 2, i)
+
--- a/scripts/statistics/distributions/binoinv.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/binoinv.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -18,8 +19,9 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} binoinv (@var{x}, @var{n}, @var{p})
-## For each element of @var{x}, compute the quantile at @var{x} of the
-## binomial distribution with parameters @var{n} and @var{p}.
+## For each element of @var{x}, compute the quantile (the inverse of
+## the CDF) at @var{x} of the binomial distribution with parameters 
+## @var{n} and @var{p}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
@@ -34,24 +36,29 @@
   if (!isscalar (n) || !isscalar (p))
     [retval, x, n, p] = common_size (x, n, p);
     if (retval > 0)
-      error ("binoinv: X, N and P must be of common size or scalars");
+      error ("binoinv: X, N, and P must be of common size or scalars");
     endif
   endif
 
-  sz = size (x);
-  inv = zeros (sz);
+  if (iscomplex (x) || iscomplex (n) || iscomplex (p))
+    error ("binoinv: X, N, and P must not be complex");
+  endif
 
-  k = find (!(x >= 0) | !(x <= 1) | !(n >= 0) | (n != round (n))
-            | !(p >= 0) | !(p <= 1));
-  if (any (k))
-    inv(k) = NaN;
+  if (isa (x, "single") || isa (n, "single") || isa (p, "single"));
+    inv = zeros (size (x), "single");
+  else
+    inv = zeros (size (x));
   endif
 
-  k = find ((x >= 0) & (x <= 1) & (n >= 0) & (n == round (n))
-            & (p >= 0) & (p <= 1));
+  k = (!(x >= 0) | !(x <= 1) | !(n >= 0) | (n != fix (n)) |
+       !(p >= 0) | !(p <= 1));
+  inv(k) = NaN;
+
+  k = find ((x >= 0) & (x <= 1) & (n >= 0) & (n == fix (n)
+             & (p >= 0) & (p <= 1)));
   if (any (k))
     if (isscalar (n) && isscalar (p))
-      cdf = binopdf (0, n, p) * ones (size(k));
+      cdf = binopdf (0, n, p) * ones (size (k));
       while (any (inv(k) < n))
         m = find (cdf < x(k));
         if (any (m))
@@ -76,3 +83,32 @@
   endif
 
 endfunction
+
+
+%!shared x
+%! x = [-1 0 0.5 1 2];
+%!assert(binoinv (x, 2*ones(1,5), 0.5*ones(1,5)), [NaN 0 1 2 NaN]);
+%!assert(binoinv (x, 2, 0.5*ones(1,5)), [NaN 0 1 2 NaN]);
+%!assert(binoinv (x, 2*ones(1,5), 0.5), [NaN 0 1 2 NaN]);
+%!assert(binoinv (x, 2*[0 -1 NaN 1.1 1], 0.5), [NaN NaN NaN NaN NaN]);
+%!assert(binoinv (x, 2, 0.5*[0 -1 NaN 3 1]), [NaN NaN NaN NaN NaN]);
+%!assert(binoinv ([x(1:2) NaN x(4:5)], 2, 0.5), [NaN 0 NaN 2 NaN]);
+
+%% Test class of input preserved
+%!assert(binoinv ([x, NaN], 2, 0.5), [NaN 0 1 2 NaN NaN]);
+%!assert(binoinv (single([x, NaN]), 2, 0.5), single([NaN 0 1 2 NaN NaN]));
+%!assert(binoinv ([x, NaN], single(2), 0.5), single([NaN 0 1 2 NaN NaN]));
+%!assert(binoinv ([x, NaN], 2, single(0.5)), single([NaN 0 1 2 NaN NaN]));
+
+%% Test input validation
+%!error binoinv ()
+%!error binoinv (1)
+%!error binoinv (1,2)
+%!error binoinv (1,2,3,4)
+%!error binoinv (ones(3),ones(2),ones(2))
+%!error binoinv (ones(2),ones(3),ones(2))
+%!error binoinv (ones(2),ones(2),ones(3))
+%!error binoinv (i, 2, 2)
+%!error binoinv (2, i, 2)
+%!error binoinv (2, 2, i)
+
--- a/scripts/statistics/distributions/binopdf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/binopdf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -35,26 +36,60 @@
   if (! isscalar (n) || ! isscalar (p))
     [retval, x, n, p] = common_size (x, n, p);
     if (retval > 0)
-      error ("binopdf: X, N and P must be of common size or scalar");
+      error ("binopdf: X, N, and P must be of common size or scalars");
     endif
   endif
 
-  k = ((x >= 0) & (x <= n)
-       & (x == round (x)) & (n == round (n))
-       & (p >= 0) & (p <= 1));
+  if (iscomplex (x) || iscomplex (n) || iscomplex (p))
+    error ("binopdf: X, N, and P must not be complex");
+  endif
 
-  pdf = zeros (size (x));
+  if (isa (x, "single") || isa (n, "single") || isa (p, "single"));
+    pdf = zeros (size (x), "single");
+  else
+    pdf = zeros (size (x));
+  endif
+
+  k = (x == fix (x)) & (n == fix (n)) & (n >= 0) & (p >= 0) & (p <= 1);
+
   pdf(! k) = NaN;
-  if (any (k(:)))
-    x = x(k);
-    if (! isscalar (n))
-      n = n(k);
-    endif
-    if (! isscalar (p))
-      p = p(k);
-    endif
-    z = gammaln(n+1) - gammaln(x+1) - gammaln(n-x+1) + x.*log(p) + (n-x).*log(1-p);
-    pdf(k) = exp (z);
+
+  k &= ((x >= 0) & (x <= n));
+  if (isscalar (n) && isscalar (p))
+    pdf(k) = exp (gammaln (n+1) - gammaln (x(k)+1) - gammaln (n-x(k)+1)
+                  + x(k)*log (p) + (n-x(k))*log (1-p));
+  else
+    pdf(k) = exp (gammaln (n(k)+1) - gammaln (x(k)+1) - gammaln (n(k)-x(k)+1)
+                  + x(k).*log (p(k)) + (n(k)-x(k)).*log (1-p(k)));
   endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 1 2 3];
+%! y = [0 1/4 1/2 1/4 0];
+%!assert(binopdf (x, 2*ones(1,5), 0.5*ones(1,5)), y);
+%!assert(binopdf (x, 2, 0.5*ones(1,5)), y);
+%!assert(binopdf (x, 2*ones(1,5), 0.5), y);
+%!assert(binopdf (x, 2*[0 -1 NaN 1.1 1], 0.5), [0 NaN NaN NaN 0]);
+%!assert(binopdf (x, 2, 0.5*[0 -1 NaN 3 1]), [0 NaN NaN NaN 0]);
+%!assert(binopdf ([x, NaN], 2, 0.5), [y, NaN]);
+
+%% Test class of input preserved
+%!assert(binopdf (single([x, NaN]), 2, 0.5), single([y, NaN]));
+%!assert(binopdf ([x, NaN], single(2), 0.5), single([y, NaN]));
+%!assert(binopdf ([x, NaN], 2, single(0.5)), single([y, NaN]));
+
+%% Test input validation
+%!error binopdf ()
+%!error binopdf (1)
+%!error binopdf (1,2)
+%!error binopdf (1,2,3,4)
+%!error binopdf (ones(3),ones(2),ones(2))
+%!error binopdf (ones(2),ones(3),ones(2))
+%!error binopdf (ones(2),ones(2),ones(3))
+%!error binopdf (i, 2, 2)
+%!error binopdf (2, i, 2)
+%!error binopdf (2, 2, i)
+
--- a/scripts/statistics/distributions/binornd.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/binornd.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,96 +18,136 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} binornd (@var{n}, @var{p}, @var{r}, @var{c})
-## @deftypefnx {Function File} {} binornd (@var{n}, @var{p}, @var{sz})
-## Return an @var{r} by @var{c}  or a @code{size (@var{sz})} matrix of
-## random samples from the binomial distribution with parameters @var{n}
-## and @var{p}.  Both @var{n} and @var{p} must be scalar or of size
-## @var{r} by @var{c}.
+## @deftypefn  {Function File} {} binornd (@var{n}, @var{p})
+## @deftypefnx {Function File} {} binornd (@var{n}, @var{p}, @var{r})
+## @deftypefnx {Function File} {} binornd (@var{n}, @var{p}, @var{r}, @var{c}, @dots{})
+## @deftypefnx {Function File} {} binornd (@var{n}, @var{p}, [@var{sz}])
+## Return a matrix of random samples from the binonmial distribution with
+## parameters @var{n} and @var{p}.
 ##
-## If @var{r} and @var{c} are omitted, the size of the result matrix is
-## the common size of @var{n} and @var{p}.
+## When called with a single size argument, return a square matrix with
+## the dimension specified.  When called with more than one scalar argument the
+## first two arguments are taken as the number of rows and columns and any
+## further arguments specify additional matrix dimensions.  The size may also
+## be specified with a vector of dimensions @var{sz}.
+## 
+## If no size arguments are given then the result matrix is the common size of
+## @var{n} and @var{p}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Random deviates from the binomial distribution
 
-function rnd = binornd (n, p, r, c)
+function rnd = binornd (n, p, varargin)
 
-  if (nargin > 1)
-    if (!isscalar(n) || !isscalar(p))
-      [retval, n, p] = common_size (n, p);
-      if (retval > 0)
-        error ("binornd: N and P must be of common size or scalar");
-      endif
+  if (nargin < 2)
+    print_usage ();
+  endif
+
+  if (!isscalar (n) || !isscalar (p))
+    [retval, n, p] = common_size (n, p);
+    if (retval > 0)
+      error ("binornd: N and P must be of common size or scalars");
     endif
   endif
 
-  if (nargin == 4)
-    if (! (isscalar (r) && (r > 0) && (r == round (r))))
-      error ("binornd: R must be a positive integer");
-    endif
-    if (! (isscalar (c) && (c > 0) && (c == round (c))))
-      error ("binornd: C must be a positive integer");
-    endif
-    sz = [r, c];
+  if (iscomplex (n) || iscomplex (p))
+    error ("binornd: N and P must not be complex");
+  endif
 
-    if (any (size (n) != 1)
-        && (length (size (n)) != length (sz) || any (size (n) != sz)))
-      error ("binornd: N and must be scalar or of size [R, C]");
-    endif
+  if (nargin == 2)
+    sz = size (n);
   elseif (nargin == 3)
-    if (isscalar (r) && (r > 0))
-      sz = [r, r];
-    elseif (isvector(r) && all (r > 0))
-      sz = r(:)';
+    if (isscalar (varargin{1}) && varargin{1} >= 0)
+      sz = [varargin{1}, varargin{1}];
+    elseif (isrow (varargin{1}) && all (varargin{1} >= 0))
+      sz = varargin{1};
     else
-      error ("binornd: R must be a positive integer or vector");
+      error ("binornd: dimension vector must be row vector of non-negative integers");
     endif
+  elseif (nargin > 3)
+    if (any (cellfun (@(x) (!isscalar (x) || x < 0), varargin)))
+      error ("binornd: dimensions must be non-negative integers");
+    endif
+    sz = [varargin{:}];
+  endif
 
-    if (any (size (n) != 1)
-        && (length (size (n)) != length (sz) || any (size (n) != sz)))
-      error ("binornd: N and must be scalar or of size SZ");
-    endif
-  elseif (nargin == 2)
-    sz = size(n);
+  if (!isscalar (n) && !isequal (size (n), sz))
+    error ("binornd: N and P must be scalar or of size SZ");
+  endif
+
+  if (isa (n, "single") || isa (p, "single"))
+    cls = "single";
   else
-    print_usage ();
+    cls = "double";
   endif
 
   if (isscalar (n) && isscalar (p))
-    if (find (!(n >= 0) | !(n < Inf) | !(n == round (n)) |
-              !(p >= 0) | !(p <= 1)))
-      rnd = NaN (sz);
-    elseif (n == 0)
-      rnd = zeros (sz);
-    else
+    if ((n > 0) && (n < Inf) && (n == fix (n)) && (p >= 0) && (p <= 1))
       nel = prod (sz);
       tmp = rand (n, nel);
-      rnd = sum(tmp < ones (n, nel) * p, 1);
-      rnd = reshape(rnd, sz);
+      rnd = sum (tmp < p, 1);
+      rnd = reshape (rnd, sz);
+      if (strcmp (cls, "single"))
+        rnd = single (rnd);
+      endif
+    elseif ((n == 0) && (p >= 0) && (p <= 1))
+      rnd = zeros (sz, cls);
+    else
+      rnd = NaN (sz, cls);
     endif
   else
-    rnd = zeros (sz);
+    rnd = zeros (sz, cls);
 
-    k = find (!(n >= 0) | !(n < Inf) | !(n == round (n)) |
-              !(p >= 0) | !(p <= 1));
-    if (any (k))
-      rnd(k) = NaN;
-    endif
+    k = !(n >= 0) | !(n < Inf) | !(n == fix (n)) | !(p >= 0) | !(p <= 1);
+    rnd(k) = NaN;
 
-    k = find ((n > 0) & (n < Inf) & (n == round (n)) & (p >= 0) & (p <= 1));
-    if (any (k))
+    k = (n > 0) & (n < Inf) & (n == fix (n)) & (p >= 0) & (p <= 1);
+    if (any (k(:)))
       N = max (n(k));
-      L = length (k);
+      L = sum (k(:));
       tmp = rand (N, L);
-      ind = (1 : N)' * ones (1, L);
-      rnd(k) = sum ((tmp < ones (N, 1) * p(k)(:)') &
-                    (ind <= ones (N, 1) * n(k)(:)'),1);
+      ind = repmat ((1 : N)', 1, L);
+      rnd(k) = sum ((tmp < repmat (p(k)(:)', N, 1)) &
+                    (ind <= repmat (n(k)(:)', N, 1)), 1);
     endif
   endif
 
 endfunction
 
-%!assert (binornd(0, 0, 1), 0)
-%!assert (binornd([0, 0], [0, 0], 1, 2), [0, 0])
+
+%!assert (binornd (0, 0, 1), 0)
+%!assert (binornd ([0, 0], [0, 0], 1, 2), [0, 0])
+
+%!assert(size (binornd (2, 1/2)), [1, 1]);
+%!assert(size (binornd (2*ones(2,1), 1/2)), [2, 1]);
+%!assert(size (binornd (2*ones(2,2), 1/2)), [2, 2]);
+%!assert(size (binornd (2, 1/2*ones(2,1))), [2, 1]);
+%!assert(size (binornd (2, 1/2*ones(2,2))), [2, 2]);
+%!assert(size (binornd (2, 1/2, 3)), [3, 3]);
+%!assert(size (binornd (2, 1/2, [4 1])), [4, 1]);
+%!assert(size (binornd (2, 1/2, 4, 1)), [4, 1]);
+
+%% Test class of input preserved
+%!assert(class (binornd (2, 0.5)), "double");
+%!assert(class (binornd (single(2), 0.5)), "single");
+%!assert(class (binornd (single([2 2]), 0.5)), "single");
+%!assert(class (binornd (2, single(0.5))), "single");
+%!assert(class (binornd (2, single([0.5 0.5]))), "single");
+
+%% Test input validation
+%!error binornd ()
+%!error binornd (1)
+%!error binornd (ones(3),ones(2))
+%!error binornd (ones(2),ones(3))
+%!error binornd (i, 2)
+%!error binornd (2, i)
+%!error binornd (1,2, -1)
+%!error binornd (1,2, ones(2))
+%!error binornd (1,2, [2 -1 2])
+%!error binornd (1,2, 1, ones(2))
+%!error binornd (1,2, 1, -1)
+%!error binornd (ones(2,2), 2, 3)
+%!error binornd (ones(2,2), 2, [3, 2])
+%!error binornd (ones(2,2), 2, 2, 3)
+
--- a/scripts/statistics/distributions/cauchy_cdf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/cauchy_cdf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,7 +18,8 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} cauchy_cdf (@var{x}, @var{location}, @var{scale})
+## @deftypefn  {Function File} {} cauchy_cdf (@var{x})
+## @deftypefnx {Function File} {} cauchy_cdf (@var{x}, @var{location}, @var{scale})
 ## For each element of @var{x}, compute the cumulative distribution
 ## function (CDF) at @var{x} of the Cauchy distribution with location
 ## parameter @var{location} and scale parameter @var{scale}.  Default
@@ -27,35 +29,63 @@
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: CDF of the Cauchy distribution
 
-function cdf = cauchy_cdf (x, location, scale)
+function cdf = cauchy_cdf (x, location = 0, scale = 1)
 
-  if (! (nargin == 1 || nargin == 3))
+  if (nargin != 1 && nargin != 3)
     print_usage ();
   endif
 
-  if (nargin == 1)
-    location = 0;
-    scale = 1;
-  endif
-
   if (!isscalar (location) || !isscalar (scale))
     [retval, x, location, scale] = common_size (x, location, scale);
     if (retval > 0)
-      error ("cauchy_cdf: X, LOCATION and SCALE must be of common size or scalar");
+      error ("cauchy_cdf: X, LOCATION, and SCALE must be of common size or scalars");
     endif
   endif
 
-  sz = size (x);
-  cdf = NaN (sz);
+  if (iscomplex (x) || iscomplex (location) || iscomplex (scale))
+    error ("cauchy_cdf: X, LOCATION, and SCALE must not be complex");
+  endif
 
-  k = find (ones (sz) & (location > -Inf) & (location < Inf)
-                      & (scale > 0) & (scale < Inf));
-  if (any (k))
-    if (isscalar (location) && isscalar (scale))
-      cdf(k) = 0.5 + atan ((x(k) - location) ./ scale) / pi;
-    else
-      cdf(k) = 0.5 + atan ((x(k) - location(k)) ./ scale(k)) / pi;
-    endif
+  if (isa (x, "single") || isa (location, "single") || isa (scale, "single"));
+    cdf = NaN (size (x), "single");
+  else
+    cdf = NaN (size (x));
+  endif
+
+  k = !isinf (location) & (scale > 0) & (scale < Inf);
+  if (isscalar (location) && isscalar (scale))
+    cdf = 0.5 + atan ((x - location) / scale) / pi;
+  else
+    cdf(k) = 0.5 + atan ((x(k) - location(k)) ./ scale(k)) / pi;
   endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 0.5 1 2];
+%! y = 1/pi * atan ((x-1) / 2) + 1/2;
+%!assert(cauchy_cdf (x, ones(1,5), 2*ones(1,5)), y);
+%!assert(cauchy_cdf (x, 1, 2*ones(1,5)), y);
+%!assert(cauchy_cdf (x, ones(1,5), 2), y);
+%!assert(cauchy_cdf (x, [-Inf 1 NaN 1 Inf], 2), [NaN y(2) NaN y(4) NaN]);
+%!assert(cauchy_cdf (x, 1, 2*[0 1 NaN 1 Inf]), [NaN y(2) NaN y(4) NaN]);
+%!assert(cauchy_cdf ([x(1:2) NaN x(4:5)], 1, 2), [y(1:2) NaN y(4:5)]);
+
+%% Test class of input preserved
+%!assert(cauchy_cdf ([x, NaN], 1, 2), [y, NaN]);
+%!assert(cauchy_cdf (single([x, NaN]), 1, 2), single([y, NaN]), eps("single"));
+%!assert(cauchy_cdf ([x, NaN], single(1), 2), single([y, NaN]), eps("single"));
+%!assert(cauchy_cdf ([x, NaN], 1, single(2)), single([y, NaN]), eps("single"));
+
+%% Test input validation
+%!error cauchy_cdf ()
+%!error cauchy_cdf (1,2)
+%!error cauchy_cdf (1,2,3,4)
+%!error cauchy_cdf (ones(3),ones(2),ones(2))
+%!error cauchy_cdf (ones(2),ones(3),ones(2))
+%!error cauchy_cdf (ones(2),ones(2),ones(3))
+%!error cauchy_cdf (i, 2, 2)
+%!error cauchy_cdf (2, i, 2)
+%!error cauchy_cdf (2, 2, i)
+
--- a/scripts/statistics/distributions/cauchy_inv.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/cauchy_inv.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,7 +18,8 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} cauchy_inv (@var{x}, @var{location}, @var{scale})
+## @deftypefn  {Function File} {} cauchy_inv (@var{x})
+## @deftypefnx {Function File} {} cauchy_inv (@var{x}, @var{location}, @var{scale})
 ## For each element of @var{x}, compute the quantile (the inverse of the
 ## CDF) at @var{x} of the Cauchy distribution with location parameter
 ## @var{location} and scale parameter @var{scale}.  Default values are
@@ -27,47 +29,70 @@
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Quantile function of the Cauchy distribution
 
-function inv = cauchy_inv (x, location, scale)
+function inv = cauchy_inv (x, location = 0, scale = 1)
 
-  if (! (nargin == 1 || nargin == 3))
+  if (nargin != 1 && nargin != 3)
     print_usage ();
   endif
 
-  if (nargin == 1)
-    location = 0;
-    scale = 1;
-  endif
-
   if (!isscalar (location) || !isscalar (scale))
     [retval, x, location, scale] = common_size (x, location, scale);
     if (retval > 0)
-      error ("cauchy_inv: X, LOCATION and SCALE must be of common size or scalar");
+      error ("cauchy_inv: X, LOCATION, and SCALE must be of common size or scalars");
     endif
   endif
 
-  sz = size (x);
-  inv = NaN (sz);
+  if (iscomplex (x) || iscomplex (location) || iscomplex (scale))
+    error ("cauchy_inv: X, LOCATION, and SCALE must not be complex");
+  endif
 
-  ok = ((location > -Inf) & (location < Inf) &
-       (scale > 0) & (scale < Inf));
-
-  k = find ((x == 0) & ok);
-  if (any (k))
-    inv(k) = -Inf;
+  if (isa (x, "single") || isa (location, "single") || isa (scale, "single"))
+    inv = NaN (size (x), "single");
+  else
+    inv = NaN (size (x));
   endif
 
-  k = find ((x > 0) & (x < 1) & ok);
-  if (any (k))
-    if (isscalar (location) && isscalar (scale))
-      inv(k) = location - scale .* cot (pi * x(k));
-    else
-      inv(k) = location(k) - scale(k) .* cot (pi * x(k));
-    endif
-  endif
+  ok = !isinf (location) & (scale > 0) & (scale < Inf);
+
+  k = (x == 0) & ok;
+  inv(k) = -Inf;
 
-  k = find ((x == 1) & ok);
-  if (any (k))
-    inv(k) = Inf;
+  k = (x == 1) & ok;
+  inv(k) = Inf;
+
+  k = (x > 0) & (x < 1) & ok;
+  if (isscalar (location) && isscalar (scale))
+    inv(k) = location - scale * cot (pi * x(k));
+  else
+    inv(k) = location(k) - scale(k) .* cot (pi * x(k));
   endif
 
 endfunction
+
+
+%!shared x
+%! x = [-1 0 0.5 1 2];
+%!assert(cauchy_inv (x, ones(1,5), 2*ones(1,5)), [NaN -Inf 1 Inf NaN], eps);
+%!assert(cauchy_inv (x, 1, 2*ones(1,5)), [NaN -Inf 1 Inf NaN], eps);
+%!assert(cauchy_inv (x, ones(1,5), 2), [NaN -Inf 1 Inf NaN], eps);
+%!assert(cauchy_inv (x, [1 -Inf NaN Inf 1], 2), [NaN NaN NaN NaN NaN]);
+%!assert(cauchy_inv (x, 1, 2*[1 0 NaN Inf 1]), [NaN NaN NaN NaN NaN]);
+%!assert(cauchy_inv ([x(1:2) NaN x(4:5)], 1, 2), [NaN -Inf NaN Inf NaN]);
+
+%% Test class of input preserved
+%!assert(cauchy_inv ([x, NaN], 1, 2), [NaN -Inf 1 Inf NaN NaN], eps);
+%!assert(cauchy_inv (single([x, NaN]), 1, 2), single([NaN -Inf 1 Inf NaN NaN]), eps("single"));
+%!assert(cauchy_inv ([x, NaN], single(1), 2), single([NaN -Inf 1 Inf NaN NaN]), eps("single"));
+%!assert(cauchy_inv ([x, NaN], 1, single(2)), single([NaN -Inf 1 Inf NaN NaN]), eps("single"));
+
+%% Test input validation
+%!error cauchy_inv ()
+%!error cauchy_inv (1,2)
+%!error cauchy_inv (1,2,3,4)
+%!error cauchy_inv (ones(3),ones(2),ones(2))
+%!error cauchy_inv (ones(2),ones(3),ones(2))
+%!error cauchy_inv (ones(2),ones(2),ones(3))
+%!error cauchy_inv (i, 2, 2)
+%!error cauchy_inv (2, i, 2)
+%!error cauchy_inv (2, 2, i)
+
--- a/scripts/statistics/distributions/cauchy_pdf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/cauchy_pdf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,7 +18,8 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} cauchy_pdf (@var{x}, @var{location}, @var{scale})
+## @deftypefn  {Function File} {} cauchy_pdf (@var{x})
+## @deftypefnx {Function File} {} cauchy_pdf (@var{x}, @var{location}, @var{scale})
 ## For each element of @var{x}, compute the probability density function
 ## (PDF) at @var{x} of the Cauchy distribution with location parameter
 ## @var{location} and scale parameter @var{scale} > 0.  Default values are
@@ -27,37 +29,69 @@
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: PDF of the Cauchy distribution
 
-function pdf = cauchy_pdf (x, location, scale)
+function pdf = cauchy_pdf (x, location = 0, scale = 1)
 
-  if (! (nargin == 1 || nargin == 3))
+  if (nargin != 1 && nargin != 3)
     print_usage ();
   endif
 
-  if (nargin == 1)
-    location = 0;
-    scale = 1;
-  endif
-
   if (!isscalar (location) || !isscalar (scale))
     [retval, x, location, scale] = common_size (x, location, scale);
     if (retval > 0)
-      error ("cauchy_pdf: X, LOCATION and SCALE must be of common size or scalar");
+      error ("cauchy_pdf: X, LOCATION, and SCALE must be of common size or scalars");
     endif
   endif
 
-  sz = size (x);
-  pdf = NaN (sz);
+  if (iscomplex (x) || iscomplex (location) || iscomplex (scale))
+    error ("cauchy_pdf: X, LOCATION, and SCALE must not be complex");
+  endif
 
-  k = find ((x > -Inf) & (x < Inf) & (location > -Inf) &
-            (location < Inf) & (scale > 0) & (scale < Inf));
-  if (any (k))
-    if (isscalar (location) && isscalar (scale))
-      pdf(k) = ((1 ./ (1 + ((x(k) - location) ./ scale) .^ 2))
-                / pi ./ scale);
-    else
-      pdf(k) = ((1 ./ (1 + ((x(k) - location(k)) ./ scale(k)) .^ 2))
-                / pi ./ scale(k));
-    endif
+  if (isa (x, "single") || isa (location, "single") || isa (scale, "single"))
+    pdf = NaN (size (x), "single");
+  else
+    pdf = NaN (size (x));
+  endif
+
+  k = !isinf (location) & (scale > 0) & (scale < Inf);
+  if (isscalar (location) && isscalar (scale))
+    pdf = ((1 ./ (1 + ((x - location) / scale) .^ 2))
+              / pi / scale);
+  else
+    pdf(k) = ((1 ./ (1 + ((x(k) - location(k)) ./ scale(k)) .^ 2))
+              / pi ./ scale(k));
   endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 0.5 1 2];
+%! y = 1/pi * ( 2 ./ ((x-1).^2 + 2^2) );
+%!assert(cauchy_pdf (x, ones(1,5), 2*ones(1,5)), y);
+%!assert(cauchy_pdf (x, 1, 2*ones(1,5)), y);
+%!assert(cauchy_pdf (x, ones(1,5), 2), y);
+%!assert(cauchy_pdf (x, [-Inf 1 NaN 1 Inf], 2), [NaN y(2) NaN y(4) NaN]);
+%!assert(cauchy_pdf (x, 1, 2*[0 1 NaN 1 Inf]), [NaN y(2) NaN y(4) NaN]);
+%!assert(cauchy_pdf ([x, NaN], 1, 2), [y, NaN]);
+
+%% Test class of input preserved
+%!assert(cauchy_pdf (single([x, NaN]), 1, 2), single([y, NaN]), eps("single"));
+%!assert(cauchy_pdf ([x, NaN], single(1), 2), single([y, NaN]), eps("single"));
+%!assert(cauchy_pdf ([x, NaN], 1, single(2)), single([y, NaN]), eps("single"));
+
+%% Cauchy (0,1) == Student's T distribution with 1 DOF
+%!test
+%! x = rand (10, 1);
+%! assert(cauchy_pdf (x, 0, 1), tpdf (x, 1), eps);
+
+%% Test input validation
+%!error cauchy_pdf ()
+%!error cauchy_pdf (1,2)
+%!error cauchy_pdf (1,2,3,4)
+%!error cauchy_pdf (ones(3),ones(2),ones(2))
+%!error cauchy_pdf (ones(2),ones(3),ones(2))
+%!error cauchy_pdf (ones(2),ones(2),ones(3))
+%!error cauchy_pdf (i, 2, 2)
+%!error cauchy_pdf (2, i, 2)
+%!error cauchy_pdf (2, 2, i)
+
--- a/scripts/statistics/distributions/cauchy_rnd.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/cauchy_rnd.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,78 +18,115 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} cauchy_rnd (@var{location}, @var{scale}, @var{r}, @var{c})
-## @deftypefnx {Function File} {} cauchy_rnd (@var{location}, @var{scale}, @var{sz})
-## Return an @var{r} by @var{c} or a @code{size (@var{sz})} matrix of
-## random samples from the Cauchy distribution with parameters @var{location}
-## and @var{scale} which must both be scalar or of size @var{r} by @var{c}.
+## @deftypefn  {Function File} {} cauchy_rnd (@var{location}, @var{scale})
+## @deftypefnx {Function File} {} cauchy_rnd (@var{location}, @var{scale}, @var{r})
+## @deftypefnx {Function File} {} cauchy_rnd (@var{location}, @var{scale}, @var{r}, @var{c}, @dots{})
+## @deftypefnx {Function File} {} cauchy_rnd (@var{location}, @var{scale}, [@var{sz}])
+## Return a matrix of random samples from the Cauchy distribution with
+## parameters @var{location} and @var{scale}.
 ##
-## If @var{r} and @var{c} are omitted, the size of the result matrix is
-## the common size of @var{location} and @var{scale}.
+## When called with a single size argument, return a square matrix with
+## the dimension specified.  When called with more than one scalar argument the
+## first two arguments are taken as the number of rows and columns and any
+## further arguments specify additional matrix dimensions.  The size may also
+## be specified with a vector of dimensions @var{sz}.
+## 
+## If no size arguments are given then the result matrix is the common size of
+## @var{location} and @var{scale}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Random deviates from the Cauchy distribution
 
-function rnd = cauchy_rnd (location, scale, r, c)
+function rnd = cauchy_rnd (location, scale, varargin)
 
-  if (nargin > 1)
-    if (!isscalar (location) || !isscalar (scale))
-      [retval, location, scale] = common_size (location, scale);
-      if (retval > 0)
-        error ("cauchy_rnd: LOCATION and SCALE must be of common size or scalar");
-      endif
+  if (nargin < 2)
+    print_usage ();
+  endif
+
+  if (!isscalar (location) || !isscalar (scale))
+    [retval, location, scale] = common_size (location, scale);
+    if (retval > 0)
+      error ("cauchy_rnd: LOCATION and SCALE must be of common size or scalars");
     endif
   endif
 
-  if (nargin == 4)
-    if (! (isscalar (r) && (r > 0) && (r == round (r))))
-      error ("cauchy_rnd: R must be a positive integer");
-    endif
-    if (! (isscalar (c) && (c > 0) && (c == round (c))))
-      error ("cauchy_rnd: C must be a positive integer");
-    endif
-    sz = [r, c];
+  if (iscomplex (location) || iscomplex (scale))
+    error ("cauchy_rnd: LOCATION and SCALE must not be complex");
+  endif
 
-    if (any (size (location) != 1)
-        && (length (size (location)) != length (sz)
-            || any (size (location) != sz)))
-      error ("cauchy_rnd: LOCATION and SCALE must be scalar or of size [R, C]");
-    endif
+  if (nargin == 2)
+    sz = size (location);
   elseif (nargin == 3)
-    if (isscalar (r) && (r > 0))
-      sz = [r, r];
-    elseif (isvector(r) && all (r > 0))
-      sz = r(:)';
+    if (isscalar (varargin{1}) && varargin{1} >= 0)
+      sz = [varargin{1}, varargin{1}];
+    elseif (isrow (varargin{1}) && all (varargin{1} >= 0))
+      sz = varargin{1};
     else
-      error ("cauchy_rnd: R must be a positive integer or vector");
+      error ("cauchy_rnd: dimension vector must be row vector of non-negative integers");
     endif
+  elseif (nargin > 3)
+    if (any (cellfun (@(x) (!isscalar (x) || x < 0), varargin)))
+      error ("cauchy_rnd: dimensions must be non-negative integers");
+    endif
+    sz = [varargin{:}];
+  endif
 
-    if (any (size (location) != 1)
-        && (length (size (location)) != length (sz)
-        || any (size (location) != sz)))
-      error ("cauchy_rnd: LOCATION and SCALE must be scalar or of size SZ");
-    endif
-  elseif (nargin == 2)
-    sz = size(location);
+  if (!isscalar (location) && !isequal (size (location), sz))
+    error ("cauchy_rnd: LOCATION and SCALE must be scalar or of size SZ");
+  endif
+
+  if (isa (location, "single") || isa (scale, "single"))
+    cls = "single";
   else
-    print_usage ();
+    cls = "double";
   endif
 
   if (isscalar (location) && isscalar (scale))
-    if (find (!(location > -Inf) | !(location < Inf)
-                | !(scale > 0) | !(scale < Inf)))
-      rnd = NaN (sz);
+    if (!isinf (location) && (scale > 0) && (scale < Inf))
+      rnd = location - cot (pi * rand (sz)) * scale;
     else
-      rnd = location - cot (pi * rand (sz)) .* scale;
+      rnd = NaN (sz, cls);
     endif
   else
-    rnd = NaN (sz);
-    k = find ((location > -Inf) & (location < Inf)
-              & (scale > 0) & (scale < Inf));
-    if (any (k))
-      rnd(k) = location(k)(:) - cot (pi * rand (size (k))) .* scale(k)(:);
-    endif
+    rnd = NaN (sz, cls);
+
+    k = !isinf (location) & (scale > 0) & (scale < Inf);
+    rnd(k) = location(k)(:) - cot (pi * rand (sum (k(:)), 1)) .* scale(k)(:);
   endif
 
 endfunction
+
+
+%!assert(size (cauchy_rnd (1,2)), [1, 1]);
+%!assert(size (cauchy_rnd (ones(2,1), 2)), [2, 1]);
+%!assert(size (cauchy_rnd (ones(2,2), 2)), [2, 2]);
+%!assert(size (cauchy_rnd (1, 2*ones(2,1))), [2, 1]);
+%!assert(size (cauchy_rnd (1, 2*ones(2,2))), [2, 2]);
+%!assert(size (cauchy_rnd (1, 2, 3)), [3, 3]);
+%!assert(size (cauchy_rnd (1, 2, [4 1])), [4, 1]);
+%!assert(size (cauchy_rnd (1, 2, 4, 1)), [4, 1]);
+
+%% Test class of input preserved
+%!assert(class (cauchy_rnd (1, 2)), "double");
+%!assert(class (cauchy_rnd (single(1), 2)), "single");
+%!assert(class (cauchy_rnd (single([1 1]), 2)), "single");
+%!assert(class (cauchy_rnd (1, single(2))), "single");
+%!assert(class (cauchy_rnd (1, single([2 2]))), "single");
+
+%% Test input validation
+%!error cauchy_rnd ()
+%!error cauchy_rnd (1)
+%!error cauchy_rnd (ones(3),ones(2))
+%!error cauchy_rnd (ones(2),ones(3))
+%!error cauchy_rnd (i, 2)
+%!error cauchy_rnd (2, i)
+%!error cauchy_rnd (1,2, -1)
+%!error cauchy_rnd (1,2, ones(2))
+%!error cauchy_rnd (1,2, [2 -1 2])
+%!error cauchy_rnd (1,2, 1, ones(2))
+%!error cauchy_rnd (1,2, 1, -1)
+%!error cauchy_rnd (ones(2,2), 2, 3)
+%!error cauchy_rnd (ones(2,2), 2, [3, 2])
+%!error cauchy_rnd (ones(2,2), 2, 2, 3)
+
--- a/scripts/statistics/distributions/chi2cdf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/chi2cdf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -19,7 +20,7 @@
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} chi2cdf (@var{x}, @var{n})
 ## For each element of @var{x}, compute the cumulative distribution
-## function (CDF) at @var{x} of the chisquare distribution with @var{n}
+## function (CDF) at @var{x} of the chi-square distribution with @var{n}
 ## degrees of freedom.
 ## @end deftypefn
 
@@ -35,10 +36,38 @@
   if (!isscalar (n))
     [retval, x, n] = common_size (x, n);
     if (retval > 0)
-      error ("chi2cdf: X and N must be of common size or scalar");
+      error ("chi2cdf: X and N must be of common size or scalars");
     endif
   endif
 
-  cdf = gamcdf (x, n / 2, 2);
+  if (iscomplex (x) || iscomplex (n))
+    error ("chi2cdf: X and N must not be complex");
+  endif
+
+  cdf = gamcdf (x, n/2, 2);
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 0.5 1 2];
+%! y = [0, 1 - exp(-x(2:end)/2)];
+%!assert(chi2cdf (x, 2*ones(1,5)), y, eps);
+%!assert(chi2cdf (x, 2), y, eps);
+%!assert(chi2cdf (x, 2*[1 0 NaN 1 1]), [y(1) NaN NaN y(4:5)], eps);
+%!assert(chi2cdf ([x(1:2) NaN x(4:5)], 2), [y(1:2) NaN y(4:5)], eps);
+
+%% Test class of input preserved
+%!assert(chi2cdf ([x, NaN], 2), [y, NaN], eps);
+%!assert(chi2cdf (single([x, NaN]), 2), single([y, NaN]), eps("single"));
+%!assert(chi2cdf ([x, NaN], single(2)), single([y, NaN]), eps("single"));
+
+%% Test input validation
+%!error chi2cdf ()
+%!error chi2cdf (1)
+%!error chi2cdf (1,2,3)
+%!error chi2cdf (ones(3),ones(2))
+%!error chi2cdf (ones(2),ones(3))
+%!error chi2cdf (i, 2)
+%!error chi2cdf (2, i)
+
--- a/scripts/statistics/distributions/chi2inv.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/chi2inv.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -19,7 +20,7 @@
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} chi2inv (@var{x}, @var{n})
 ## For each element of @var{x}, compute the quantile (the inverse of the
-## CDF) at @var{x} of the chisquare distribution with @var{n} degrees of
+## CDF) at @var{x} of the chi-square distribution with @var{n} degrees of
 ## freedom.
 ## @end deftypefn
 
@@ -35,10 +36,37 @@
   if (!isscalar (n))
     [retval, x, n] = common_size (x, n);
     if (retval > 0)
-      error ("chi2inv: X and N must be of common size or scalar");
+      error ("chi2inv: X and N must be of common size or scalars");
     endif
   endif
 
-  inv = gaminv (x, n / 2, 2);
+  if (iscomplex (x) || iscomplex (n))
+    error ("chi2inv: X and N must not be complex");
+  endif
+
+  inv = gaminv (x, n/2, 2);
 
 endfunction
+
+
+%!shared x
+%! x = [-1 0 0.3934693402873666 1 2];
+%!assert(chi2inv (x, 2*ones(1,5)), [NaN 0 1 Inf NaN], 5*eps);
+%!assert(chi2inv (x, 2), [NaN 0 1 Inf NaN], 5*eps);
+%!assert(chi2inv (x, 2*[0 1 NaN 1 1]), [NaN 0 NaN Inf NaN], 5*eps);
+%!assert(chi2inv ([x(1:2) NaN x(4:5)], 2), [NaN 0 NaN Inf NaN], 5*eps);
+
+%% Test class of input preserved
+%!assert(chi2inv ([x, NaN], 2), [NaN 0 1 Inf NaN NaN], 5*eps);
+%!assert(chi2inv (single([x, NaN]), 2), single([NaN 0 1 Inf NaN NaN]), 5*eps("single"));
+%!assert(chi2inv ([x, NaN], single(2)), single([NaN 0 1 Inf NaN NaN]), 5*eps("single"));
+
+%% Test input validation
+%!error chi2inv ()
+%!error chi2inv (1)
+%!error chi2inv (1,2,3)
+%!error chi2inv (ones(3),ones(2))
+%!error chi2inv (ones(2),ones(3))
+%!error chi2inv (i, 2)
+%!error chi2inv (2, i)
+
--- a/scripts/statistics/distributions/chi2pdf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/chi2pdf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -19,7 +20,7 @@
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} chi2pdf (@var{x}, @var{n})
 ## For each element of @var{x}, compute the probability density function
-## (PDF) at @var{x} of the chisquare distribution with @var{n} degrees
+## (PDF) at @var{x} of the chi-square distribution with @var{n} degrees
 ## of freedom.
 ## @end deftypefn
 
@@ -35,10 +36,37 @@
   if (!isscalar (n))
     [retval, x, n] = common_size (x, n);
     if (retval > 0)
-      error ("chi2pdf: X and N must be of common size or scalar");
+      error ("chi2pdf: X and N must be of common size or scalars");
     endif
   endif
 
-  pdf = gampdf (x, n / 2, 2);
+  if (iscomplex (x) || iscomplex (n))
+    error ("chi2pdf: X and N must not be complex");
+  endif
+
+  pdf = gampdf (x, n/2, 2);
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 0.5 1 Inf];
+%! y = [0, 1/2 * exp(-x(2:5)/2)];
+%!assert(chi2pdf (x, 2*ones(1,5)), y);
+%!assert(chi2pdf (x, 2), y);
+%!assert(chi2pdf (x, 2*[1 0 NaN 1 1]), [y(1) NaN NaN y(4:5)]);
+%!assert(chi2pdf ([x, NaN], 2), [y, NaN]);
+
+%% Test class of input preserved
+%!assert(chi2pdf (single([x, NaN]), 2), single([y, NaN]));
+%!assert(chi2pdf ([x, NaN], single(2)), single([y, NaN]));
+
+%% Test input validation
+%!error chi2pdf ()
+%!error chi2pdf (1)
+%!error chi2pdf (1,2,3)
+%!error chi2pdf (ones(3),ones(2))
+%!error chi2pdf (ones(2),ones(3))
+%!error chi2pdf (i, 2)
+%!error chi2pdf (2, i)
+
--- a/scripts/statistics/distributions/chi2rnd.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/chi2rnd.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,75 +18,103 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} chi2rnd (@var{n}, @var{r}, @var{c})
-## @deftypefnx {Function File} {} chi2rnd (@var{n}, @var{sz})
-## Return an @var{r} by @var{c}  or a @code{size (@var{sz})} matrix of
-## random samples from the chisquare distribution with @var{n} degrees
-## of freedom.  @var{n} must be a scalar or of size @var{r} by @var{c}.
+## @deftypefn  {Function File} {} chi2rnd (@var{n})
+## @deftypefnx {Function File} {} chi2rnd (@var{n}, @var{r})
+## @deftypefnx {Function File} {} chi2rnd (@var{n}, @var{r}, @var{c}, @dots{})
+## @deftypefnx {Function File} {} chi2rnd (@var{n}, [@var{sz}])
+## Return a matrix of random samples from the chi-square distribution with
+## @var{n} degrees of freedom.
 ##
-## If @var{r} and @var{c} are omitted, the size of the result matrix is
-## the size of @var{n}.
+## When called with a single size argument, return a square matrix with
+## the dimension specified.  When called with more than one scalar argument the
+## first two arguments are taken as the number of rows and columns and any
+## further arguments specify additional matrix dimensions.  The size may also
+## be specified with a vector of dimensions @var{sz}.
+## 
+## If no size arguments are given then the result matrix is the size of
+## @var{n}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Random deviates from the chi-square distribution
 
-function rnd = chi2rnd (n, r, c)
-
-  if (nargin == 3)
-    if (! (isscalar (r) && (r > 0) && (r == round (r))))
-      error ("chi2rnd: R must be a positive integer");
-    endif
-    if (! (isscalar (c) && (c > 0) && (c == round (c))))
-      error ("chi2rnd: C must be a positive integer");
-    endif
-    sz = [r, c];
+function rnd = chi2rnd (n, varargin)
 
-    if (any (size (n) != 1)
-        && (length (size (n)) != length (sz) || any (size (n) != sz)))
-      error ("chi2rnd: N must be scalar or of size [R, C]");
-    endif
-  elseif (nargin == 2)
-    if (isscalar (r) && (r > 0))
-      sz = [r, r];
-    elseif (isvector(r) && all (r > 0))
-      sz = r(:)';
-    else
-      error ("chi2rnd: R must be a positive integer or vector");
-    endif
-
-    if (any (size (n) != 1)
-        && (length (size (n)) != length (sz) || any (size (n) != sz)))
-      error ("chi2rnd: N must be scalar or of size SZ");
-    endif
-  elseif (nargin == 1)
-    sz = size(n);
-  else
+  if (nargin < 1)
     print_usage ();
   endif
 
-  if (isscalar (n))
-     if (find (!(n > 0) | !(n < Inf)))
-       rnd = NaN (sz);
-     else
-       rnd = 2 * randg(n/2, sz);
-     endif
-  else
-    [retval, n, dummy] = common_size (n, ones (sz));
-    if (retval > 0)
-      error ("chi2rnd: a and b must be of common size or scalar");
+  if (nargin == 1)
+    sz = size (n);
+  elseif (nargin == 2)
+    if (isscalar (varargin{1}) && varargin{1} >= 0)
+      sz = [varargin{1}, varargin{1}];
+    elseif (isrow (varargin{1}) && all (varargin{1} >= 0))
+      sz = varargin{1};
+    else
+      error ("chi2rnd: dimension vector must be row vector of non-negative integers");
+    endif
+  elseif (nargin > 2)
+    if (any (cellfun (@(x) (!isscalar (x) || x < 0), varargin)))
+      error ("chi2rnd: dimensions must be non-negative integers");
     endif
+    sz = [varargin{:}];
+  endif
 
-    rnd = zeros (sz);
-    k = find (!(n > 0) | !(n < Inf));
-    if (any (k))
-      rnd(k) = NaN;
+  if (!isscalar (n) && !isequal (size (n), sz))
+    error ("chi2rnd: N must be scalar or of size SZ");
+  endif
+
+  if (iscomplex (n))
+    error ("chi2rnd: N must not be complex");
+  endif
+
+  if (isa (n, "single"))
+    cls = "single";
+  else
+    cls = "double";
+  endif
+
+  if (isscalar (n))
+    if ((n > 0) && (n < Inf))
+      rnd = 2 * randg (n/2, sz);
+      if (strcmp (cls, "single"))
+        rnd = single (rnd);
+      endif
+    else
+      rnd = NaN (sz, cls);
     endif
+  else
+    rnd = NaN (sz, cls);
 
-    k = find ((n > 0) & (n < Inf));
-    if (any (k))
-      rnd(k) = 2 * randg(n(k)/2, size(k));
-    endif
+    k = (n > 0) | (n < Inf);
+    rnd(k) = 2 * randg (n(k)/2);
   endif
 
 endfunction
+
+
+%!assert(size (chi2rnd (2)), [1, 1]);
+%!assert(size (chi2rnd (ones(2,1))), [2, 1]);
+%!assert(size (chi2rnd (ones(2,2))), [2, 2]);
+%!assert(size (chi2rnd (1, 3)), [3, 3]);
+%!assert(size (chi2rnd (1, [4 1])), [4, 1]);
+%!assert(size (chi2rnd (1, 4, 1)), [4, 1]);
+
+%% Test class of input preserved
+%!assert(class (chi2rnd (2)), "double");
+%!assert(class (chi2rnd (single(2))), "single");
+%!assert(class (chi2rnd (single([2 2]))), "single");
+
+%% Test input validation
+%!error chi2rnd ()
+%!error chi2rnd (ones(3),ones(2))
+%!error chi2rnd (ones(2),ones(3))
+%!error chi2rnd (i)
+%!error chi2rnd (1, -1)
+%!error chi2rnd (1, ones(2))
+%!error chi2rnd (1, [2 -1 2])
+%!error chi2rnd (ones(2,2), 3)
+%!error chi2rnd (ones(2,2), [3, 2])
+%!error chi2rnd (ones(2,2), 2, 3)
+
--- a/scripts/statistics/distributions/discrete_cdf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/discrete_cdf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 2010-2011 David Bateman
 ##
 ## This file is part of Octave.
@@ -29,28 +30,52 @@
     print_usage ();
   endif
 
-  sz = size (x);
-
   if (! isvector (v))
     error ("discrete_cdf: V must be a vector");
+  elseif (any (isnan (v)))
+    error ("discrete_cdf: V must not have any NaN elements");
   elseif (! isvector (p) || (length (p) != length (v)))
     error ("discrete_cdf: P must be a vector with length (V) elements");
   elseif (! (all (p >= 0) && any (p)))
-    error ("discrete_cdf: P must be a nonzero, nonnegative vector");
+    error ("discrete_cdf: P must be a nonzero, non-negative vector");
+  endif
+
+  p = p(:) / sum (p);   # Reshape and normalize probability vector
+
+  if (isa (x, "single") || isa (v, "single") || isa (p, "single"));
+    cdf = NaN (size (x), "single");
+  else
+    cdf = NaN (size (x));
   endif
 
-  n = numel (x);
-  m = length (v);
-  x = reshape (x, n, 1);
-  v = reshape (v, 1, m);
-  p = reshape (p / sum (p), m, 1);
-
-  cdf = NaN (sz);
-  k = find (!isnan (x));
-  if (any (k))
-    n = length (k);
-    [vs, vi] = sort (v);
-    cdf(k) = [0 ; cumsum(p(vi))](lookup (vs, x(k)) + 1);
-  endif
+  k = !isnan (x);
+  [vs, vi] = sort (v);
+  cdf(k) = [0 ; cumsum(p(vi))](lookup (vs, x(k)) + 1);
 
 endfunction
+
+
+%!shared x,v,p,y
+%! x = [-1 0.1 1.1 1.9 3];
+%! v = 0.1:0.2:1.9;
+%! p = 1/length(v) * ones(1, length(v));
+%! y = [0 0.1 0.6 1 1];
+%!assert(discrete_cdf ([x, NaN], v, p), [y, NaN], eps);
+
+%% Test class of input preserved
+%!assert(discrete_cdf (single([x, NaN]), v, p), single([y, NaN]), 2*eps("single"));
+%!assert(discrete_cdf ([x, NaN], single(v), p), single([y, NaN]), 2*eps("single"));
+%!assert(discrete_cdf ([x, NaN], v, single(p)), single([y, NaN]), 2*eps("single"));
+
+%% Test input validation
+%!error discrete_cdf ()
+%!error discrete_cdf (1)
+%!error discrete_cdf (1,2)
+%!error discrete_cdf (1,2,3,4)
+%!error discrete_cdf (1, ones(2), ones(2,1))
+%!error discrete_cdf (1, [1 ; NaN], ones(2,1))
+%!error discrete_cdf (1, ones(2,1), ones(1,1))
+%!error discrete_cdf (1, ones(2,1), [1 -1])
+%!error discrete_cdf (1, ones(2,1), [1 NaN])
+%!error discrete_cdf (1, ones(2,1), [0  0])
+
--- a/scripts/statistics/distributions/discrete_inv.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/discrete_inv.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1996-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -18,7 +19,7 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} discrete_inv (@var{x}, @var{v}, @var{p})
-## For each component of @var{x}, compute the quantile (the inverse of
+## For each element of @var{x}, compute the quantile (the inverse of
 ## the CDF) at @var{x} of the univariate distribution which assumes the
 ## values in @var{v} with probabilities @var{p}.
 ## @end deftypefn
@@ -32,35 +33,63 @@
     print_usage ();
   endif
 
-  sz = size (x);
-
   if (! isvector (v))
     error ("discrete_inv: V must be a vector");
   elseif (! isvector (p) || (length (p) != length (v)))
     error ("discrete_inv: P must be a vector with length (V) elements");
+  elseif (any (isnan (p)))
+    error ("discrete_rnd: P must not have any NaN elements");
   elseif (! (all (p >= 0) && any (p)))
-    error ("discrete_inv: P must be a nonzero, nonnegative vector");
+    error ("discrete_inv: P must be a nonzero, non-negative vector");
+  endif
+
+  if (isa (x, "single") || isa (v, "single") || isa (p, "single"));
+    inv = NaN (size (x), "single");
+  else
+    inv = NaN (size (x));
   endif
 
-  n = numel (x);
-  x = reshape (x, 1, n);
-  m = length (v);
-  [v, idx] = sort (v);
-  p = reshape (cumsum (p (idx) / sum (p)), m, 1);
-
-  inv = NaN (sz);
-  if (any (k = find (x == 0)))
-    inv(k) = -Inf;
-  endif
-  if (any (k = find (x == 1)))
-    inv(k) = v(m) * ones (size (k));
+  ## FIXME: This isn't elegant.  But cumsum and lookup together produce
+  ## different results when called with a single or a double.
+  if (isa (p, "single"));
+    p = double (p);
   endif
 
-  if (any (k = find ((x > 0) & (x < 1))))
-    n = length (k);
-    inv (k) = v(length (p) - lookup (sort (p,"descend"), x(k)) + 1);
-  endif
+  [v, idx] = sort (v);
+  p = cumsum (p(idx)(:)) / sum (p);  # Reshape and normalize probability vector
+
+  k = (x == 0);
+  inv(k) = v(1);
+
+  k = (x == 1);
+  inv(k) = v(end);
+
+  k = (x > 0) & (x < 1);
+  inv(k) = v(length (p) - lookup (sort (p, "descend"), x(k)) + 1);
 
 endfunction
 
 
+%!shared x,v,p,y
+%! x = [-1 0 0.1 0.5 1 2];
+%! v = 0.1:0.2:1.9;
+%! p = 1/length(v) * ones(1, length(v));
+%! y = [NaN v(1) v(1) v(end/2) v(end) NaN];
+%!assert(discrete_inv ([x, NaN], v, p), [y, NaN], eps);
+
+%% Test class of input preserved
+%!assert(discrete_inv (single([x, NaN]), v, p), single([y, NaN]), eps("single"));
+%!assert(discrete_inv ([x, NaN], single(v), p), single([y, NaN]), eps("single"));
+%!assert(discrete_inv ([x, NaN], v, single(p)), single([y, NaN]), eps("single"));
+
+%% Test input validation
+%!error discrete_inv ()
+%!error discrete_inv (1)
+%!error discrete_inv (1,2)
+%!error discrete_inv (1,2,3,4)
+%!error discrete_inv (1, ones(2), ones(2,1))
+%!error discrete_inv (1, ones(2,1), ones(1,1))
+%!error discrete_inv (1, ones(2,1), [1 NaN])
+%!error discrete_inv (1, ones(2,1), [1 -1])
+%!error discrete_inv (1, ones(2,1), [0  0])
+
--- a/scripts/statistics/distributions/discrete_pdf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/discrete_pdf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1996-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -24,7 +25,7 @@
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
-## Description: pDF of a discrete distribution
+## Description: PDF of a discrete distribution
 
 function pdf = discrete_pdf (x, v, p)
 
@@ -32,28 +33,53 @@
     print_usage ();
   endif
 
-  sz = size (x);
-
   if (! isvector (v))
     error ("discrete_pdf: V must be a vector");
+  elseif (any (isnan (v)))
+    error ("discrete_pdf: V must not have any NaN elements");
   elseif (! isvector (p) || (length (p) != length (v)))
     error ("discrete_pdf: P must be a vector with length (V) elements");
   elseif (! (all (p >= 0) && any (p)))
-    error ("discrete_pdf: P must be a nonzero, nonnegative vector");
+    error ("discrete_pdf: P must be a nonzero, non-negative vector");
+  endif
+
+  ## Reshape and normalize probability vector.  Values not in table get 0 prob.
+  p = [0 ; p(:)/sum(p)];   
+
+  if (isa (x, "single") || isa (v, "single") || isa (p, "single"))
+    pdf = NaN (size (x), "single");
+  else
+    pdf = NaN (size (x));
   endif
 
-  n = numel (x);
-  m = length (v);
-  x = reshape (x, n, 1);
-  v = reshape (v, 1, m);
-  p = reshape (p / sum (p), m, 1);
-
-  pdf = NaN (sz);
-  k = find (!isnan (x));
-  if (any (k))
-    n = length (k);
-    [vs, vi] = sort (v);
-    pdf (k) = p (vi(lookup (vs, x(k), 'm')));
-  endif
+  k = !isnan (x);
+  [vs, vi] = sort (v(:));
+  pdf(k) = p([0 ; vi](lookup (vs, x(k), 'm') + 1) + 1);
 
 endfunction
+
+
+%!shared x,v,p,y
+%! x = [-1 0.1 1.1 1.9 3];
+%! v = 0.1:0.2:1.9;
+%! p = 1/length(v) * ones(1, length(v));
+%! y = [0 0.1 0.1 0.1 0];
+%!assert(discrete_pdf ([x, NaN], v, p), [y, NaN], 5*eps);
+
+%% Test class of input preserved
+%!assert(discrete_pdf (single([x, NaN]), v, p), single([y, NaN]), 5*eps("single"));
+%!assert(discrete_pdf ([x, NaN], single(v), p), single([y, NaN]), 5*eps("single"));
+%!assert(discrete_pdf ([x, NaN], v, single(p)), single([y, NaN]), 5*eps("single"));
+
+%% Test input validation
+%!error discrete_pdf ()
+%!error discrete_pdf (1)
+%!error discrete_pdf (1,2)
+%!error discrete_pdf (1,2,3,4)
+%!error discrete_pdf (1, ones(2), ones(2,1))
+%!error discrete_pdf (1, [1 ; NaN], ones(2,1))
+%!error discrete_pdf (1, ones(2,1), ones(1,1))
+%!error discrete_pdf (1, ones(2,1), [1 -1])
+%!error discrete_pdf (1, ones(2,1), [1 NaN])
+%!error discrete_pdf (1, ones(2,1), [0  0])
+
--- a/scripts/statistics/distributions/discrete_rnd.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/discrete_rnd.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1996-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,51 +18,29 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} discrete_rnd (@var{n}, @var{v}, @var{p})
-## @deftypefnx {Function File} {} discrete_rnd (@var{v}, @var{p}, @var{r}, @var{c})
-## @deftypefnx {Function File} {} discrete_rnd (@var{v}, @var{p}, @var{sz})
-## Generate a row vector containing a random sample of size @var{n} from
-## the univariate distribution which assumes the values in @var{v} with
-## probabilities @var{p}.  @var{n} must be a scalar.
+## @deftypefn  {Function File} {} discrete_rnd (@var{v}, @var{p})
+## @deftypefnx {Function File} {} discrete_rnd (@var{v}, @var{p}, @var{r})
+## @deftypefnx {Function File} {} discrete_rnd (@var{v}, @var{p}, @var{r}, @var{c}, @dots{})
+## @deftypefnx {Function File} {} discrete_rnd (@var{v}, @var{p}, [@var{sz}])
+## Return a matrix of random samples from the univariate distribution which
+## assumes the values in @var{v} with probabilities @var{p}.
 ##
-## If @var{r} and @var{c} are given create a matrix with @var{r} rows and
-## @var{c} columns.  Or if @var{sz} is a vector, create a matrix of size
-## @var{sz}.
+## When called with a single size argument, return a square matrix with
+## the dimension specified.  When called with more than one scalar argument the
+## first two arguments are taken as the number of rows and columns and any
+## further arguments specify additional matrix dimensions.  The size may also
+## be specified with a vector of dimensions @var{sz}.
+## 
+## If no size arguments are given then the result matrix is the common size of
+## @var{v} and @var{p}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Random deviates from a discrete distribution
 
-function rnd = discrete_rnd (v, p, r, c)
+function rnd = discrete_rnd (v, p, varargin)
 
-  if (nargin == 4)
-    if (! (isscalar (r) && (r > 0) && (r == round (r))))
-      error ("discrete_rnd: R must be a positive integer");
-    endif
-    if (! (isscalar (c) && (c > 0) && (c == round (c))))
-      error ("discrete_rnd: C must be a positive integer");
-    endif
-    sz = [r, c];
-  elseif (nargin == 3)
-    ## A potential problem happens here if all args are scalar, as
-    ## we can't distiguish between the command syntax. Thankfully this
-    ## case doesn't make much sense. So we assume the first syntax
-    ## if the first arg is scalar
-
-    if (isscalar (v))
-      sz = [1, floor(v)];
-      v = p;
-      p = r;
-    else
-      if (isscalar (r) && (r > 0))
-        sz = [r, r];
-      elseif (isvector(r) && all (r > 0))
-        sz = r(:)';
-      else
-        error ("discrete_rnd: R must be a positive integer or vector");
-      endif
-    endif
-  else
+  if (nargin < 2)
     print_usage ();
   endif
 
@@ -69,9 +48,57 @@
     error ("discrete_rnd: V must be a vector");
   elseif (! isvector (p) || (length (p) != length (v)))
     error ("discrete_rnd: P must be a vector with length (V) elements");
+  elseif (any (isnan (p)))
+    error ("discrete_rnd: P must not have any NaN elements");
   elseif (! (all (p >= 0) && any (p)))
-    error ("discrete_rnd: P must be a nonzero, nonnegative vector");
+    error ("discrete_rnd: P must be a nonzero, non-negative vector");
+  endif
+
+  if (nargin == 2)
+    sz = size (v);
+  elseif (nargin == 3)
+    if (isscalar (varargin{1}) && varargin{1} >= 0)
+      sz = [varargin{1}, varargin{1}];
+    elseif (isrow (varargin{1}) && all (varargin{1} >= 0))
+      sz = varargin{1};
+    else
+      error ("discrete_rnd: dimension vector must be row vector of non-negative integers");
+    endif
+  elseif (nargin > 3)
+    if (any (cellfun (@(x) (!isscalar (x) || x < 0), varargin)))
+      error ("discrete_rnd: dimensions must be non-negative integers");
+    endif
+    sz = [varargin{:}];
   endif
 
-  rnd = v (lookup (cumsum (p (1 : end-1)) / sum(p), rand (sz)) + 1);
+  rnd = v(lookup (cumsum (p(1:end-1)) / sum (p), rand (sz)) + 1);
+  rnd = reshape (rnd, sz);
+
 endfunction
+
+
+%!assert(size (discrete_rnd (1:2, 1:2, 3)), [3, 3]);
+%!assert(size (discrete_rnd (1:2, 1:2, [4 1])), [4, 1]);
+%!assert(size (discrete_rnd (1:2, 1:2, 4, 1)), [4, 1]);
+
+%% Test class of input preserved
+%!assert(class (discrete_rnd (1:2, 1:2)), "double");
+%!assert(class (discrete_rnd (single(1:2), 1:2)), "single");
+## FIXME: Maybe this should work, maybe it shouldn't.
+#%!assert(class (discrete_rnd (1:2, single(1:2))), "single");
+
+%% Test input validation
+%!error discrete_rnd ()
+%!error discrete_rnd (1)
+%!error discrete_rnd (1:2,1:2, -1)
+%!error discrete_rnd (1:2,1:2, ones(2))
+%!error discrete_rnd (1:2,1:2, [2 -1 2])
+%!error discrete_rnd (1:2,1:2, 1, ones(2))
+%!error discrete_rnd (1:2,1:2, 1, -1)
+%% test v,p verification
+%!error discrete_rnd (1, ones(2), ones(2,1))
+%!error discrete_rnd (1, ones(2,1), ones(1,1))
+%!error discrete_rnd (1, ones(2,1), [1 -1])
+%!error discrete_rnd (1, ones(2,1), [1 NaN])
+%!error discrete_rnd (1, ones(2,1), [0  0])
+
--- a/scripts/statistics/distributions/empirical_cdf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/empirical_cdf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1996-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -36,6 +37,26 @@
     error ("empirical_cdf: DATA must be a vector");
   endif
 
-  cdf = discrete_cdf (x, data, ones (size (data)) / length (data));
+  cdf = discrete_cdf (x, data, ones (size (data)));
 
 endfunction
+
+
+%!shared x,v,y
+%! x = [-1 0.1 1.1 1.9 3];
+%! v = 0.1:0.2:1.9;
+%! y = [0 0.1 0.6 1 1];
+%!assert(empirical_cdf (x, v), y, eps);
+%!assert(empirical_cdf ([x(1) NaN x(3:5)], v), [0 NaN 0.6 1 1], eps);
+
+%% Test class of input preserved
+%!assert(empirical_cdf ([x, NaN], v), [y, NaN], eps);
+%!assert(empirical_cdf (single([x, NaN]), v), single([y, NaN]), eps);
+%!assert(empirical_cdf ([x, NaN], single(v)), single([y, NaN]), eps);
+
+%% Test input validation
+%!error empirical_cdf ()
+%!error empirical_cdf (1)
+%!error empirical_cdf (1,2,3)
+%!error empirical_cdf (1, ones(2))
+
--- a/scripts/statistics/distributions/empirical_inv.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/empirical_inv.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1996-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -36,6 +37,25 @@
     error ("empirical_inv: DATA must be a vector");
   endif
 
-  inv = discrete_inv (x, data, ones (size (data)) / length (data));
+  inv = discrete_inv (x, data, ones (size (data)));
 
 endfunction
+
+
+%!shared x,v,y
+%! x = [-1 0 0.1 0.5 1 2];
+%! v = 0.1:0.2:1.9;
+%! y = [NaN v(1) v(1) v(end/2) v(end) NaN];
+%!assert(empirical_inv (x, v), y, eps);
+
+%% Test class of input preserved
+%!assert(empirical_inv ([x, NaN], v), [y, NaN], eps);
+%!assert(empirical_inv (single([x, NaN]), v), single([y, NaN]), eps);
+%!assert(empirical_inv ([x, NaN], single(v)), single([y, NaN]), eps);
+
+%% Test input validation
+%!error empirical_inv ()
+%!error empirical_inv (1)
+%!error empirical_inv (1,2,3)
+%!error empirical_inv (1, ones(2))
+
--- a/scripts/statistics/distributions/empirical_pdf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/empirical_pdf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1996-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -36,6 +37,24 @@
     error ("empirical_pdf: DATA must be a vector");
   endif
 
-  pdf = discrete_pdf (x, data, ones (size (data)) / length (data));
+  pdf = discrete_pdf (x, data, ones (size (data)));
 
 endfunction
+
+
+%!shared x,v,y
+%! x = [-1 0.1 1.1 1.9 3];
+%! v = 0.1:0.2:1.9;
+%! y = [0 0.1 0.1 0.1 0];
+%!assert(empirical_pdf (x, v), y);
+
+%% Test class of input preserved
+%!assert(empirical_pdf (single(x), v), single (y));
+%!assert(empirical_pdf (x, single(v)), single (y));
+
+%% Test input validation
+%!error empirical_pdf ()
+%!error empirical_pdf (1)
+%!error empirical_pdf (1,2,3)
+%!error empirical_inv (1, ones(2))
+
--- a/scripts/statistics/distributions/empirical_rnd.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/empirical_rnd.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1996-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,29 +18,29 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} empirical_rnd (@var{n}, @var{data})
-## @deftypefnx {Function File} {} empirical_rnd (@var{data}, @var{r}, @var{c})
-## @deftypefnx {Function File} {} empirical_rnd (@var{data}, @var{sz})
-## Generate a bootstrap sample of size @var{n} from the empirical
-## distribution obtained from the univariate sample @var{data}.
+## @deftypefn  {Function File} {} empirical_rnd (@var{data})
+## @deftypefnx {Function File} {} empirical_rnd (@var{data}, @var{r})
+## @deftypefnx {Function File} {} empirical_rnd (@var{data}, @var{r}, @var{c}, @dots{})
+## @deftypefnx {Function File} {} empirical_rnd (@var{data}, [@var{sz}])
+## Return a matrix of random samples from the empirical distribution obtained
+## from the univariate sample @var{data}.
 ##
-## If @var{r} and @var{c} are given create a matrix with @var{r} rows and
-## @var{c} columns.  Or if @var{sz} is a vector, create a matrix of size
-## @var{sz}.
+## When called with a single size argument, return a square matrix with
+## the dimension specified.  When called with more than one scalar argument the
+## first two arguments are taken as the number of rows and columns and any
+## further arguments specify additional matrix dimensions.  The size may also
+## be specified with a vector of dimensions @var{sz}.
+## 
+## If no size arguments are given then the result matrix is a random ordering
+## of the sample @var{data}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Bootstrap samples from the empirical distribution
 
-function rnd = empirical_rnd (data, r, c)
+function rnd = empirical_rnd (data, varargin)
 
-  if (nargin == 2)
-    if (isscalar(data))
-      c = data;
-      data = r;
-      r = 1;
-    endif
-  elseif (nargin != 3)
+  if (nargin < 1)
     print_usage ();
   endif
 
@@ -47,6 +48,22 @@
     error ("empirical_rnd: DATA must be a vector");
   endif
 
-  rnd = discrete_rnd (data, ones (size (data)) / length (data), r, c);
+  rnd = discrete_rnd (data, ones (size (data)), varargin{:});
 
 endfunction
+
+
+%!assert(size (empirical_rnd (ones (3, 1))), [3, 1]);
+%!assert(size (empirical_rnd (1:2, [4 1])), [4, 1]);
+%!assert(size (empirical_rnd (1:2, 4, 1)), [4, 1]);
+
+%% Test class of input preserved
+%!assert(class (empirical_rnd (1:2, 1)), "double");
+%!assert(class (empirical_rnd (single(1:2), 1)), "single");
+
+%% Test input validation
+%!error empirical_rnd ()
+%!error empirical_rnd (ones(2), 1)
+%% test data verification
+%!error empirical_rnd (ones(2), 1, 1)
+
--- a/scripts/statistics/distributions/expcdf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/expcdf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -22,7 +23,7 @@
 ## function (CDF) at @var{x} of the exponential distribution with
 ## mean @var{lambda}.
 ##
-## The arguments can be of common size or scalar.
+## The arguments can be of common size or scalars.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
@@ -34,40 +35,57 @@
     print_usage ();
   endif
 
-  if (!isscalar (x) && !isscalar(lambda))
+  if (!isscalar (lambda))
     [retval, x, lambda] = common_size (x, lambda);
     if (retval > 0)
-      error ("expcdf: X and LAMBDA must be of common size or scalar");
+      error ("expcdf: X and LAMBDA must be of common size or scalars");
     endif
   endif
 
-  if (isscalar (x))
-    sz = size (lambda);
-  else
-    sz = size (x);
+  if (iscomplex (x) || iscomplex (lambda))
+    error ("expcdf: X and LAMBDA must not be complex");
   endif
 
-  cdf = zeros (sz);
-
-  k = find (isnan (x) | !(lambda > 0));
-  if (any (k))
-    cdf(k) = NaN;
+  if (isa (x, "single") || isa (lambda, "single"))
+    cdf = zeros (size (x), "single");
+  else
+    cdf = zeros (size (x));
   endif
 
-  k = find ((x == Inf) & (lambda > 0));
-  if (any (k))
-    cdf(k) = 1;
-  endif
+  k = isnan (x) | !(lambda > 0);
+  cdf(k) = NaN;
+
+  k = (x == Inf) & (lambda > 0);
+  cdf(k) = 1;
 
-  k = find ((x > 0) & (x < Inf) & (lambda > 0));
-  if (any (k))
-    if isscalar (lambda)
-      cdf (k) = 1 - exp (- x(k) ./ lambda);
-    elseif isscalar (x)
-      cdf (k) = 1 - exp (- x ./ lambda(k));
-    else
-      cdf (k) = 1 - exp (- x(k) ./ lambda(k));
-    endif
+  k = (x > 0) & (x < Inf) & (lambda > 0);
+  if isscalar (lambda)
+    cdf(k) = 1 - exp (- x(k) / lambda);
+  else
+    cdf(k) = 1 - exp (- x(k) ./ lambda(k));
   endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 0.5 1 Inf];
+%! y = [0, 1 - exp(-x(2:end)/2)];
+%!assert(expcdf (x, 2*ones(1,5)), y);
+%!assert(expcdf (x, 2), y);
+%!assert(expcdf (x, 2*[1 0 NaN 1 1]), [y(1) NaN NaN y(4:5)]);
+
+%% Test class of input preserved
+%!assert(expcdf ([x, NaN], 2), [y, NaN]);
+%!assert(expcdf (single([x, NaN]), 2), single([y, NaN]));
+%!assert(expcdf ([x, NaN], single(2)), single([y, NaN]));
+
+%% Test input validation
+%!error expcdf ()
+%!error expcdf (1)
+%!error expcdf (1,2,3)
+%!error expcdf (ones(3),ones(2))
+%!error expcdf (ones(2),ones(3))
+%!error expcdf (i, 2)
+%!error expcdf (2, i)
+
--- a/scripts/statistics/distributions/expinv.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/expinv.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -19,8 +20,7 @@
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} expinv (@var{x}, @var{lambda})
 ## For each element of @var{x}, compute the quantile (the inverse of the
-## CDF) at @var{x} of the exponential distribution with mean
-## @var{lambda}.
+## CDF) at @var{x} of the exponential distribution with mean @var{lambda}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
@@ -32,41 +32,64 @@
     print_usage ();
   endif
 
-  if (!isscalar (x) && !isscalar(lambda))
+  if (!isscalar (lambda))
     [retval, x, lambda] = common_size (x, lambda);
     if (retval > 0)
-      error ("expinv: X and LAMBDA must be of common size or scalar");
+      error ("expinv: X and LAMBDA must be of common size or scalars");
     endif
   endif
 
-  if (isscalar (x))
-    sz = size (lambda);
-  else
-    sz = size (x);
+  if (iscomplex (x) || iscomplex (lambda))
+    error ("expinv: X and LAMBDA must not be complex");
   endif
 
-  inv = zeros (sz);
+  if (!isscalar (x))
+    sz = size (x);
+  else
+    sz = size (lambda);
+  endif
 
-  k = find (!(lambda > 0) | (x < 0) | (x > 1) | isnan (x));
-  if (any (k))
-    inv(k) = NaN;
+  if (iscomplex (x) || iscomplex (lambda))
+    error ("expinv: X and LAMBDA must not be complex");
   endif
 
-  k = find ((x == 1) & (lambda > 0));
-  if (any (k))
-    inv(k) = Inf;
+  if (isa (x, "single") || isa (lambda, "single"))
+    inv = NaN (size (x), "single");
+  else
+    inv = NaN (size (x));
   endif
 
-  k = find ((x > 0) & (x < 1) & (lambda > 0));
-  if (any (k))
-    if isscalar (lambda)
-      inv(k) = - lambda .* log (1 - x(k));
-    elseif isscalar (x)
-      inv(k) = - lambda(k) .* log (1 - x);
-    else
-      inv(k) = - lambda(k) .* log (1 - x(k));
-    endif
+  k = (x == 1) & (lambda > 0);
+  inv(k) = Inf;
+
+  k = (x >= 0) & (x < 1) & (lambda > 0);
+  if isscalar (lambda)
+    inv(k) = - lambda * log (1 - x(k));
+  else
+    inv(k) = - lambda(k) .* log (1 - x(k));
   endif
 
 endfunction
 
+
+%!shared x
+%! x = [-1 0 0.3934693402873666 1 2];
+%!assert(expinv (x, 2*ones(1,5)), [NaN 0 1 Inf NaN], eps);
+%!assert(expinv (x, 2), [NaN 0 1 Inf NaN], eps);
+%!assert(expinv (x, 2*[1 0 NaN 1 1]), [NaN NaN NaN Inf NaN], eps);
+%!assert(expinv ([x(1:2) NaN x(4:5)], 2), [NaN 0 NaN Inf NaN], eps);
+
+%% Test class of input preserved
+%!assert(expinv ([x, NaN], 2), [NaN 0 1 Inf NaN NaN], eps);
+%!assert(expinv (single([x, NaN]), 2), single([NaN 0 1 Inf NaN NaN]), eps);
+%!assert(expinv ([x, NaN], single(2)), single([NaN 0 1 Inf NaN NaN]), eps);
+
+%% Test input validation
+%!error expinv ()
+%!error expinv (1)
+%!error expinv (1,2,3)
+%!error expinv (ones(3),ones(2))
+%!error expinv (ones(2),ones(3))
+%!error expinv (i, 2)
+%!error expinv (2, i)
+
--- a/scripts/statistics/distributions/exppdf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/exppdf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -19,7 +20,7 @@
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} exppdf (@var{x}, @var{lambda})
 ## For each element of @var{x}, compute the probability density function
-## (PDF) of the exponential distribution with mean @var{lambda}.
+## (PDF) at @var{x} of the exponential distribution with mean @var{lambda}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
@@ -31,34 +32,53 @@
     print_usage ();
   endif
 
-  if (!isscalar (x) && !isscalar(lambda))
+  if (!isscalar (lambda))
     [retval, x, lambda] = common_size (x, lambda);
     if (retval > 0)
-      error ("exppdf: X and LAMBDA must be of common size or scalar");
+      error ("exppdf: X and LAMBDA must be of common size or scalars");
     endif
   endif
 
-  if (isscalar (x))
-    sz = size (lambda);
-  else
-    sz = size (x);
-  endif
-  pdf = zeros (sz);
-
-  k = find (!(lambda > 0) | isnan (x));
-  if (any (k))
-    pdf(k) = NaN;
+  if (iscomplex (x) || iscomplex (lambda))
+    error ("exppdf: X and LAMBDA must not be complex");
   endif
 
-  k = find ((x >= 0) & (x < Inf) & (lambda > 0));
-  if (any (k))
-    if isscalar (lambda)
-      pdf(k) = exp (- x(k) ./ lambda) ./ lambda;
-    elseif isscalar (x)
-      pdf(k) = exp (- x ./ lambda(k)) ./ lambda(k);
-    else
-      pdf(k) = exp (- x(k) ./ lambda(k)) ./ lambda(k);
-    endif
+  if (isa (x, "single") || isa (lambda, "single"))
+    pdf = zeros (size (x), "single");
+  else
+    pdf = zeros (size (x));
+  endif
+
+  k = isnan (x) | !(lambda > 0);
+  pdf(k) = NaN;
+
+  k = (x >= 0) & (x < Inf) & (lambda > 0);
+  if isscalar (lambda)
+    pdf(k) = exp (- x(k) / lambda) / lambda;
+  else
+    pdf(k) = exp (- x(k) ./ lambda(k)) ./ lambda(k);
   endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 0.5 1 Inf];
+%! y = gampdf (x, 1, 2);
+%!assert(exppdf (x, 2*ones(1,5)), y);
+%!assert(exppdf (x, 2*[1 0 NaN 1 1]), [y(1) NaN NaN y(4:5)]);
+%!assert(exppdf ([x, NaN], 2), [y, NaN]);
+
+%% Test class of input preserved
+%!assert(exppdf (single([x, NaN]), 2), single([y, NaN]));
+%!assert(exppdf ([x, NaN], single(2)), single([y, NaN]));
+
+%% Test input validation
+%!error exppdf ()
+%!error exppdf (1)
+%!error exppdf (1,2,3)
+%!error exppdf (ones(3),ones(2))
+%!error exppdf (ones(2),ones(3))
+%!error exppdf (i, 2)
+%!error exppdf (2, i)
+
--- a/scripts/statistics/distributions/exprnd.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/exprnd.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,71 +18,100 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} exprnd (@var{lambda}, @var{r}, @var{c})
-## @deftypefnx {Function File} {} exprnd (@var{lambda}, @var{sz})
-## Return an @var{r} by @var{c} matrix of random samples from the
-## exponential distribution with mean @var{lambda}, which must be a
-## scalar or of size @var{r} by @var{c}.  Or if @var{sz} is a vector,
-## create a matrix of size @var{sz}.
+## @deftypefn  {Function File} {} exprnd (@var{lambda})
+## @deftypefnx {Function File} {} exprnd (@var{lambda}, @var{r})
+## @deftypefnx {Function File} {} exprnd (@var{lambda}, @var{r}, @var{c}, @dots{})
+## @deftypefnx {Function File} {} exprnd (@var{lambda}, [@var{sz}])
+## Return a matrix of random samples from the exponential distribution with
+## mean @var{lambda}.
 ##
-## If @var{r} and @var{c} are omitted, the size of the result matrix is
-## the size of @var{lambda}.
+## When called with a single size argument, return a square matrix with
+## the dimension specified.  When called with more than one scalar argument the
+## first two arguments are taken as the number of rows and columns and any
+## further arguments specify additional matrix dimensions.  The size may also
+## be specified with a vector of dimensions @var{sz}.
+## 
+## If no size arguments are given then the result matrix is the size of
+## @var{lambda}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Random deviates from the exponential distribution
 
-function rnd = exprnd (lambda, r, c)
-
-  if (nargin == 3)
-    if (! (isscalar (r) && (r > 0) && (r == round (r))))
-      error ("exprnd: R must be a positive integer");
-    endif
-    if (! (isscalar (c) && (c > 0) && (c == round (c))))
-      error ("exprnd: C must be a positive integer");
-    endif
-    sz = [r, c];
+function rnd = exprnd (lambda, varargin)
 
-    if (any (size (lambda) != 1)
-        && (length (size (lambda)) != length (sz) || any (size (lambda) != sz)))
-      error ("exprnd: LAMBDA must be scalar or of size [R, C]");
-    endif
-  elseif (nargin == 2)
-    if (isscalar (r) && (r > 0))
-      sz = [r, r];
-    elseif (isvector(r) && all (r > 0))
-      sz = r(:)';
-    else
-      error ("exprnd: R must be a positive integer or vector");
-    endif
-
-    if (any (size (lambda) != 1)
-        && ((length (size (lambda)) != length (sz)) || any (size (lambda) != sz)))
-      error ("exprnd: LAMBDA must be scalar or of size SZ");
-    endif
-  elseif (nargin == 1)
-    sz = size (lambda);
-  else
+  if (nargin < 1)
     print_usage ();
   endif
 
+  if (nargin == 1)
+    sz = size (lambda);
+  elseif (nargin == 2)
+    if (isscalar (varargin{1}) && varargin{1} >= 0)
+      sz = [varargin{1}, varargin{1}];
+    elseif (isrow (varargin{1}) && all (varargin{1} >= 0))
+      sz = varargin{1};
+    else
+      error ("exprnd: dimension vector must be row vector of non-negative integers");
+    endif
+  elseif (nargin > 2)
+    if (any (cellfun (@(x) (!isscalar (x) || x < 0), varargin)))
+      error ("exprnd: dimensions must be non-negative integers");
+    endif
+    sz = [varargin{:}];
+  endif
+
+  if (!isscalar (lambda) && !isequal (size (lambda), sz))
+    error ("exprnd: LAMBDA must be scalar or of size SZ");
+  endif
+
+  if (iscomplex (lambda))
+    error ("exprnd: LAMBDA must not be complex");
+  endif
+
+  if (isa (lambda, "single"))
+    cls = "single";
+  else
+    cls = "double";
+  endif
 
   if (isscalar (lambda))
     if ((lambda > 0) && (lambda < Inf))
-      rnd = rande(sz) * lambda;
+      rnd = rande (sz) * lambda;
     else
-      rnd = NaN (sz);
+      rnd = NaN (sz, cls);
     endif
   else
-    rnd = zeros (sz);
-    k = find (!(lambda > 0) | !(lambda < Inf));
-    if (any (k))
-      rnd(k) = NaN;
-    endif
-    k = find ((lambda > 0) & (lambda < Inf));
-    if (any (k))
-      rnd(k) = rande(size(k)) .* lambda(k);
-    endif
+    rnd = NaN (sz, cls);
+
+    k = (lambda > 0) & (lambda < Inf);
+    rnd(k) = rande (sum (k(:)), 1) .* lambda(k)(:);
   endif
 
 endfunction
+
+
+%!assert(size (exprnd (2)), [1, 1]);
+%!assert(size (exprnd (ones(2,1))), [2, 1]);
+%!assert(size (exprnd (ones(2,2))), [2, 2]);
+%!assert(size (exprnd (1, 3)), [3, 3]);
+%!assert(size (exprnd (1, [4 1])), [4, 1]);
+%!assert(size (exprnd (1, 4, 1)), [4, 1]);
+
+%% Test class of input preserved
+%!assert(class (exprnd (1)), "double");
+%!assert(class (exprnd (single(1))), "single");
+%!assert(class (exprnd (single([1 1]))), "single");
+
+%% Test input validation
+%!error exprnd ()
+%!error exprnd (1, -1)
+%!error exprnd (1, ones(2))
+%!error exprnd (i)
+%!error exprnd (1, [2 -1 2])
+%!error exprnd (1, 2, -1)
+%!error exprnd (1, 2, ones(2))
+%!error exprnd (ones(2,2), 3)
+%!error exprnd (ones(2,2), [3, 2])
+%!error exprnd (ones(2,2), 2, 3)
+
--- a/scripts/statistics/distributions/fcdf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/fcdf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -18,9 +19,9 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} fcdf (@var{x}, @var{m}, @var{n})
-## For each element of @var{x}, compute the CDF at @var{x} of the F
-## distribution with @var{m} and @var{n} degrees of freedom, i.e.,
-## PROB (F (@var{m}, @var{n}) @leq{} @var{x}).
+## For each element of @var{x}, compute the cumulative distribution function
+## (CDF) at @var{x} of the F distribution with @var{m} and @var{n} degrees of
+## freedom.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
@@ -35,31 +36,61 @@
   if (!isscalar (m) || !isscalar (n))
     [retval, x, m, n] = common_size (x, m, n);
     if (retval > 0)
-      error ("fcdf: X, M and N must be of common size or scalar");
+      error ("fcdf: X, M, and N must be of common size or scalars");
     endif
   endif
 
-  sz = size (x);
-  cdf = zeros (sz);
+  if (iscomplex (x) || iscomplex (m) || iscomplex (n))
+    error ("fcdf: X, M, and N must not be complex");
+  endif
 
-  k = find (!(m > 0) | !(n > 0) | isnan (x));
-  if (any (k))
-    cdf(k) = NaN;
+  if (isa (x, "single") || isa (m, "single") || isa (n, "single"))
+    cdf = zeros (size (x), "single");
+  else
+    cdf = zeros (size (x));
   endif
 
-  k = find ((x == Inf) & (m > 0) & (n > 0));
-  if (any (k))
-    cdf(k) = 1;
-  endif
+  k = isnan (x) | !(m > 0) | !(m < Inf) | !(n > 0) | !(n < Inf);
+  cdf(k) = NaN;
+
+  k = (x == Inf) & (m > 0) & (m < Inf) & (n > 0) & (n < Inf);
+  cdf(k) = 1;
 
-  k = find ((x > 0) & (x < Inf) & (m > 0) & (n > 0));
-  if (any (k))
-    if (isscalar (m) && isscalar (n))
-      cdf(k) = 1 - betainc (1 ./ (1 + m .* x(k) ./ n), n / 2, m / 2);
-    else
-      cdf(k) = 1 - betainc (1 ./ (1 + m(k) .* x(k) ./ n(k)), n(k) / 2,
-                            m(k) / 2);
-    endif
+  k = (x > 0) & (x < Inf) & (m > 0) & (m < Inf) & (n > 0) & (n < Inf);
+  if (isscalar (m) && isscalar (n))
+    cdf(k) = 1 - betainc (1 ./ (1 + m * x(k) / n), n/2, m/2);
+  else
+    cdf(k) = 1 - betainc (1 ./ (1 + m(k) .* x(k) ./ n(k)), n(k)/2, m(k)/2);
   endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 0.5 1 2 Inf];
+%! y = [0 0 1/3 1/2 2/3 1];
+%!assert(fcdf (x, 2*ones(1,6), 2*ones(1,6)), y, eps);
+%!assert(fcdf (x, 2, 2*ones(1,6)), y, eps);
+%!assert(fcdf (x, 2*ones(1,6), 2), y, eps);
+%!assert(fcdf (x, [0 NaN Inf 2 2 2], 2), [NaN NaN NaN y(4:6)], eps);
+%!assert(fcdf (x, 2, [0 NaN Inf 2 2 2]), [NaN NaN NaN y(4:6)], eps);
+%!assert(fcdf ([x(1:2) NaN x(4:6)], 2, 2), [y(1:2) NaN y(4:6)], eps);
+
+%% Test class of input preserved
+%!assert(fcdf ([x, NaN], 2, 2), [y, NaN], eps);
+%!assert(fcdf (single([x, NaN]), 2, 2), single([y, NaN]), eps("single"));
+%!assert(fcdf ([x, NaN], single(2), 2), single([y, NaN]), eps("single"));
+%!assert(fcdf ([x, NaN], 2, single(2)), single([y, NaN]), eps("single"));
+
+%% Test input validation
+%!error fcdf ()
+%!error fcdf (1)
+%!error fcdf (1,2)
+%!error fcdf (1,2,3,4)
+%!error fcdf (ones(3),ones(2),ones(2))
+%!error fcdf (ones(2),ones(3),ones(2))
+%!error fcdf (ones(2),ones(2),ones(3))
+%!error fcdf (i, 2, 2)
+%!error fcdf (2, i, 2)
+%!error fcdf (2, 2, i)
+
--- a/scripts/statistics/distributions/finv.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/finv.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -18,9 +19,9 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} finv (@var{x}, @var{m}, @var{n})
-## For each component of @var{x}, compute the quantile (the inverse of
-## the CDF) at @var{x} of the F distribution with parameters @var{m} and
-## @var{n}.
+## For each element of @var{x}, compute the quantile (the inverse of
+## the CDF) at @var{x} of the F distribution with @var{m} and @var{n}
+## degrees of freedom.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
@@ -35,31 +36,58 @@
   if (!isscalar (m) || !isscalar (n))
     [retval, x, m, n] = common_size (x, m, n);
     if (retval > 0)
-      error ("finv: X, M and N must be of common size or scalar");
+      error ("finv: X, M, and N must be of common size or scalars");
     endif
   endif
 
-  sz = size (x);
-  inv = zeros (sz);
+  if (iscomplex (x) || iscomplex (m) || iscomplex (n))
+    error ("finv: X, M, and N must not be complex");
+  endif
 
-  k = find ((x < 0) | (x > 1) | isnan (x) | !(m > 0) | !(n > 0));
-  if (any (k))
-    inv(k) = NaN;
+  if (isa (x, "single") || isa (m, "single") || isa (n, "single"))
+    inv = NaN (size (x), "single");
+  else
+    inv = NaN (size (x));
   endif
 
-  k = find ((x == 1) & (m > 0) & (n > 0));
-  if (any (k))
-    inv(k) = Inf;
-  endif
+  k = (x == 1) & (m > 0) & (m < Inf) & (n > 0) & (n < Inf);
+  inv(k) = Inf;
 
-  k = find ((x > 0) & (x < 1) & (m > 0) & (n > 0));
-  if (any (k))
-    if (isscalar (m) && isscalar (n))
-      inv(k) = ((1 ./ betainv (1 - x(k), n / 2, m / 2) - 1) .* n ./ m);
-    else
-      inv(k) = ((1 ./ betainv (1 - x(k), n(k) / 2, m(k) / 2) - 1)
-                .* n(k) ./ m(k));
-    endif
+  k = (x >= 0) & (x < 1) & (m > 0) & (m < Inf) & (n > 0) & (n < Inf);
+  if (isscalar (m) && isscalar (n))
+    inv(k) = ((1 ./ betainv (1 - x(k), n/2, m/2) - 1) * n / m);
+  else
+    inv(k) = ((1 ./ betainv (1 - x(k), n(k)/2, m(k)/2) - 1)
+              .* n(k) ./ m(k));
   endif
 
 endfunction
+
+
+%!shared x
+%! x = [-1 0 0.5 1 2];
+%!assert(finv (x, 2*ones(1,5), 2*ones(1,5)), [NaN 0 1 Inf NaN]);
+%!assert(finv (x, 2, 2*ones(1,5)), [NaN 0 1 Inf NaN]);
+%!assert(finv (x, 2*ones(1,5), 2), [NaN 0 1 Inf NaN]);
+%!assert(finv (x, [2 -Inf NaN Inf 2], 2), [NaN NaN NaN NaN NaN]);
+%!assert(finv (x, 2, [2 -Inf NaN Inf 2]), [NaN NaN NaN NaN NaN]);
+%!assert(finv ([x(1:2) NaN x(4:5)], 2, 2), [NaN 0 NaN Inf NaN]);
+
+%% Test class of input preserved
+%!assert(finv ([x, NaN], 2, 2), [NaN 0 1 Inf NaN NaN]);
+%!assert(finv (single([x, NaN]), 2, 2), single([NaN 0 1 Inf NaN NaN]));
+%!assert(finv ([x, NaN], single(2), 2), single([NaN 0 1 Inf NaN NaN]));
+%!assert(finv ([x, NaN], 2, single(2)), single([NaN 0 1 Inf NaN NaN]));
+
+%% Test input validation
+%!error finv ()
+%!error finv (1)
+%!error finv (1,2)
+%!error finv (1,2,3,4)
+%!error finv (ones(3),ones(2),ones(2))
+%!error finv (ones(2),ones(3),ones(2))
+%!error finv (ones(2),ones(2),ones(3))
+%!error finv (i, 2, 2)
+%!error finv (2, i, 2)
+%!error finv (2, 2, i)
+
--- a/scripts/statistics/distributions/fpdf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/fpdf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -35,31 +36,70 @@
   if (!isscalar (m) || !isscalar (n))
     [retval, x, m, n] = common_size (x, m, n);
     if (retval > 0)
-      error ("fpdf: X, M and N must be of common size or scalar");
+      error ("fpdf: X, M, and N must be of common size or scalars");
     endif
   endif
 
-  sz = size (x);
-  pdf = zeros (sz);
+  if (iscomplex (x) || iscomplex (m) || iscomplex (n))
+    error ("fpdf: X, M, and N must not be complex");
+  endif
 
-  k = find (isnan (x) | !(m > 0) | !(n > 0));
-  if (any (k))
-    pdf(k) = NaN;
+  if (isa (x, "single") || isa (m, "single") || isa (n, "single"))
+    pdf = zeros (size (x), "single");
+  else
+    pdf = zeros (size (x));
   endif
 
-  k = find ((x > 0) & (x < Inf) & (m > 0) & (n > 0));
-  if (any (k))
-    if (isscalar (m) && isscalar (n))
-      tmp = m / n * x(k);
-      pdf(k) = (exp ((m / 2 - 1) .* log (tmp)
-                     - ((m + n) / 2) .* log (1 + tmp))
-                .* (m / n) ./ beta (m / 2, n / 2));
-    else
-      tmp = m(k) .* x(k) ./ n(k);
-      pdf(k) = (exp ((m(k) / 2 - 1) .* log (tmp)
-                     - ((m(k) + n(k)) / 2) .* log (1 + tmp))
-                .* (m(k) ./ n(k)) ./ beta (m(k) / 2, n(k) / 2));
-    endif
+  k = isnan (x) | !(m > 0) | !(m < Inf) | !(n > 0) | !(n < Inf);
+  pdf(k) = NaN;
+
+  k = (x > 0) & (x < Inf) & (m > 0) & (m < Inf) & (n > 0) & (n < Inf);
+  if (isscalar (m) && isscalar (n))
+    tmp = m / n * x(k);
+    pdf(k) = (exp ((m/2 - 1) * log (tmp)
+                   - ((m + n) / 2) * log (1 + tmp))
+              * (m / n) ./ beta (m/2, n/2));
+  else
+    tmp = m(k) .* x(k) ./ n(k);
+    pdf(k) = (exp ((m(k)/2 - 1) .* log (tmp)
+                   - ((m(k) + n(k)) / 2) .* log (1 + tmp))
+              .* (m(k) ./ n(k)) ./ beta (m(k)/2, n(k)/2));
   endif
 
 endfunction
+
+
+%% F (x, 1, m) == T distribution (sqrt (x), m) / sqrt (x)
+%!test
+%! x = rand (10,1);
+%! x = x(x > 0.1 & x < 0.9);
+%! y = tpdf (sqrt (x), 2) ./ sqrt (x);
+%! assert(fpdf (x, 1, 2), y, 5*eps);
+
+%!shared x,y
+%! x = [-1 0 0.5 1 2];
+%! y = [0 0 4/9 1/4 1/9];
+%!assert(fpdf (x, 2*ones(1,5), 2*ones(1,5)), y, eps);
+%!assert(fpdf (x, 2, 2*ones(1,5)), y, eps);
+%!assert(fpdf (x, 2*ones(1,5), 2), y, eps);
+%!assert(fpdf (x, [0 NaN Inf 2 2], 2), [NaN NaN NaN y(4:5)], eps);
+%!assert(fpdf (x, 2, [0 NaN Inf 2 2]), [NaN NaN NaN y(4:5)], eps);
+%!assert(fpdf ([x, NaN], 2, 2), [y, NaN], eps);
+
+%% Test class of input preserved
+%!assert(fpdf (single([x, NaN]), 2, 2), single([y, NaN]), eps("single"));
+%!assert(fpdf ([x, NaN], single(2), 2), single([y, NaN]), eps("single"));
+%!assert(fpdf ([x, NaN], 2, single(2)), single([y, NaN]), eps("single"));
+
+%% Test input validation
+%!error fpdf ()
+%!error fpdf (1)
+%!error fpdf (1,2)
+%!error fpdf (1,2,3,4)
+%!error fpdf (ones(3),ones(2),ones(2))
+%!error fpdf (ones(2),ones(3),ones(2))
+%!error fpdf (ones(2),ones(2),ones(3))
+%!error fpdf (i, 2, 2)
+%!error fpdf (2, i, 2)
+%!error fpdf (2, 2, i)
+
--- a/scripts/statistics/distributions/frnd.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/frnd.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,103 +18,115 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} frnd (@var{m}, @var{n}, @var{r}, @var{c})
-## @deftypefnx {Function File} {} frnd (@var{m}, @var{n}, @var{sz})
-## Return an @var{r} by @var{c} matrix of random samples from the F
-## distribution with @var{m} and @var{n} degrees of freedom.  Both
-## @var{m} and @var{n} must be scalar or of size @var{r} by @var{c}.
-## If @var{sz} is a vector the random samples are in a matrix of
-## size @var{sz}.
+## @deftypefn  {Function File} {} frnd (@var{m}, @var{n})
+## @deftypefnx {Function File} {} frnd (@var{m}, @var{n}, @var{r})
+## @deftypefnx {Function File} {} frnd (@var{m}, @var{n}, @var{r}, @var{c}, @dots{})
+## @deftypefnx {Function File} {} frnd (@var{m}, @var{n}, [@var{sz}])
+## Return a matrix of random samples from the F distribution with
+## @var{m} and @var{n} degrees of freedom.
 ##
-## If @var{r} and @var{c} are omitted, the size of the result matrix is
-## the common size of @var{m} and @var{n}.
+## When called with a single size argument, return a square matrix with
+## the dimension specified.  When called with more than one scalar argument the
+## first two arguments are taken as the number of rows and columns and any
+## further arguments specify additional matrix dimensions.  The size may also
+## be specified with a vector of dimensions @var{sz}.
+## 
+## If no size arguments are given then the result matrix is the common size of
+## @var{m} and @var{n}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Random deviates from the F distribution
 
-function rnd = frnd (m, n, r, c)
+function rnd = frnd (m, n, varargin)
 
-  if (nargin > 1)
-    if (!isscalar(m) || !isscalar(n))
-      [retval, m, n] = common_size (m, n);
-      if (retval > 0)
-        error ("frnd: M and N must be of common size or scalar");
-      endif
+  if (nargin < 2)
+    print_usage ();
+  endif
+
+  if (!isscalar (m) || !isscalar (n))
+    [retval, m, n] = common_size (m, n);
+    if (retval > 0)
+      error ("frnd: M and N must be of common size or scalars");
     endif
   endif
 
-
-  if (nargin == 4)
-    if (! (isscalar (r) && (r > 0) && (r == round (r))))
-      error ("frnd: R must be a positive integer");
-    endif
-    if (! (isscalar (c) && (c > 0) && (c == round (c))))
-      error ("frnd: C must be a positive integer");
-    endif
-    sz = [r, c];
-
-    if (any (size (m) != 1)
-        && ((length (size (m)) != length (sz)) || any (size (m) != sz)))
-      error ("frnd: M and N must be scalar or of size [R,C]");
-    endif
-  elseif (nargin == 3)
-    if (isscalar (r) && (r > 0))
-      sz = [r, r];
-    elseif (isvector(r) && all (r > 0))
-      sz = r(:)';
-    else
-      error ("frnd: R must be a positive integer or vector");
-    endif
-
-    if (any (size (m) != 1)
-        && ((length (size (m)) != length (sz)) || any (size (m) != sz)))
-      error ("frnd: M and N must be scalar or of size SZ");
-    endif
-  elseif (nargin == 2)
-    sz = size(m);
-  else
-    print_usage ();
+  if (iscomplex (m) || iscomplex (n))
+    error ("frnd: M and N must not be complex");
   endif
 
+  if (nargin == 2)
+    sz = size (m);
+  elseif (nargin == 3)
+    if (isscalar (varargin{1}) && varargin{1} >= 0)
+      sz = [varargin{1}, varargin{1}];
+    elseif (isrow (varargin{1}) && all (varargin{1} >= 0))
+      sz = varargin{1};
+    else
+      error ("frnd: dimension vector must be row vector of non-negative integers");
+    endif
+  elseif (nargin > 3)
+    if (any (cellfun (@(x) (!isscalar (x) || x < 0), varargin)))
+      error ("frnd: dimensions must be non-negative integers");
+    endif
+    sz = [varargin{:}];
+  endif
+
+  if (!isscalar (m) && !isequal (size (m), sz))
+    error ("frnd: M and N must be scalar or of size SZ");
+  endif
+
+  if (isa (m, "single") || isa (n, "single"))
+    cls = "single";
+  else
+    cls = "double";
+  endif
 
   if (isscalar (m) && isscalar (n))
-    if (isinf (m) || isinf (n))
-      if (isinf (m))
-        rnd = ones (sz);
-      else
-        rnd = 2 ./ m .* randg(m / 2, sz);
-      endif
-      if (! isinf (n))
-        rnd = 0.5 .* n .* rnd ./ randg (n / 2, sz);
-      endif
-    elseif ((m > 0) && (m < Inf) && (n > 0) && (n < Inf))
-      rnd = n ./ m .* randg (m / 2, sz) ./ randg (n / 2, sz);
+    if ((m > 0) && (m < Inf) && (n > 0) && (n < Inf))
+      rnd = n/m * randg (m/2, sz) ./ randg (n/2, sz);
     else
-      rnd = NaN (sz);
+      rnd = NaN (sz, cls);
     endif
   else
-    rnd = zeros (sz);
-
-    k = find (isinf(m) | isinf(n));
-    if (any (k))
-      rnd (k) = 1;
-      k2 = find (!isinf(m) & isinf(n));
-      rnd (k2) = 2 ./ m(k2) .* randg (m(k2) ./ 2, size(k2));
-      k2 = find (isinf(m) & !isinf(n));
-      rnd (k2) = 0.5 .* n(k2) .* rnd(k2) ./ randg (n(k2) ./ 2, size(k2));
-    endif
+    rnd = NaN (sz, cls);
 
-    k = find (!(m > 0) | !(n > 0));
-    if (any (k))
-      rnd(k) = NaN;
-    endif
-
-    k = find ((m > 0) & (m < Inf) &
-              (n > 0) & (n < Inf));
-    if (any (k))
-      rnd(k) = n(k) ./ m(k) .* randg(m(k)./2,size(k)) ./ randg(n(k)./2,size(k));
-    endif
+    k = (m > 0) & (m < Inf) & (n > 0) & (n < Inf);
+    rnd(k) = n(k) ./ m(k) .* randg (m(k)/2) ./ randg (n(k)/2);
   endif
 
 endfunction
+
+
+%!assert(size (frnd (1,2)), [1, 1]);
+%!assert(size (frnd (ones(2,1), 2)), [2, 1]);
+%!assert(size (frnd (ones(2,2), 2)), [2, 2]);
+%!assert(size (frnd (1, 2*ones(2,1))), [2, 1]);
+%!assert(size (frnd (1, 2*ones(2,2))), [2, 2]);
+%!assert(size (frnd (1, 2, 3)), [3, 3]);
+%!assert(size (frnd (1, 2, [4 1])), [4, 1]);
+%!assert(size (frnd (1, 2, 4, 1)), [4, 1]);
+
+%% Test class of input preserved
+%!assert(class (frnd (1, 2)), "double");
+%!assert(class (frnd (single(1), 2)), "single");
+%!assert(class (frnd (single([1 1]), 2)), "single");
+%!assert(class (frnd (1, single(2))), "single");
+%!assert(class (frnd (1, single([2 2]))), "single");
+
+%% Test input validation
+%!error frnd ()
+%!error frnd (1)
+%!error frnd (ones(3),ones(2))
+%!error frnd (ones(2),ones(3))
+%!error frnd (i, 2)
+%!error frnd (2, i)
+%!error frnd (1,2, -1)
+%!error frnd (1,2, ones(2))
+%!error frnd (1, 2, [2 -1 2])
+%!error frnd (1,2, 1, ones(2))
+%!error frnd (1,2, 1, -1)
+%!error frnd (ones(2,2), 2, 3)
+%!error frnd (ones(2,2), 2, [3, 2])
+%!error frnd (ones(2,2), 2, 2, 3)
+
--- a/scripts/statistics/distributions/gamcdf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/gamcdf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -21,7 +22,6 @@
 ## For each element of @var{x}, compute the cumulative distribution
 ## function (CDF) at @var{x} of the Gamma distribution with parameters
 ## @var{a} and @var{b}.
-## @seealso{gamma, gammaln, gammainc, gampdf, gaminv, gamrnd}
 ## @end deftypefn
 
 ## Author: TT <Teresa.Twaroch@ci.tuwien.ac.at>
@@ -33,28 +33,59 @@
     print_usage ();
   endif
 
-  if (!isscalar (a) || !isscalar(b))
+  if (!isscalar (a) || !isscalar (b))
     [retval, x, a, b] = common_size (x, a, b);
     if (retval > 0)
-      error ("gamcdf: X, A and B must be of common size or scalars");
+      error ("gamcdf: X, A, and B must be of common size or scalars");
     endif
   endif
 
-  sz = size (x);
-  cdf = zeros (sz);
-
-  k = find (!(a > 0) | !(b > 0) | isnan (x));
-  if (any (k))
-    cdf (k) = NaN;
+  if (iscomplex (x) || iscomplex (a) || iscomplex (b))
+    error ("gamcdf: X, A, and B must not be complex");
   endif
 
-  k = find ((x > 0) & (a > 0) & (b > 0));
-  if (any (k))
-    if (isscalar (a) && isscalar(b))
-      cdf (k) = gammainc (x(k) ./ b, a);
-    else
-      cdf (k) = gammainc (x(k) ./ b(k), a(k));
-    endif
+  if (isa (x, "single") || isa (a, "single") || isa (b, "single"))
+    cdf = zeros (size (x), "single");
+  else
+    cdf = zeros (size (x));
+  endif
+
+  k = isnan (x) | !(a > 0) | !(a < Inf) | !(b > 0) | !(b < Inf);
+  cdf(k) = NaN;
+
+  k = (x > 0) & (a > 0) & (a < Inf) & (b > 0) & (b < Inf);
+  if (isscalar (a) && isscalar (b))
+    cdf(k) = gammainc (x(k) / b, a);
+  else
+    cdf(k) = gammainc (x(k) ./ b(k), a(k));
   endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 0.5 1 2 Inf];
+%! y = [0, gammainc(x(2:end), 1)];
+%!assert(gamcdf (x, ones(1,6), ones(1,6)), y);
+%!assert(gamcdf (x, 1, ones(1,6)), y);
+%!assert(gamcdf (x, ones(1,6), 1), y);
+%!assert(gamcdf (x, [0 -Inf NaN Inf 1 1], 1), [NaN NaN NaN NaN y(5:6)]);
+%!assert(gamcdf (x, 1, [0 -Inf NaN Inf 1 1]), [NaN NaN NaN NaN y(5:6)]);
+%!assert(gamcdf ([x(1:2) NaN x(4:6)], 1, 1), [y(1:2) NaN y(4:6)]);
+
+%% Test class of input preserved
+%!assert(gamcdf ([x, NaN], 1, 1), [y, NaN]);
+%!assert(gamcdf (single([x, NaN]), 1, 1), single([y, NaN]), eps("single"));
+
+%% Test input validation
+%!error gamcdf ()
+%!error gamcdf (1)
+%!error gamcdf (1,2)
+%!error gamcdf (1,2,3,4)
+%!error gamcdf (ones(3),ones(2),ones(2))
+%!error gamcdf (ones(2),ones(3),ones(2))
+%!error gamcdf (ones(2),ones(2),ones(3))
+%!error gamcdf (i, 2, 2)
+%!error gamcdf (2, i, 2)
+%!error gamcdf (2, 2, i)
+
--- a/scripts/statistics/distributions/gaminv.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/gaminv.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -18,10 +19,9 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} gaminv (@var{x}, @var{a}, @var{b})
-## For each component of @var{x}, compute the quantile (the inverse of
+## For each element of @var{x}, compute the quantile (the inverse of
 ## the CDF) at @var{x} of the Gamma distribution with parameters @var{a}
 ## and @var{b}.
-## @seealso{gamma, gammaln, gammainc, gampdf, gamcdf, gamrnd}
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
@@ -33,36 +33,40 @@
     print_usage ();
   endif
 
-  if (!isscalar (a) || !isscalar(b))
+  if (!isscalar (a) || !isscalar (b))
     [retval, x, a, b] = common_size (x, a, b);
     if (retval > 0)
-      error ("gaminv: X, A and B must be of common size or scalars");
+      error ("gaminv: X, A, and B must be of common size or scalars");
     endif
   endif
 
-  sz = size (x);
-  inv = zeros (sz);
+  if (iscomplex (x) || iscomplex (a) || iscomplex (b))
+    error ("gaminv: X, A, and B must not be complex");
+  endif
 
-  k = find ((x < 0) | (x > 1) | isnan (x) | !(a > 0) | !(b > 0));
-  if (any (k))
-    inv (k) = NaN;
+  if (isa (x, "single") || isa (a, "single") || isa (b, "single"))
+    inv = zeros (size (x), "single");
+  else
+    inv = zeros (size (x));
   endif
 
-  k = find ((x == 1) & (a > 0) & (b > 0));
-  if (any (k))
-    inv (k) = Inf;
-  endif
+  k = ((x < 0) | (x > 1) | isnan (x)
+       | !(a > 0) | !(a < Inf) | !(b > 0) | !(b < Inf));
+  inv(k) = NaN;
 
-  k = find ((x > 0) & (x < 1) & (a > 0) & (b > 0));
+  k = (x == 1) & (a > 0) & (a < Inf) & (b > 0) & (b < Inf);
+  inv(k) = Inf;
+
+  k = find ((x > 0) & (x < 1) & (a > 0) & (a < Inf) & (b > 0) & (b < Inf));
   if (any (k))
-    if (!isscalar(a) || !isscalar(b))
-      a = a (k);
-      b = b (k);
+    if (!isscalar (a) || !isscalar (b))
+      a = a(k);
+      b = b(k);
       y = a .* b;
     else
       y = a * b * ones (size (k));
     endif
-    x = x (k);
+    x = x(k);
 
     if (isa (x, "single"))
       myeps = eps ("single");
@@ -90,7 +94,36 @@
       y_old = y_new;
     endfor
 
-    inv (k) = y_new;
+    inv(k) = y_new;
   endif
 
 endfunction
+
+
+%!shared x
+%! x = [-1 0 0.63212055882855778 1 2];
+%!assert(gaminv (x, ones(1,5), ones(1,5)), [NaN 0 1 Inf NaN], eps);
+%!assert(gaminv (x, 1, ones(1,5)), [NaN 0 1 Inf NaN], eps);
+%!assert(gaminv (x, ones(1,5), 1), [NaN 0 1 Inf NaN], eps);
+%!assert(gaminv (x, [1 -Inf NaN Inf 1], 1), [NaN NaN NaN NaN NaN]);
+%!assert(gaminv (x, 1, [1 -Inf NaN Inf 1]), [NaN NaN NaN NaN NaN]);
+%!assert(gaminv ([x(1:2) NaN x(4:5)], 1, 1), [NaN 0 NaN Inf NaN]);
+
+%% Test class of input preserved
+%!assert(gaminv ([x, NaN], 1, 1), [NaN 0 1 Inf NaN NaN], eps);
+%!assert(gaminv (single([x, NaN]), 1, 1), single([NaN 0 1 Inf NaN NaN]), eps("single"));
+%!assert(gaminv ([x, NaN], single(1), 1), single([NaN 0 1 Inf NaN NaN]), eps("single"));
+%!assert(gaminv ([x, NaN], 1, single(1)), single([NaN 0 1 Inf NaN NaN]), eps("single"));
+
+%% Test input validation
+%!error gaminv ()
+%!error gaminv (1)
+%!error gaminv (1,2)
+%!error gaminv (1,2,3,4)
+%!error gaminv (ones(3),ones(2),ones(2))
+%!error gaminv (ones(2),ones(3),ones(2))
+%!error gaminv (ones(2),ones(2),ones(3))
+%!error gaminv (i, 2, 2)
+%!error gaminv (2, i, 2)
+%!error gaminv (2, 2, i)
+
--- a/scripts/statistics/distributions/gampdf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/gampdf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -21,7 +22,6 @@
 ## For each element of @var{x}, return the probability density function
 ## (PDF) at @var{x} of the Gamma distribution with parameters @var{a}
 ## and @var{b}.
-## @seealso{gamma, gammaln, gammainc, gamcdf, gaminv, gamrnd}
 ## @end deftypefn
 
 ## Author: TT <Teresa.Twaroch@ci.tuwien.ac.at>
@@ -33,41 +33,71 @@
     print_usage ();
   endif
 
-  if (!isscalar (a) || !isscalar(b))
+  if (!isscalar (a) || !isscalar (b))
     [retval, x, a, b] = common_size (x, a, b);
     if (retval > 0)
-      error ("gampdf: X, A and B must be of common size or scalars");
+      error ("gampdf: X, A, and B must be of common size or scalars");
     endif
   endif
 
-  sz = size(x);
-  pdf = zeros (sz);
+  if (iscomplex (x) || iscomplex (a) || iscomplex (b))
+    error ("gampdf: X, A, and B must not be complex");
+  endif
 
-  k = find (!(a > 0) | !(b > 0) | isnan (x));
-  if (any (k))
-    pdf (k) = NaN;
+  if (isa (x, "single") || isa (a, "single") || isa (b, "single"))
+    pdf = zeros (size (x), "single");
+  else
+    pdf = zeros (size (x));
   endif
 
-  k = find ((x >= 0) & (a > 0) & (a <= 1) & (b > 0));
-  if (any (k))
-    if (isscalar(a) && isscalar(b))
-      pdf(k) = (x(k) .^ (a - 1)) ...
-                .* exp(- x(k) ./ b) ./ gamma (a) ./ (b .^ a);
-    else
-      pdf(k) = (x(k) .^ (a(k) - 1)) ...
-                .* exp(- x(k) ./ b(k)) ./ gamma (a(k)) ./ (b(k) .^ a(k));
-    endif
+  k = !(a > 0) | !(b > 0) | isnan (x);
+  pdf(k) = NaN;
+
+  k = (x >= 0) & (a > 0) & (a <= 1) & (b > 0);
+  if (isscalar (a) && isscalar (b))
+    pdf(k) = (x(k) .^ (a - 1)) ...
+              .* exp (- x(k) / b) / gamma (a) / (b ^ a);
+  else
+    pdf(k) = (x(k) .^ (a(k) - 1)) ...
+              .* exp (- x(k) ./ b(k)) ./ gamma (a(k)) ./ (b(k) .^ a(k));
   endif
 
-  k = find ((x >= 0) & (a > 1) & (b > 0));
-  if (any (k))
-    if (isscalar(a) && isscalar(b))
-      pdf(k) = exp (- a .* log (b) + (a-1) .* log (x(k))
-                    - x(k) ./ b - gammaln (a));
-    else
-      pdf(k) = exp (- a(k) .* log (b(k)) + (a(k)-1) .* log (x(k))
-                    - x(k) ./ b(k) - gammaln (a(k)));
-    endif
+  k = (x >= 0) & (a > 1) & (b > 0);
+  if (isscalar (a) && isscalar (b))
+    pdf(k) = exp (- a * log (b) + (a-1) * log (x(k))
+                  - x(k) / b - gammaln (a));
+  else
+    pdf(k) = exp (- a(k) .* log (b(k)) + (a(k)-1) .* log (x(k))
+                  - x(k) ./ b(k) - gammaln (a(k)));
   endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 0.5 1 Inf];
+%! y = [0 exp(-x(2:end))];
+%!assert(gampdf (x, ones(1,5), ones(1,5)), y);
+%!assert(gampdf (x, 1, ones(1,5)), y);
+%!assert(gampdf (x, ones(1,5), 1), y);
+%!assert(gampdf (x, [0 -Inf NaN Inf 1], 1), [NaN NaN NaN NaN y(5)]);
+%!assert(gampdf (x, 1, [0 -Inf NaN Inf 1]), [NaN NaN NaN 0 y(5)]);
+%!assert(gampdf ([x, NaN], 1, 1), [y, NaN]);
+
+%% Test class of input preserved
+%!assert(gampdf (single([x, NaN]), 1, 1), single([y, NaN]));
+%!assert(gampdf ([x, NaN], single(1), 1), single([y, NaN]));
+%!assert(gampdf ([x, NaN], 1, single(1)), single([y, NaN]));
+
+%% Test input validation
+%!error gampdf ()
+%!error gampdf (1)
+%!error gampdf (1,2)
+%!error gampdf (1,2,3,4)
+%!error gampdf (ones(3),ones(2),ones(2))
+%!error gampdf (ones(2),ones(3),ones(2))
+%!error gampdf (ones(2),ones(2),ones(3))
+%!error gampdf (i, 2, 2)
+%!error gampdf (2, i, 2)
+%!error gampdf (2, 2, i)
+
--- a/scripts/statistics/distributions/gamrnd.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/gamrnd.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,81 +18,118 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} gamrnd (@var{a}, @var{b}, @var{r}, @var{c})
-## @deftypefnx {Function File} {} gamrnd (@var{a}, @var{b}, @var{sz})
-## Return an @var{r} by @var{c} or a @code{size (@var{sz})} matrix of
-## random samples from the Gamma distribution with parameters @var{a}
-## and @var{b}.  Both @var{a} and @var{b} must be scalar or of size
-## @var{r} by @var{c}.
+## @deftypefn  {Function File} {} gamrnd (@var{a}, @var{b})
+## @deftypefnx {Function File} {} gamrnd (@var{a}, @var{b}, @var{r})
+## @deftypefnx {Function File} {} gamrnd (@var{a}, @var{b}, @var{r}, @var{c}, @dots{})
+## @deftypefnx {Function File} {} gamrnd (@var{a}, @var{b}, [@var{sz}])
+## Return a matrix of random samples from the Gamma distribution with
+## parameters @var{a} and @var{b}.
 ##
-## If @var{r} and @var{c} are omitted, the size of the result matrix is
-## the common size of @var{a} and @var{b}.
-## @seealso{gamma, gammaln, gammainc, gampdf, gamcdf, gaminv}
+## When called with a single size argument, return a square matrix with
+## the dimension specified.  When called with more than one scalar argument the
+## first two arguments are taken as the number of rows and columns and any
+## further arguments specify additional matrix dimensions.  The size may also
+## be specified with a vector of dimensions @var{sz}.
+## 
+## If no size arguments are given then the result matrix is the common size of
+## @var{a} and @var{b}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Random deviates from the Gamma distribution
 
-function rnd = gamrnd (a, b, r, c)
+function rnd = gamrnd (a, b, varargin)
 
-  if (nargin > 1)
-    if (!isscalar(a) || !isscalar(b))
-      [retval, a, b] = common_size (a, b);
-      if (retval > 0)
-        error ("gamrnd: A and B must be of common size or scalar");
-      endif
+  if (nargin < 2)
+    print_usage ();
+  endif
+
+  if (!isscalar (a) || !isscalar (b))
+    [retval, a, b] = common_size (a, b);
+    if (retval > 0)
+      error ("gamrnd: A and B must be of common size or scalars");
     endif
   endif
 
-  if (nargin == 4)
-    if (! (isscalar (r) && (r > 0) && (r == round (r))))
-      error ("gamrnd: R must be a positive integer");
-    endif
-    if (! (isscalar (c) && (c > 0) && (c == round (c))))
-      error ("gamrnd: C must be a positive integer");
-    endif
-    sz = [r, c];
+  if (iscomplex (a) || iscomplex (b))
+    error ("gamrnd: A and B must not be complex");
+  endif
 
-    if (any (size (a) != 1)
-        && (length (size (a)) != length (sz) || any (size (a) != sz)))
-      error ("gamrnd: A and B must be scalar or of size [R, C]");
-    endif
+  if (nargin == 2)
+    sz = size (a);
   elseif (nargin == 3)
-    if (isscalar (r) && (r > 0))
-      sz = [r, r];
-    elseif (isvector(r) && all (r > 0))
-      sz = r(:)';
+    if (isscalar (varargin{1}) && varargin{1} >= 0)
+      sz = [varargin{1}, varargin{1}];
+    elseif (isrow (varargin{1}) && all (varargin{1} >= 0))
+      sz = varargin{1};
     else
-      error ("gamrnd: R must be a positive integer or vector");
+      error ("gamrnd: dimension vector must be row vector of non-negative integers");
     endif
-
-    if (any (size (a) != 1)
-        && (length (size (a)) != length (sz) || any (size (a) != sz)))
-      error ("gamrnd: A and B must be scalar or of size SZ");
+  elseif (nargin > 3)
+    if (any (cellfun (@(x) (!isscalar (x) || x < 0), varargin)))
+      error ("gamrnd: dimensions must be non-negative integers");
     endif
-  elseif (nargin == 2)
-    sz = size(a);
-  else
-    print_usage ();
+    sz = [varargin{:}];
   endif
 
-  rnd = zeros (sz);
+  if (!isscalar (a) && !isequal (size (a), sz))
+    error ("gamrnd: A and B must be scalar or of size SZ");
+  endif
 
-  if (isscalar (a) && isscalar(b))
-    if (find (!(a > 0) | !(a < Inf) | !(b > 0) | !(b < Inf)))
-      rnd = NaN (sz);
-    else
-      rnd = b .* randg(a, sz);
+  if (isa (a, "single") || isa (b, "single"))
+    cls = "single";
+  else
+    cls = "double";
+  endif
+
+  if (isscalar (a) && isscalar (b))
+    if ((a > 0) && (a < Inf) && (b > 0) && (b < Inf))
+      rnd = b * randg (a, sz);
+      if (strcmp (cls, "single"))
+        rnd = single (rnd);
+      endif
+    else 
+      rnd = NaN (sz, cls);
     endif
   else
-    k = find (!(a > 0) | !(a < Inf) | !(b > 0) | !(b < Inf));
-    if (any (k))
-      rnd(k) = NaN;
-    endif
-    k = find ((a > 0) & (a < Inf) & (b > 0) & (b < Inf));
-    if (any (k))
-      rnd(k) = b(k) .* randg(a(k), size(k));
-    endif
+    rnd = NaN (sz, cls);
+
+    k = (a > 0) & (a < Inf) & (b > 0) & (b < Inf);
+    rnd(k) = b(k) .* randg (a(k));
   endif
 
 endfunction
+
+
+%!assert(size (gamrnd (1,2)), [1, 1]);
+%!assert(size (gamrnd (ones(2,1), 2)), [2, 1]);
+%!assert(size (gamrnd (ones(2,2), 2)), [2, 2]);
+%!assert(size (gamrnd (1, 2*ones(2,1))), [2, 1]);
+%!assert(size (gamrnd (1, 2*ones(2,2))), [2, 2]);
+%!assert(size (gamrnd (1, 2, 3)), [3, 3]);
+%!assert(size (gamrnd (1, 2, [4 1])), [4, 1]);
+%!assert(size (gamrnd (1, 2, 4, 1)), [4, 1]);
+
+%% Test class of input preserved
+%!assert(class (gamrnd (1, 2)), "double");
+%!assert(class (gamrnd (single(1), 2)), "single");
+%!assert(class (gamrnd (single([1 1]), 2)), "single");
+%!assert(class (gamrnd (1, single(2))), "single");
+%!assert(class (gamrnd (1, single([2 2]))), "single");
+
+%% Test input validation
+%!error gamrnd ()
+%!error gamrnd (1)
+%!error gamrnd (ones(3),ones(2))
+%!error gamrnd (ones(2),ones(3))
+%!error gamrnd (i, 2)
+%!error gamrnd (2, i)
+%!error gamrnd (1,2, -1)
+%!error gamrnd (1,2, ones(2))
+%!error gamrnd (1, 2, [2 -1 2])
+%!error gamrnd (1,2, 1, ones(2))
+%!error gamrnd (1,2, 1, -1)
+%!error gamrnd (ones(2,2), 2, 3)
+%!error gamrnd (ones(2,2), 2, [3, 2])
+%!error gamrnd (ones(2,2), 2, 2, 3)
+
--- a/scripts/statistics/distributions/geocdf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/geocdf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -18,8 +19,8 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} geocdf (@var{x}, @var{p})
-## For each element of @var{x}, compute the CDF at @var{x} of the
-## geometric distribution with parameter @var{p}.
+## For each element of @var{x}, compute the cumulative distribution function
+## (CDF) at @var{x} of the geometric distribution with parameter @var{p}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
@@ -31,34 +32,58 @@
     print_usage ();
   endif
 
-  if (!isscalar (x) && !isscalar (p))
+  if (!isscalar (p))
     [retval, x, p] = common_size (x, p);
     if (retval > 0)
-      error ("geocdf: X and P must be of common size or scalar");
+      error ("geocdf: X and P must be of common size or scalars");
     endif
   endif
 
-  cdf = zeros (size (x));
+  if (iscomplex (x) || iscomplex (p))
+    error ("geocdf: X and P must not be complex");
+  endif
 
-  k = find (isnan (x) | !(p >= 0) | !(p <= 1));
-  if (any (k))
-    cdf(k) = NaN;
+  if (isa (x, "single") || isa (p, "single"))
+    cdf = zeros (size (x), "single");
+  else
+    cdf = zeros (size (x));
   endif
 
-  k = find ((x == Inf) & (p >= 0) & (p <= 1));
-  if (any (k))
-    cdf(k) = 1;
-  endif
+  k = isnan (x) | !(p >= 0) | !(p <= 1);
+  cdf(k) = NaN;
+
+  k = (x == Inf) & (p >= 0) & (p <= 1);
+  cdf(k) = 1;
 
-  k = find ((x >= 0) & (x < Inf) & (x == round (x)) & (p > 0) & (p <= 1));
-  if (any (k))
-    if (isscalar (x))
-      cdf(k) = 1 - ((1 - p(k)) .^ (x + 1));
-    elseif (isscalar (p))
-      cdf(k) = 1 - ((1 - p) .^ (x(k) + 1));
-    else
-      cdf(k) = 1 - ((1 - p(k)) .^ (x(k) + 1));
-    endif
+  k = (x >= 0) & (x < Inf) & (x == fix (x)) & (p > 0) & (p <= 1);
+  if (isscalar (p))
+    cdf(k) = 1 - ((1 - p) .^ (x(k) + 1));
+  else
+    cdf(k) = 1 - ((1 - p(k)) .^ (x(k) + 1));
   endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 1 Inf];
+%! y = [0 0.5 0.75 1];
+%!assert(geocdf (x, 0.5*ones(1,4)), y);
+%!assert(geocdf (x, 0.5), y);
+%!assert(geocdf (x, 0.5*[-1 NaN 4 1]), [NaN NaN NaN y(4)]);
+%!assert(geocdf ([x(1:2) NaN x(4)], 0.5), [y(1:2) NaN y(4)]);
+
+%% Test class of input preserved
+%!assert(geocdf ([x, NaN], 0.5), [y, NaN]);
+%!assert(geocdf (single([x, NaN]), 0.5), single([y, NaN]));
+%!assert(geocdf ([x, NaN], single(0.5)), single([y, NaN]));
+
+%% Test input validation
+%!error geocdf ()
+%!error geocdf (1)
+%!error geocdf (1,2,3)
+%!error geocdf (ones(3),ones(2))
+%!error geocdf (ones(2),ones(3))
+%!error geocdf (i, 2)
+%!error geocdf (2, i)
+
--- a/scripts/statistics/distributions/geoinv.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/geoinv.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -18,8 +19,8 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} geoinv (@var{x}, @var{p})
-## For each element of @var{x}, compute the quantile at @var{x} of the
-## geometric distribution with parameter @var{p}.
+## For each element of @var{x}, compute the quantile (the inverse of
+## the CDF) at @var{x} of the geometric distribution with parameter @var{p}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
@@ -31,34 +32,54 @@
     print_usage ();
   endif
 
-  if (!isscalar (x) && !isscalar (p))
+  if (!isscalar (p))
     [retval, x, p] = common_size (x, p);
     if (retval > 0)
-      error ("geoinv: X and P must be of common size or scalar");
+      error ("geoinv: X and P must be of common size or scalars");
     endif
   endif
 
-  inv = zeros (size (x));
-
-  k = find (!(x >= 0) | !(x <= 1) | !(p >= 0) | !(p <= 1));
-  if (any (k))
-    inv(k) = NaN;
+  if (iscomplex (x) || iscomplex (p))
+    error ("geoinv: X and P must not be complex");
   endif
 
-  k = find ((x == 1) & (p >= 0) & (p <= 1));
-  if (any (k))
-    inv(k) = Inf;
+  if (isa (x, "single") || isa (p, "single"))
+    inv = NaN (size (x), "single");
+  else
+    inv = NaN (size (x));
   endif
 
-  k = find ((x > 0) & (x < 1) & (p > 0) & (p <= 1));
-  if (any (k))
-    if (isscalar (x))
-      inv(k) = max (ceil (log (1 - x) ./ log (1 - p(k))) - 1, 0);
-    elseif (isscalar (p))
-      inv(k) = max (ceil (log (1 - x(k)) / log (1 - p)) - 1, 0);
-    else
-      inv(k) = max (ceil (log (1 - x(k)) ./ log (1 - p(k))) - 1, 0);
-    endif
+  k = (x == 1) & (p >= 0) & (p <= 1);
+  inv(k) = Inf;
+
+  k = (x >= 0) & (x < 1) & (p > 0) & (p <= 1);
+  if (isscalar (p))
+    inv(k) = max (ceil (log (1 - x(k)) / log (1 - p)) - 1, 0);
+  else
+    inv(k) = max (ceil (log (1 - x(k)) ./ log (1 - p(k))) - 1, 0);
   endif
 
 endfunction
+
+
+%!shared x
+%! x = [-1 0 0.75 1 2];
+%!assert(geoinv (x, 0.5*ones(1,5)), [NaN 0 1 Inf NaN]);
+%!assert(geoinv (x, 0.5), [NaN 0 1 Inf NaN]);
+%!assert(geoinv (x, 0.5*[1 -1 NaN 4 1]), [NaN NaN NaN NaN NaN]);
+%!assert(geoinv ([x(1:2) NaN x(4:5)], 0.5), [NaN 0 NaN Inf NaN]);
+
+%% Test class of input preserved
+%!assert(geoinv ([x, NaN], 0.5), [NaN 0 1 Inf NaN NaN]);
+%!assert(geoinv (single([x, NaN]), 0.5), single([NaN 0 1 Inf NaN NaN]));
+%!assert(geoinv ([x, NaN], single(0.5)), single([NaN 0 1 Inf NaN NaN]));
+
+%% Test input validation
+%!error geoinv ()
+%!error geoinv (1)
+%!error geoinv (1,2,3)
+%!error geoinv (ones(3),ones(2))
+%!error geoinv (ones(2),ones(3))
+%!error geoinv (i, 2)
+%!error geoinv (2, i)
+
--- a/scripts/statistics/distributions/geopdf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/geopdf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -31,35 +32,54 @@
     print_usage ();
   endif
 
-  if (!isscalar (x) && !isscalar (p))
+  if (!isscalar (p))
     [retval, x, p] = common_size (x, p);
     if (retval > 0)
-      error ("geopdf: X and P must be of common size or scalar");
+      error ("geopdf: X and P must be of common size or scalars");
     endif
   endif
 
-  pdf = zeros (size (x));
-
-  k = find (isnan (x) | !(p >= 0) | !(p <= 1));
-  if (any (k))
-    pdf(k) = NaN;
+  if (iscomplex (x) || iscomplex (p))
+    error ("geopdf: X and P must not be complex");
   endif
 
-  ## Just for the fun of it ...
-  k = find ((x == Inf) & (p == 0));
-  if (any (k))
-    pdf(k) = 1;
+  if (isa (x, "single") || isa (p, "single"))
+    pdf = zeros (size (x), "single");
+  else
+    pdf = zeros (size (x));
   endif
 
-  k = find ((x >= 0) & (x < Inf) & (x == round (x)) & (p > 0) & (p <= 1));
-  if (any (k))
-    if (isscalar (x))
-      pdf(k) = p(k) .* ((1 - p(k)) .^ x);
-    elseif (isscalar (p))
-      pdf(k) = p .* ((1 - p) .^ x(k));
-    else
-      pdf(k) = p(k) .* ((1 - p(k)) .^ x(k));
-    endif
+  k = isnan (x) | (x == Inf) | !(p >= 0) | !(p <= 1);
+  pdf(k) = NaN;
+
+  k = (x >= 0) & (x < Inf) & (x == fix (x)) & (p > 0) & (p <= 1);
+  if (isscalar (p))
+    pdf(k) = p * ((1 - p) .^ x(k));
+  else
+    pdf(k) = p(k) .* ((1 - p(k)) .^ x(k));
   endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 1 Inf];
+%! y = [0, 1/2, 1/4, NaN];
+%!assert(geopdf (x, 0.5*ones(1,4)), y);
+%!assert(geopdf (x, 0.5), y);
+%!assert(geopdf (x, 0.5*[-1 NaN 4 1]), [NaN NaN NaN y(4)]);
+%!assert(geopdf ([x, NaN], 0.5), [y, NaN]);
+
+%% Test class of input preserved
+%!assert(geopdf (single([x, NaN]), 0.5), single([y, NaN]), 5*eps("single"));
+%!assert(geopdf ([x, NaN], single(0.5)), single([y, NaN]), 5*eps("single"));
+
+%% Test input validation
+%!error geopdf ()
+%!error geopdf (1)
+%!error geopdf (1,2,3)
+%!error geopdf (ones(3),ones(2))
+%!error geopdf (ones(2),ones(3))
+%!error geopdf (i, 2)
+%!error geopdf (2, i)
+
--- a/scripts/statistics/distributions/geornd.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/geornd.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,77 +18,108 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} geornd (@var{p}, @var{r}, @var{c})
-## @deftypefnx {Function File} {} geornd (@var{p}, @var{sz})
-## Return an @var{r} by @var{c} matrix of random samples from the
-## geometric distribution with parameter @var{p}, which must be a scalar
-## or of size @var{r} by @var{c}.
+## @deftypefn  {Function File} {} geornd (@var{p})
+## @deftypefnx {Function File} {} geornd (@var{p}, @var{r})
+## @deftypefnx {Function File} {} geornd (@var{p}, @var{r}, @var{c}, @dots{})
+## @deftypefnx {Function File} {} geornd (@var{p}, [@var{sz}])
+## Return a matrix of random samples from the geometric distribution with
+## parameter @var{p}.
 ##
-## If @var{r} and @var{c} are given create a matrix with @var{r} rows and
-## @var{c} columns.  Or if @var{sz} is a vector, create a matrix of size
-## @var{sz}.
+## When called with a single size argument, return a square matrix with
+## the dimension specified.  When called with more than one scalar argument the
+## first two arguments are taken as the number of rows and columns and any
+## further arguments specify additional matrix dimensions.  The size may also
+## be specified with a vector of dimensions @var{sz}.
+## 
+## If no size arguments are given then the result matrix is the size of
+## @var{p}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Random deviates from the geometric distribution
 
-function rnd = geornd (p, r, c)
-
-  if (nargin == 3)
-    if (! (isscalar (r) && (r > 0) && (r == round (r))))
-      error ("geornd: R must be a positive integer");
-    endif
-    if (! (isscalar (c) && (c > 0) && (c == round (c))))
-      error ("geornd: C must be a positive integer");
-    endif
-    sz = [r, c];
+function rnd = geornd (p, varargin)
 
-    if (any (size (p) != 1)
-        && ((length (size (p)) != length (sz)) || any (size (p) != sz)))
-      error ("geornd: P must be scalar or of size [R, C]");
-    endif
-  elseif (nargin == 2)
-    if (isscalar (r) && (r > 0))
-      sz = [r, r];
-    elseif (isvector(r) && all (r > 0))
-      sz = r(:)';
-    else
-      error ("geornd: R must be a positive integer or vector");
-    endif
-
-    if (any (size (p) != 1)
-        && ((length (size (p)) != length (sz)) || any (size (p) != sz)))
-      error ("geornd: n must be scalar or of size SZ");
-    endif
-  elseif (nargin == 1)
-    sz = size(p);
-  elseif (nargin != 1)
+  if (nargin < 1)
     print_usage ();
   endif
 
+  if (nargin == 1)
+    sz = size (p);
+  elseif (nargin == 2)
+    if (isscalar (varargin{1}) && varargin{1} >= 0)
+      sz = [varargin{1}, varargin{1}];
+    elseif (isrow (varargin{1}) && all (varargin{1} >= 0))
+      sz = varargin{1};
+    else
+      error ("geornd: dimension vector must be row vector of non-negative integers");
+    endif
+  elseif (nargin > 2)
+    if (any (cellfun (@(x) (!isscalar (x) || x < 0), varargin)))
+      error ("geornd: dimensions must be non-negative integers");
+    endif
+    sz = [varargin{:}];
+  endif
+
+  if (!isscalar (p) && !isequal (size (p), sz))
+    error ("geornd: P must be scalar or of size SZ");
+  endif
+
+  if (iscomplex (p))
+    error ("geornd: P must not be complex");
+  endif
+
+  if (isa (p, "single"))
+    cls = "single";
+  else
+    cls = "double";
+  endif
 
   if (isscalar (p))
-    if (p < 0 || p > 1)
-      rnd = NaN (sz);
+    if (p > 0 && p < 1);
+      rnd = floor (- rande (sz) ./ log (1 - p));
     elseif (p == 0)
-      rnd = Inf (sz);
-    elseif (p > 0 && p < 1);
-      rnd = floor (- rande(sz) ./ log (1 - p));
-    else
-      rnd = zeros (sz);
+      rnd = Inf (sz, cls);
+    elseif (p == 1)
+      rnd = zeros (sz, cls);
+    elseif (p < 0 || p > 1)
+      rnd = NaN (sz, cls);
     endif
   else
-    rnd = floor (- rande(sz) ./ log (1 - p));
+    rnd = floor (- rande (sz) ./ log (1 - p));
 
-    k = find (!(p >= 0) | !(p <= 1));
-    if (any (k))
-      rnd(k) = NaN (1, length (k));
-    endif
+    k = !(p >= 0) | !(p <= 1);
+  rnd(k) = NaN;
 
-    k = find (p == 0);
-    if (any (k))
-      rnd(k) = Inf (1, length (k));
-    endif
+    k = (p == 0);
+    rnd(k) = Inf;
   endif
 
 endfunction
+
+
+%!assert(size (geornd (0.5)), [1, 1]);
+%!assert(size (geornd (0.5*ones(2,1))), [2, 1]);
+%!assert(size (geornd (0.5*ones(2,2))), [2, 2]);
+%!assert(size (geornd (0.5, 3)), [3, 3]);
+%!assert(size (geornd (0.5, [4 1])), [4, 1]);
+%!assert(size (geornd (0.5, 4, 1)), [4, 1]);
+
+%% Test class of input preserved
+%!assert(class (geornd (0.5)), "double");
+%!assert(class (geornd (single(0.5))), "single");
+%!assert(class (geornd (single([0.5 0.5]))), "single");
+%!assert(class (geornd (single(0))), "single");
+%!assert(class (geornd (single(1))), "single");
+
+%% Test input validation
+%!error geornd ()
+%!error geornd (ones(3),ones(2))
+%!error geornd (ones(2),ones(3))
+%!error geornd (i)
+%!error geornd (1, -1)
+%!error geornd (1, ones(2))
+%!error geornd (1, [2 -1 2])
+%!error geornd (ones(2,2), 2, 3)
+%!error geornd (ones(2,2), 3, 2)
+
--- a/scripts/statistics/distributions/hygecdf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/hygecdf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1997-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -25,7 +26,7 @@
 ## replacement from a population of total size @var{t} containing
 ## @var{m} marked items.
 ##
-## The parameters @var{t}, @var{m}, and @var{n} must positive integers
+## The parameters @var{t}, @var{m}, and @var{n} must be positive integers
 ## with @var{m} and @var{n} not greater than @var{t}.
 ## @end deftypefn
 
@@ -39,14 +40,70 @@
   endif
 
   if (!isscalar (t) || !isscalar (m) || !isscalar (n))
-    error ("hygecdf: T, M and N must all be positive integers");
+    [retval, x, t, m, n] = common_size (x, t, m, n);
+    if (retval > 0)
+      error ("hygecdf: X, T, M, and N must be of common size or scalars");
+    endif
+  endif
+
+  if (iscomplex (x) || iscomplex (t) || iscomplex (m) || iscomplex (n))
+    error ("hygecdf: X, T, M, and N must not be complex");
   endif
 
-  if (t < 0 || m < 0 || n <= 0 || t != round (t) || m != round (m)
-      || n != round (n) || m > t || n > t)
+  if (isa (x, "single") || isa (t, "single") || isa (m, "single") || isa (n, "single"))
+    cdf = NaN (size (x), "single");
+  else
     cdf = NaN (size (x));
+  endif
+
+  ok = ((t >= 0) & (m >= 0) & (n > 0) & (m <= t) & (n <= t) &
+        (t == fix (t)) & (m == fix (m)) & (n == fix (n)));
+
+  if (isscalar (t))
+    if (ok)
+      cdf = discrete_cdf (x, 0 : n, hygepdf (0 : n, t, m, n));
+    endif
   else
-    cdf = discrete_cdf (x, 0 : n, hygepdf (0 : n, t, m, n));
+    for i = find (ok(:)')  # Must be row vector arg to for loop
+      v = 0 : n(i);
+      cdf(i) = discrete_cdf (x(i), v, hygepdf (v, t(i), m(i), n(i)));
+    endfor
   endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 1 2 3];
+%! y = [0 1/6 5/6 1 1];
+%!assert(hygecdf (x, 4*ones(1,5), 2, 2), y, eps);
+%!assert(hygecdf (x, 4, 2*ones(1,5), 2), y, eps);
+%!assert(hygecdf (x, 4, 2, 2*ones(1,5)), y, eps);
+%!assert(hygecdf (x, 4*[1 -1 NaN 1.1 1], 2, 2), [y(1) NaN NaN NaN y(5)], eps);
+%!assert(hygecdf (x, 4, 2*[1 -1 NaN 1.1 1], 2), [y(1) NaN NaN NaN y(5)], eps);
+%!assert(hygecdf (x, 4, 5, 2), [NaN NaN NaN NaN NaN]);
+%!assert(hygecdf (x, 4, 2, 2*[1 -1 NaN 1.1 1]), [y(1) NaN NaN NaN y(5)], eps);
+%!assert(hygecdf (x, 4, 2, 5), [NaN NaN NaN NaN NaN]);
+%!assert(hygecdf ([x(1:2) NaN x(4:5)], 4, 2, 2), [y(1:2) NaN y(4:5)], eps);
+
+%% Test class of input preserved
+%!assert(hygecdf ([x, NaN], 4, 2, 2), [y, NaN], eps);
+%!assert(hygecdf (single([x, NaN]), 4, 2, 2), single([y, NaN]), eps("single"));
+%!assert(hygecdf ([x, NaN], single(4), 2, 2), single([y, NaN]), eps("single"));
+%!assert(hygecdf ([x, NaN], 4, single(2), 2), single([y, NaN]), eps("single"));
+%!assert(hygecdf ([x, NaN], 4, 2, single(2)), single([y, NaN]), eps("single"));
+
+%% Test input validation
+%!error hygecdf ()
+%!error hygecdf (1)
+%!error hygecdf (1,2)
+%!error hygecdf (1,2,3)
+%!error hygecdf (1,2,3,4,5)
+%!error hygecdf (ones(2), ones(3), 1, 1)
+%!error hygecdf (1, ones(2), ones(3), 1)
+%!error hygecdf (1, 1, ones(2), ones(3))
+%!error hygecdf (i, 2, 2, 2)
+%!error hygecdf (2, i, 2, 2)
+%!error hygecdf (2, 2, i, 2)
+%!error hygecdf (2, 2, 2, i)
+
--- a/scripts/statistics/distributions/hygeinv.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/hygeinv.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1997-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -18,11 +19,14 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} hygeinv (@var{x}, @var{t}, @var{m}, @var{n})
-## For each element of @var{x}, compute the quantile at @var{x} of the
-## hypergeometric distribution with parameters @var{t}, @var{m}, and
-## @var{n}.
+## For each element of @var{x}, compute the quantile (the inverse of
+## the CDF) at @var{x} of the hypergeometric distribution with parameters
+## @var{t}, @var{m}, and @var{n}.  This is the probability of obtaining @var{x}
+## marked items when randomly drawing a sample of size @var{n} without
+## replacement from a population of total size @var{t} containing @var{m}
+## marked items.
 ##
-## The parameters @var{t}, @var{m}, and @var{n} must positive integers
+## The parameters @var{t}, @var{m}, and @var{n} must be positive integers
 ## with @var{m} and @var{n} not greater than @var{t}.
 ## @end deftypefn
 
@@ -36,14 +40,75 @@
   endif
 
   if (!isscalar (t) || !isscalar (m) || !isscalar (n))
-    error ("hygeinv: T, M and N must all be positive integers");
+    [retval, x, t, m, n] = common_size (x, t, m, n);
+    if (retval > 0)
+      error ("hygeinv: X, T, M, and N must be of common size or scalars");
+    endif
+  endif
+
+  if (iscomplex (x) || iscomplex (t) || iscomplex (m) || iscomplex (n))
+    error ("hygeinv: X, T, M, and N must not be complex");
+  endif
+
+  if (isa (x, "single") || isa (t, "single") || isa (m, "single") || isa (n, "single"))
+    inv = NaN (size (x), "single");
+  else
+    inv = NaN (size (x));
   endif
 
-  if (t < 0 || m < 0 || n <= 0 || t != round (t) || m != round (m)
-      || n != round (n) || m > t || n > t)
-    inv = NaN (size (x));
+  ok = ((t >= 0) & (m >= 0) & (n > 0) & (m <= t) & (n <= t) &
+        (t == fix (t)) & (m == fix (m)) & (n == fix (n)));
+
+  if (isscalar (t))
+    if (ok)
+      inv = discrete_inv (x, 0 : n, hygepdf (0 : n, t, m, n));
+      inv(x == 0) = 0;  # Hack to return correct value for start of distribution
+    endif
   else
-    inv = discrete_inv (x, 0 : n, hygepdf (0 : n, t, m, n));
+    for i = find (ok(:)')  # Must be row vector arg to for loop
+      v = 0 : n(i);
+      if (x(i) == 0)
+        inv(i) = 0;  # Hack to return correct value for start of distribution
+      else
+        inv(i) = discrete_inv (x(i), v, hygepdf (v, t(i), m(i), n(i)));
+      endif
+    endfor
   endif
 
 endfunction
+
+
+%!shared x
+%! x = [-1 0 0.5 1 2];
+%!assert(hygeinv (x, 4*ones(1,5), 2*ones(1,5), 2*ones(1,5)), [NaN 0 1 2 NaN]);
+%!assert(hygeinv (x, 4*ones(1,5), 2, 2), [NaN 0 1 2 NaN]);
+%!assert(hygeinv (x, 4, 2*ones(1,5), 2), [NaN 0 1 2 NaN]);
+%!assert(hygeinv (x, 4, 2, 2*ones(1,5)), [NaN 0 1 2 NaN]);
+%!assert(hygeinv (x, 4*[1 -1 NaN 1.1 1], 2, 2), [NaN NaN NaN NaN NaN]);
+%!assert(hygeinv (x, 4, 2*[1 -1 NaN 1.1 1], 2), [NaN NaN NaN NaN NaN]);
+%!assert(hygeinv (x, 4, 5, 2), [NaN NaN NaN NaN NaN]);
+%!assert(hygeinv (x, 4, 2, 2*[1 -1 NaN 1.1 1]), [NaN NaN NaN NaN NaN]);
+%!assert(hygeinv (x, 4, 2, 5), [NaN NaN NaN NaN NaN]);
+%!assert(hygeinv ([x(1:2) NaN x(4:5)], 4, 2, 2), [NaN 0 NaN 2 NaN]);
+
+%% Test class of input preserved
+%!assert(hygeinv ([x, NaN], 4, 2, 2), [NaN 0 1 2 NaN NaN]);
+%!assert(hygeinv (single([x, NaN]), 4, 2, 2), single([NaN 0 1 2 NaN NaN]));
+%!assert(hygeinv ([x, NaN], single(4), 2, 2), single([NaN 0 1 2 NaN NaN]));
+%!assert(hygeinv ([x, NaN], 4, single(2), 2), single([NaN 0 1 2 NaN NaN]));
+%!assert(hygeinv ([x, NaN], 4, 2, single(2)), single([NaN 0 1 2 NaN NaN]));
+
+%% Test input validation
+%!error hygeinv ()
+%!error hygeinv (1)
+%!error hygeinv (1,2)
+%!error hygeinv (1,2,3)
+%!error hygeinv (1,2,3,4,5)
+%!error hygeinv (ones(2), ones(3), 1, 1)
+%!error hygeinv (1, ones(2), ones(3), 1)
+%!error hygeinv (1, 1, ones(2), ones(3))
+%!error hygeinv (i, 2, 2, 2)
+%!error hygeinv (2, i, 2, 2)
+%!error hygeinv (2, 2, i, 2)
+%!error hygeinv (2, 2, 2, i)
+
--- a/scripts/statistics/distributions/hygepdf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/hygepdf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1996-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -24,7 +25,8 @@
 ## when randomly drawing a sample of size @var{n} without replacement
 ## from a population of total size @var{t} containing @var{m} marked items.
 ##
-## The arguments must be of common size or scalar.
+## The parameters @var{t}, @var{m}, and @var{n} must be positive integers
+## with @var{m} and @var{n} not greater than @var{t}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
@@ -39,34 +41,72 @@
   if (!isscalar (t) || !isscalar (m) || !isscalar (n))
     [retval, x, t, m, n] = common_size (x, t, m, n);
     if (retval > 0)
-      error ("hygepdf: X, T, M, and N must be of common size or scalar");
+      error ("hygepdf: X, T, M, and N must be of common size or scalars");
     endif
   endif
 
-  pdf = zeros (size (x));
+  if (iscomplex (x) || iscomplex (t) || iscomplex (m) || iscomplex (n))
+    error ("hygepdf: X, T, M, and N must not be complex");
+  endif
+
+  if (isa (x, "single") || isa (t, "single") || isa (m, "single") || isa (n, "single"))
+    pdf = zeros (size (x), "single");
+  else
+    pdf = zeros (size (x));
+  endif
 
-  ## everything in i1 gives NaN
-  i1 = ((t < 0) | (m < 0) | (n <= 0) | (t != round (t)) |
-        (m != round (m)) | (n != round (n)) | (m > t) | (n > t));
-  ## everything in i2 gives 0 unless in i1
-  i2 = ((x != round (x)) | (x < 0) | (x > m) | (n < x) | (n-x > t-m));
-  k = find (i1);
-  if (any (k))
+  ## everything in nel gives NaN
+  nel = (isnan (x) | (t < 0) | (m < 0) | (n <= 0) | (m > t) | (n > t) |
+        (t != fix (t)) | (m != fix (m)) | (n != fix (n)));
+  ## everything in zel gives 0 unless in nel
+  zel = ((x != fix (x)) | (x < 0) | (x > m) | (n < x) | (n-x > t-m));
+
+  pdf(nel) = NaN;
+
+  k = !nel & !zel;
+  if (any (k(:)))
     if (isscalar (t) && isscalar (m) && isscalar (n))
-      pdf = NaN (size (x));
+      pdf(k) = (bincoeff (m, x(k)) .* bincoeff (t-m, n-x(k))
+                / bincoeff (t, n));
     else
-      pdf (k) = NaN;
-    endif
-  endif
-  k = find (!i1 & !i2);
-  if (any (k))
-    if (isscalar (t) && isscalar (m) && isscalar (n))
-      pdf (k) = (bincoeff (m, x(k)) .* bincoeff (t-m, n-x(k))
-                 / bincoeff (t, n));
-    else
-      pdf (k) = (bincoeff (m(k), x(k)) .* bincoeff (t(k)-m(k), n(k)-x(k))
-                 ./ bincoeff (t(k), n(k)));
+      pdf(k) = (bincoeff (m(k), x(k)) .* bincoeff (t(k)-m(k), n(k)-x(k))
+                ./ bincoeff (t(k), n(k)));
     endif
   endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 1 2 3];
+%! y = [0 1/6 4/6 1/6 0];
+%!assert(hygepdf (x, 4*ones(1,5), 2, 2), y);
+%!assert(hygepdf (x, 4, 2*ones(1,5), 2), y);
+%!assert(hygepdf (x, 4, 2, 2*ones(1,5)), y);
+%!assert(hygepdf (x, 4*[1 -1 NaN 1.1 1], 2, 2), [0 NaN NaN NaN 0]);
+%!assert(hygepdf (x, 4, 2*[1 -1 NaN 1.1 1], 2), [0 NaN NaN NaN 0]);
+%!assert(hygepdf (x, 4, 5, 2), [NaN NaN NaN NaN NaN]);
+%!assert(hygepdf (x, 4, 2, 2*[1 -1 NaN 1.1 1]), [0 NaN NaN NaN 0]);
+%!assert(hygepdf (x, 4, 2, 5), [NaN NaN NaN NaN NaN]);
+%!assert(hygepdf ([x, NaN], 4, 2, 2), [y, NaN], eps);
+
+%% Test class of input preserved
+%!assert(hygepdf (single([x, NaN]), 4, 2, 2), single([y, NaN]));
+%!assert(hygepdf ([x, NaN], single(4), 2, 2), single([y, NaN]));
+%!assert(hygepdf ([x, NaN], 4, single(2), 2), single([y, NaN]));
+%!assert(hygepdf ([x, NaN], 4, 2, single(2)), single([y, NaN]));
+
+%% Test input validation
+%!error hygepdf ()
+%!error hygepdf (1)
+%!error hygepdf (1,2)
+%!error hygepdf (1,2,3)
+%!error hygepdf (1,2,3,4,5)
+%!error hygepdf (1, ones(3),ones(2),ones(2))
+%!error hygepdf (1, ones(2),ones(3),ones(2))
+%!error hygepdf (1, ones(2),ones(2),ones(3))
+%!error hygepdf (i, 2, 2, 2)
+%!error hygepdf (2, i, 2, 2)
+%!error hygepdf (2, 2, i, 2)
+%!error hygepdf (2, 2, 2, i)
+
--- a/scripts/statistics/distributions/hygernd.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/hygernd.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1997-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,81 +18,131 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} hygernd (@var{t}, @var{m}, @var{n}, @var{r}, @var{c})
-## @deftypefnx {Function File} {} hygernd (@var{t}, @var{m}, @var{n}, @var{sz})
-## @deftypefnx {Function File} {} hygernd (@var{t}, @var{m}, @var{n})
-## Return an @var{r} by @var{c} matrix of random samples from the
-## hypergeometric distribution with parameters @var{t}, @var{m},
-## and @var{n}.
+## @deftypefn  {Function File} {} hygernd (@var{t}, @var{m}, @var{n})
+## @deftypefnx {Function File} {} hygernd (@var{t}, @var{m}, @var{n}, @var{r})
+## @deftypefnx {Function File} {} hygernd (@var{t}, @var{m}, @var{n}, @var{r}, @var{c}, @dots{})
+## @deftypefnx {Function File} {} hygernd (@var{t}, @var{m}, @var{n}, [@var{sz}])
+## Return a matrix of random samples from the hypergeometric distribution
+## with parameters @var{t}, @var{m}, and @var{n}.
 ##
-## The parameters @var{t}, @var{m}, and @var{n} must positive integers
+## The parameters @var{t}, @var{m}, and @var{n} must be positive integers
 ## with @var{m} and @var{n} not greater than @var{t}.
 ##
-## The parameter @var{sz} must be scalar or a vector of matrix
-## dimensions.  If @var{sz} is scalar, then a @var{sz} by @var{sz}
-## matrix of random samples is generated.
+## When called with a single size argument, return a square matrix with
+## the dimension specified.  When called with more than one scalar argument the
+## first two arguments are taken as the number of rows and columns and any
+## further arguments specify additional matrix dimensions.  The size may also
+## be specified with a vector of dimensions @var{sz}.
+## 
+## If no size arguments are given then the result matrix is the common size of
+## @var{t}, @var{m}, and @var{n}.
 ## @end deftypefn
 
-function rnd = hygernd (t, m, n, r, c)
+function rnd = hygernd (t, m, n, varargin)
 
-  if (nargin == 5)
-    if (! (isscalar (r) && (r > 0) && (r == round (r))))
-      error ("hygernd: R must be a positive integer");
-    endif
-    if (! (isscalar (c) && (c > 0) && (c == round (c))))
-      error ("hygernd: C must be a positive integer");
-    endif
-    sz = [r, c];
-  elseif (nargin == 4)
-    if (isvector (r) && all (r > 0) && all (r == round (r)))
-      if (isscalar (r))
-        sz = [r, r];
-      else
-        sz = r(:)';
-      endif
-    else
-      error ("hygernd: R must be a vector of positive integers");
-    endif
-  elseif (nargin != 3)
+  if (nargin < 3)
     print_usage ();
   endif
 
   if (! isscalar (t) || ! isscalar (m) || ! isscalar (n))
     [retval, t, m, n] = common_size (t, m, n);
     if (retval > 0)
-      error ("hygernd: T, M and N must be of common size or scalar");
+      error ("hygernd: T, M, and N must be of common size or scalars");
+    endif
+  endif
+
+  if (iscomplex (t) || iscomplex (m) || iscomplex (n))
+    error ("hygernd: T, M, and N must not be complex");
+  endif
+
+  if (nargin == 3)
+    sz = size (t);
+  elseif (nargin == 4)
+    if (isscalar (varargin{1}) && varargin{1} >= 0)
+      sz = [varargin{1}, varargin{1}];
+    elseif (isrow (varargin{1}) && all (varargin{1} >= 0))
+      sz = varargin{1};
+    else
+      error ("hygernd: dimension vector must be row vector of non-negative integers");
+    endif
+  elseif (nargin > 4)
+    if (any (cellfun (@(x) (!isscalar (x) || x < 0), varargin)))
+      error ("hygernd: dimensions must be non-negative integers");
     endif
-    if (nargin > 3)
-      if (any (sz != size (t)))
-        error ("hygernd: T, M and N must have the same size as implied by R and C or must be scalar");
+    sz = [varargin{:}];
+  endif
+
+  if (!isscalar (t) && !isequal (size (t), sz))
+    error ("hygernd: T, M, and N must be scalar or of size SZ");
+  endif
+
+  if (isa (t, "single") || isa (m, "single") || isa (n, "single"))
+    cls = "single";
+  else
+    cls = "double";
+  endif
+
+  ok = ((t >= 0) & (m >= 0) & (n > 0) & (m <= t) & (n <= t) &
+        (t == fix (t)) & (m == fix (m)) & (n == fix (n)));
+
+  if (isscalar (t))
+    if (ok)
+      v = 0:n;
+      p = hygepdf (v, t, m, n);
+      rnd = v(lookup (cumsum (p(1:end-1)) / sum (p), rand (sz)) + 1);
+      rnd = reshape (rnd, sz);
+      if (strcmp (cls, "single"))
+        rnd = single (rnd);
       endif
     else
-      sz = size (t);
+      rnd = NaN (sz, cls);
     endif
-  elseif (nargin == 3)
-    sz = 1;
-  endif
-
-  ## NaN elements
-  ne = (! (t >= 0) | ! (m >= 0) | ! (n > 0) | ! (t == round (t)) | ! (m == round (m)) | ! (n == round (n)) | ! (m <= t) | ! (n <= t));
-
-  if (! isscalar (t))
-    rnd = zeros (sz);
-    rnd(ne) = NaN;
+  else
+    rnd = NaN (sz, cls);
     rn = rand (sz);
-    for i = find (! ne)
+    for i = find (ok(:)')  # Must be row vector arg to for loop
       v = 0 : n(i);
       p = hygepdf (v, t(i), m(i), n(i));
       rnd(i) = v(lookup (cumsum (p(1 : end-1)) / sum (p), rn(i)) + 1);
     endfor
-  else
-    if (ne)
-      rnd = NaN (sz);
-    else
-      v = 0:n;
-      p = hygepdf (v, t, m, n);
-      rnd = v(lookup (cumsum (p(1:end-1)) / sum (p), rand (sz)) + 1);
-    endif
   endif
 
 endfunction
+
+
+%!assert(size (hygernd (4,2,2)), [1, 1]);
+%!assert(size (hygernd (4*ones(2,1), 2,2)), [2, 1]);
+%!assert(size (hygernd (4*ones(2,2), 2,2)), [2, 2]);
+%!assert(size (hygernd (4, 2*ones(2,1), 2)), [2, 1]);
+%!assert(size (hygernd (4, 2*ones(2,2), 2)), [2, 2]);
+%!assert(size (hygernd (4, 2, 2*ones(2,1))), [2, 1]);
+%!assert(size (hygernd (4, 2, 2*ones(2,2))), [2, 2]);
+%!assert(size (hygernd (4, 2, 2, 3)), [3, 3]);
+%!assert(size (hygernd (4, 2, 2, [4 1])), [4, 1]);
+%!assert(size (hygernd (4, 2, 2, 4, 1)), [4, 1]);
+
+%!assert(class (hygernd (4,2,2)), "double");
+%!assert(class (hygernd (single(4),2,2)), "single");
+%!assert(class (hygernd (single([4 4]),2,2)), "single");
+%!assert(class (hygernd (4,single(2),2)), "single");
+%!assert(class (hygernd (4,single([2 2]),2)), "single");
+%!assert(class (hygernd (4,2,single(2))), "single");
+%!assert(class (hygernd (4,2,single([2 2]))), "single");
+
+%% Test input validation
+%!error hygernd ()
+%!error hygernd (1)
+%!error hygernd (1,2)
+%!error hygernd (ones(3),ones(2),ones(2), 2)
+%!error hygernd (ones(2),ones(3),ones(2), 2)
+%!error hygernd (ones(2),ones(2),ones(3), 2)
+%!error hygernd (i, 2, 2)
+%!error hygernd (2, i, 2)
+%!error hygernd (2, 2, i)
+%!error hygernd (4,2,2, -1)
+%!error hygernd (4,2,2, ones(2))
+%!error hygernd (4,2,2, [2 -1 2])
+%!error hygernd (4*ones(2),2,2, 3)
+%!error hygernd (4*ones(2),2,2, [3, 2])
+%!error hygernd (4*ones(2),2,2, 3, 2)
+
--- a/scripts/statistics/distributions/kolmogorov_smirnov_cdf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/kolmogorov_smirnov_cdf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -18,16 +19,17 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} kolmogorov_smirnov_cdf (@var{x}, @var{tol})
-## Return the CDF at @var{x} of the Kolmogorov-Smirnov distribution,
+## Return the cumulative distribution function (CDF) at @var{x} of the 
+## Kolmogorov-Smirnov distribution,
 ## @tex
-## $$ Q(x) = \sum_{k=-\infty}^\infty (-1)^k \exp(-2 k^2 x^2) $$
+## $$ Q(x) = \sum_{k=-\infty}^\infty (-1)^k \exp (-2 k^2 x^2) $$
 ## @end tex
 ## @ifnottex
 ##
 ## @example
 ## @group
 ##          Inf
-## Q(x) =   SUM    (-1)^k exp(-2 k^2 x^2)
+## Q(x) =   SUM    (-1)^k exp (-2 k^2 x^2)
 ##        k = -Inf
 ## @end group
 ## @end example
@@ -61,8 +63,7 @@
     endif
   endif
 
-  n = numel (x);
-  if (n == 0)
+  if (numel (x) == 0)
     error ("kolmogorov_smirnov_cdf: X must not be empty");
   endif
 
@@ -70,10 +71,10 @@
 
   ind = find (x > 0);
   if (length (ind) > 0)
-    if (size(ind,2) < size(ind,1))
+    if (columns (ind) < rows (ind))
       y = x(ind.');
     else
-      y   = x(ind);
+      y = x(ind);
     endif
     K   = ceil (sqrt (- log (tol) / 2) / min (y));
     k   = (1:K)';
@@ -84,3 +85,11 @@
   endif
 
 endfunction
+
+
+%% Test input validation
+%!error kolmogorov_smirnov_cdf ()
+%!error kolmogorov_smirnov_cdf (1,2,3)
+%!error kolmogorov_smirnov_cdf (1, ones(2))
+%!error kolmogorov_smirnov_cdf ([], 1)
+
--- a/scripts/statistics/distributions/laplace_cdf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/laplace_cdf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -31,21 +32,25 @@
     print_usage ();
   endif
 
-  cdf = zeros (size (x));
-
-  k = find (isnan (x));
-  if (any (k))
-    cdf(k) = NaN;
+  if (iscomplex (x))
+    error ("laplace_cdf: X must not be complex");
   endif
 
-  k = find (x == Inf);
-  if (any (k))
-    cdf(k) = 1;
-  endif
-
-  k = find ((x > -Inf) & (x < Inf));
-  if (any (k))
-    cdf(k) = (1 + sign (x(k)) .* (1 - exp (- abs (x(k))))) / 2;
-  endif
+  cdf = (1 + sign (x) .* (1 - exp (- abs (x)))) / 2;
 
 endfunction
+
+
+%!shared x,y
+%! x = [-Inf -log(2) 0 log(2) Inf];
+%! y = [0, 1/4, 1/2, 3/4, 1]; 
+%!assert(laplace_cdf ([x, NaN]), [y, NaN]);
+
+%% Test class of input preserved
+%!assert(laplace_cdf (single([x, NaN])), single([y, NaN]));
+
+%% Test input validation
+%!error laplace_cdf ()
+%!error laplace_cdf (1,2)
+%!error laplace_cdf (i)
+
--- a/scripts/statistics/distributions/laplace_inv.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/laplace_inv.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -31,22 +32,33 @@
     print_usage ();
   endif
 
-  inv = -Inf (size (x));
+  if (iscomplex (x))
+    error ("laplace_inv: X must not be complex");
+  endif
 
-  k = find (isnan (x) | (x < 0) | (x > 1));
-  if (any (k))
-    inv(k) = NaN;
+  if (isa (x, "single"))
+    inv = NaN (size (x), "single");
+  else
+    inv = NaN (size (x));
   endif
 
-  k = find (x == 1);
-  if (any (k))
-    inv(k) = Inf;
-  endif
-
-  k = find ((x > 0) & (x < 1));
-  if (any (k))
-    inv(k) = ((x(k) < 1/2) .* log (2 * x(k))
-              - (x(k) > 1/2) .* log (2 * (1 - x(k))));
-  endif
+  k = (x >= 0) & (x <= 1);
+  inv(k) = ((x(k) < 1/2) .* log (2 * x(k))
+            - (x(k) > 1/2) .* log (2 * (1 - x(k))));
 
 endfunction
+
+
+%!shared x
+%! x = [-1 0 0.5 1 2];
+%!assert(laplace_inv (x), [NaN -Inf 0 Inf NaN]);
+
+%% Test class of input preserved
+%!assert(laplace_inv ([x, NaN]), [NaN -Inf 0 Inf NaN NaN]);
+%!assert(laplace_inv (single([x, NaN])), single([NaN -Inf 0 Inf NaN NaN]));
+
+%% Test input validation
+%!error laplace_inv ()
+%!error laplace_inv (1,2)
+%!error laplace_inv (i)
+
--- a/scripts/statistics/distributions/laplace_pdf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/laplace_pdf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -30,17 +31,26 @@
   if (nargin != 1)
     print_usage ();
   endif
-
-  pdf = zeros (size (x));
-
-  k = find (isnan (x));
-  if (any (k))
-    pdf(k) = NaN;
+  
+  if (iscomplex (x))
+    error ("laplace_pdf: X must not be complex");
   endif
 
-  k = find ((x > -Inf) & (x < Inf));
-  if (any (k))
-    pdf(k) = exp (- abs (x(k))) / 2;
-  endif
+  pdf = exp (- abs (x)) / 2;
 
 endfunction
+
+
+%!shared x,y
+%! x = [-Inf -log(2) 0 log(2) Inf];
+%! y = [0, 1/4, 1/2, 1/4, 0]; 
+%!assert(laplace_pdf ([x, NaN]), [y, NaN]);
+
+%% Test class of input preserved
+%!assert(laplace_pdf (single([x, NaN])), single([y, NaN]));
+
+%% Test input validation
+%!error laplace_pdf ()
+%!error laplace_pdf (1,2)
+%!error laplace_pdf (i)
+
--- a/scripts/statistics/distributions/laplace_rnd.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/laplace_rnd.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,40 +18,57 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} laplace_rnd (@var{r}, @var{c})
-## @deftypefnx {Function File} {} laplace_rnd (@var{sz});
-## Return an @var{r} by @var{c} matrix of random numbers from the
-## Laplace distribution.  Or if @var{sz} is a vector, create a matrix of
-## @var{sz}.
+## @deftypefn  {Function File} {} laplace_rnd (@var{r})
+## @deftypefnx {Function File} {} laplace_rnd (@var{r}, @var{c}, @dots{})
+## @deftypefnx {Function File} {} laplace_rnd ([@var{sz}])
+## Return a matrix of random samples from the Laplace distribution.
+##
+## When called with a single size argument, return a square matrix with
+## the dimension specified.  When called with more than one scalar argument the
+## first two arguments are taken as the number of rows and columns and any
+## further arguments specify additional matrix dimensions.  The size may also
+## be specified with a vector of dimensions @var{sz}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Random deviates from the Laplace distribution
 
-function rnd = laplace_rnd (r, c)
+function rnd = laplace_rnd (varargin)
 
-  if (nargin == 2)
-    if (! (isscalar (r) && (r > 0) && (r == round (r))))
-      error ("laplace_rnd: R must be a positive integer");
-    endif
-    if (! (isscalar (c) && (c > 0) && (c == round (c))))
-      error ("laplace_rnd: C must be a positive integer");
-    endif
-    sz = [r, c];
-  elseif (nargin == 1)
-    if (isscalar (r) && (r > 0))
-      sz = [r, r];
-    elseif (isvector(r) && all (r > 0))
-      sz = r(:)';
-    else
-      error ("laplace_rnd: R must be a positive integer or vector");
-    endif
-  else
+  if (nargin < 1)
     print_usage ();
   endif
 
+  if (nargin == 1)
+    if (isscalar (varargin{1}) && varargin{1} >= 0)
+      sz = [varargin{1}, varargin{1}];
+    elseif (isrow (varargin{1}) && all (varargin{1} >= 0))
+      sz = varargin{1}(:)';
+    else
+      error ("laplace_rnd: dimension vector must be row vector of non-negative integers");
+    endif
+  elseif (nargin > 1)
+    if (any (cellfun (@(x) (!isscalar (x) || x < 0), varargin)))
+      error ("laplace_rnd: dimensions must be non-negative integers");
+    endif
+    sz = [varargin{:}];
+  endif
+
   tmp = rand (sz);
-  rnd = ((tmp < 1/2) .* log (2 * tmp)
-         - (tmp > 1/2) .* log (2 * (1 - tmp)));
+  rnd = (tmp < 1/2) .* log (2 * tmp) - (tmp > 1/2) .* log (2 * (1 - tmp));
 
 endfunction
+
+
+%!assert(size (laplace_rnd (3)), [3, 3]);
+%!assert(size (laplace_rnd ([4 1])), [4, 1]);
+%!assert(size (laplace_rnd (4,1)), [4, 1]);
+
+%% Test input validation
+%!error laplace_rnd ()
+%!error laplace_rnd (-1)
+%!error laplace_rnd (ones(2))
+%!error laplace_rnd ([2 -1 2])
+%!error laplace_rnd (1, ones(2))
+%!error laplace_rnd (1, -1)
+
--- a/scripts/statistics/distributions/logistic_cdf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/logistic_cdf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -18,8 +19,8 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} logistic_cdf (@var{x})
-## For each component of @var{x}, compute the CDF at @var{x} of the
-## logistic distribution.
+## For each element of @var{x}, compute the cumulative distribution function
+## (CDF) at @var{x} of the logistic distribution.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
@@ -31,6 +32,25 @@
     print_usage ();
   endif
 
-  cdf = 1 ./ (1 + exp (- x));
+  if (iscomplex (x))
+    error ("logistic_cdf: X must not be complex");
+  endif
+
+  cdf = 1 ./ (1 + exp (-x));
 
 endfunction
+
+
+%!shared x,y
+%! x = [-Inf -log(3) 0 log(3) Inf];
+%! y = [0, 1/4, 1/2, 3/4, 1]; 
+%!assert(logistic_cdf ([x, NaN]), [y, NaN], eps);
+
+%% Test class of input preserved
+%!assert(logistic_cdf (single([x, NaN])), single([y, NaN]), eps ("single"));
+
+%% Test input validation
+%!error logistic_cdf ()
+%!error logistic_cdf (1,2)
+%!error logistic_cdf (i)
+
--- a/scripts/statistics/distributions/logistic_inv.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/logistic_inv.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -18,7 +19,7 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} logistic_inv (@var{x})
-## For each component of @var{x}, compute the quantile (the inverse of
+## For each element of @var{x}, compute the quantile (the inverse of
 ## the CDF) at @var{x} of the logistic distribution.
 ## @end deftypefn
 
@@ -31,26 +32,38 @@
     print_usage ();
   endif
 
-  inv = zeros (size (x));
-
-  k = find ((x < 0) | (x > 1) | isnan (x));
-  if (any (k))
-    inv(k) = NaN;
+  if (iscomplex (x))
+    error ("logistic_inv: X must not be complex");
   endif
 
-  k = find (x == 0);
-  if (any (k))
-    inv(k) = -Inf;
+  if (isa (x, "single"))
+    inv = NaN (size (x), "single");
+  else
+    inv = NaN (size (x));
   endif
 
-  k = find (x == 1);
-  if (any (k))
-    inv(k) = Inf;
-  endif
+  k = (x == 0);
+  inv(k) = -Inf;
 
-  k = find ((x > 0) & (x < 1));
-  if (any (k))
-    inv (k) = - log (1 ./ x(k) - 1);
-  endif
+  k = (x == 1);
+  inv(k) = Inf;
+
+  k = (x > 0) & (x < 1);
+  inv(k) = - log (1 ./ x(k) - 1);
 
 endfunction
+
+
+%!shared x
+%! x = [-1 0 0.5 1 2];
+%!assert(logistic_inv (x), [NaN -Inf 0 Inf NaN]);
+
+%% Test class of input preserved
+%!assert(logistic_inv ([x, NaN]), [NaN -Inf 0 Inf NaN NaN]);
+%!assert(logistic_inv (single([x, NaN])), single([NaN -Inf 0 Inf NaN NaN]));
+
+%% Test input validation
+%!error logistic_inv ()
+%!error logistic_inv (1,2)
+%!error logistic_inv (i)
+
--- a/scripts/statistics/distributions/logistic_pdf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/logistic_pdf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -18,7 +18,7 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} logistic_pdf (@var{x})
-## For each component of @var{x}, compute the PDF at @var{x} of the
+## For each element of @var{x}, compute the PDF at @var{x} of the
 ## logistic distribution.
 ## @end deftypefn
 
@@ -31,7 +31,26 @@
     print_usage ();
   endif
 
+  if (iscomplex (x))
+    error ("logistic_pdf: X must not be complex");
+  endif
+
   cdf = logistic_cdf (x);
   pdf = cdf .* (1 - cdf);
 
 endfunction
+
+
+%!shared x,y
+%! x = [-Inf -log(4) 0 log(4) Inf];
+%! y = [0, 0.16, 1/4, 0.16, 0]; 
+%!assert(logistic_pdf ([x, NaN]), [y, NaN], eps);
+
+%% Test class of input preserved
+%!assert(logistic_pdf (single([x, NaN])), single([y, NaN]), eps ("single"));
+
+%% Test input validation
+%!error logistic_pdf ()
+%!error logistic_pdf (1,2)
+%!error logistic_pdf (i)
+
--- a/scripts/statistics/distributions/logistic_rnd.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/logistic_rnd.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,39 +18,56 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} logistic_rnd (@var{r}, @var{c})
-## @deftypefnx {Function File} {} logistic_rnd (@var{sz})
-## Return an @var{r} by @var{c} matrix of random numbers from the
-## logistic distribution.  Or if @var{sz} is a vector, create a matrix of
-## @var{sz}.
+## @deftypefn  {Function File} {} logistic_rnd (@var{r})
+## @deftypefnx {Function File} {} logistic_rnd (@var{r}, @var{c}, @dots{})
+## @deftypefnx {Function File} {} logistic_rnd ([@var{sz}])
+## Return a matrix of random samples from the logistic distribution.
+##
+## When called with a single size argument, return a square matrix with
+## the dimension specified.  When called with more than one scalar argument the
+## first two arguments are taken as the number of rows and columns and any
+## further arguments specify additional matrix dimensions.  The size may also
+## be specified with a vector of dimensions @var{sz}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Random deviates from the logistic distribution
 
-function rnd = logistic_rnd (r, c)
+function rnd = logistic_rnd (varargin)
 
+  if (nargin < 1)
+    print_usage ();
+  endif
 
-  if (nargin == 2)
-    if (! (isscalar (r) && (r > 0) && (r == round (r))))
-      error ("logistic_rnd: R must be a positive integer");
-    endif
-    if (! (isscalar (c) && (c > 0) && (c == round (c))))
-      error ("logistic_rnd: C must be a positive integer");
+  if (nargin == 1)
+    if (isscalar (varargin{1}) && varargin{1} >= 0)
+      sz = [varargin{1}, varargin{1}];
+    elseif (isrow (varargin{1}) && all (varargin{1} >= 0))
+      sz = varargin{1};
+    else
+      error ("logistic_rnd: dimension vector must be row vector of non-negative integers");
     endif
-    sz = [r, c];
-  elseif (nargin == 1)
-    if (isscalar (r) && (r > 0))
-      sz = [r, r];
-    elseif (isvector(r) && all (r > 0))
-      sz = r(:)';
-    else
-      error ("logistic_rnd: R must be a positive integer or vector");
+  elseif (nargin > 1)
+    if (any (cellfun (@(x) (!isscalar (x) || x < 0), varargin)))
+      error ("logistic_rnd: dimensions must be non-negative integers");
     endif
-  else
-    print_usage ();
+    sz = [varargin{:}];
   endif
 
   rnd = - log (1 ./ rand (sz) - 1);
 
 endfunction
+
+
+%!assert(size (logistic_rnd (3)), [3, 3]);
+%!assert(size (logistic_rnd ([4 1])), [4, 1]);
+%!assert(size (logistic_rnd (4,1)), [4, 1]);
+
+%% Test input validation
+%!error logistic_rnd ()
+%!error logistic_rnd (-1)
+%!error logistic_rnd (ones(2))
+%!error logistic_rnd ([2 -1 2])
+%!error logistic_rnd (1, ones(2))
+%!error logistic_rnd (1, -1)
+
--- a/scripts/statistics/distributions/logncdf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/logncdf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,7 +18,8 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} logncdf (@var{x}, @var{mu}, @var{sigma})
+## @deftypefn  {Function File} {} logncdf (@var{x})
+## @deftypefnx {Function File} {} logncdf (@var{x}, @var{mu}, @var{sigma})
 ## For each element of @var{x}, compute the cumulative distribution
 ## function (CDF) at @var{x} of the lognormal distribution with
 ## parameters @var{mu} and @var{sigma}.  If a random variable follows this
@@ -30,48 +32,69 @@
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: CDF of the log normal distribution
 
-function cdf = logncdf (x, mu, sigma)
+function cdf = logncdf (x, mu = 0, sigma = 1)
 
-  if (! ((nargin == 1) || (nargin == 3)))
+  if (nargin != 1 && nargin != 3)
     print_usage ();
   endif
 
-  if (nargin == 1)
-    mu = 0;
-    sigma = 1;
-  endif
-
-  ## The following "straightforward" implementation unfortunately does
-  ## not work (because exp (Inf) -> NaN etc):
-  ## cdf = normal_cdf (log (x), log (mu), sigma);
-  ## Hence ...
-
   if (!isscalar (mu) || !isscalar (sigma))
     [retval, x, mu, sigma] = common_size (x, mu, sigma);
     if (retval > 0)
-      error ("logncdf: X, MU and SIGMA must be of common size or scalars");
+      error ("logncdf: X, MU, and SIGMA must be of common size or scalars");
     endif
   endif
 
-  cdf = zeros (size (x));
+  if (iscomplex (x) || iscomplex (mu) || iscomplex (sigma))
+    error ("logncdf: X, MU, and SIGMA must not be complex");
+  endif
 
-  k = find (isnan (x) | !(sigma > 0) | !(sigma < Inf));
-  if (any (k))
-    cdf(k) = NaN;
+  if (isa (x, "single") || isa (mu, "single") || isa (sigma, "single"))
+    cdf = zeros (size (x), "single");
+  else
+    cdf = zeros (size (x));
   endif
 
-  k = find ((x == Inf) & (sigma > 0) & (sigma < Inf));
-  if (any (k))
-    cdf(k) = 1;
-  endif
+  k = isnan (x) | !(sigma > 0) | !(sigma < Inf);
+  cdf(k) = NaN;
+
+  k = (x == Inf) & (sigma > 0) & (sigma < Inf);
+  cdf(k) = 1;
 
-  k = find ((x > 0) & (x < Inf) & (sigma > 0) & (sigma < Inf));
-  if (any (k))
-    if (isscalar (mu) && isscalar (sigma))
-      cdf(k) = stdnormal_cdf ((log (x(k)) - mu) / sigma);
-    else
-      cdf(k) = stdnormal_cdf ((log (x(k)) - mu(k)) ./ sigma(k));
-    endif
+  k = (x > 0) & (x < Inf) & (sigma > 0) & (sigma < Inf);
+  if (isscalar (mu) && isscalar (sigma))
+    cdf(k) = stdnormal_cdf ((log (x(k)) - mu) / sigma);
+  else
+    cdf(k) = stdnormal_cdf ((log (x(k)) - mu(k)) ./ sigma(k));
   endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 1 e Inf];
+%! y = [0, 0, 0.5, 1/2+1/2*erf(1/2), 1];
+%!assert(logncdf (x, zeros(1,5), sqrt(2)*ones(1,5)), y);
+%!assert(logncdf (x, 0, sqrt(2)*ones(1,5)), y);
+%!assert(logncdf (x, zeros(1,5), sqrt(2)), y);
+%!assert(logncdf (x, [0 1 NaN 0 1], sqrt(2)), [0 0 NaN y(4:5)]);
+%!assert(logncdf (x, 0, sqrt(2)*[0 NaN Inf 1 1]), [NaN NaN NaN y(4:5)]);
+%!assert(logncdf ([x(1:3) NaN x(5)], 0, sqrt(2)), [y(1:3) NaN y(5)]);
+
+%% Test class of input preserved
+%!assert(logncdf ([x, NaN], 0, sqrt(2)), [y, NaN]);
+%!assert(logncdf (single([x, NaN]), 0, sqrt(2)), single([y, NaN]), eps("single"));
+%!assert(logncdf ([x, NaN], single(0), sqrt(2)), single([y, NaN]), eps("single"));
+%!assert(logncdf ([x, NaN], 0, single(sqrt(2))), single([y, NaN]), eps("single"));
+
+%% Test input validation
+%!error logncdf ()
+%!error logncdf (1,2)
+%!error logncdf (1,2,3,4)
+%!error logncdf (ones(3),ones(2),ones(2))
+%!error logncdf (ones(2),ones(3),ones(2))
+%!error logncdf (ones(2),ones(2),ones(3))
+%!error logncdf (i, 2, 2)
+%!error logncdf (2, i, 2)
+%!error logncdf (2, 2, i)
+
--- a/scripts/statistics/distributions/logninv.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/logninv.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,7 +18,8 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} logninv (@var{x}, @var{mu}, @var{sigma})
+## @deftypefn  {Function File} {} logninv (@var{x})
+## @deftypefnx {Function File} {} logninv (@var{x}, @var{mu}, @var{sigma})
 ## For each element of @var{x}, compute the quantile (the inverse of the
 ## CDF) at @var{x} of the lognormal distribution with parameters @var{mu}
 ## and @var{sigma}.  If a random variable follows this distribution, its
@@ -30,48 +32,68 @@
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Quantile function of the log normal distribution
 
-function inv = logninv (x, mu, sigma)
+function inv = logninv (x, mu = 0, sigma = 1)
 
-  if (! ((nargin == 1) || (nargin == 3)))
+  if (nargin != 1 && nargin != 3)
     print_usage ();
   endif
 
-  if (nargin == 1)
-    mu = 0;
-    sigma = 1;
-  endif
-
-  ## The following "straightforward" implementation unfortunately does
-  ## not work (because exp (Inf) -> NaN):
-  ## inv = exp (norminv (x, mu, sigma));
-  ## Hence ...
-
   if (!isscalar (mu) || !isscalar (sigma))
     [retval, x, mu, sigma] = common_size (x, mu, sigma);
     if (retval > 0)
-      error ("logninv: X, MU and SIGMA must be of common size or scalars");
+      error ("logninv: X, MU, and SIGMA must be of common size or scalars");
     endif
   endif
 
-  inv = zeros (size (x));
+  if (iscomplex (x) || iscomplex (mu) || iscomplex (sigma))
+    error ("logninv: X, MU, and SIGMA must not be complex");
+  endif
 
-  k = find (!(x >= 0) | !(x <= 1) | !(sigma > 0) | !(sigma < Inf));
-  if (any (k))
-    inv(k) = NaN;
+  if (isa (x, "single") || isa (mu, "single") || isa (sigma, "single"))
+    inv = NaN (size (x), "single");
+  else
+    inv = NaN (size (x));
   endif
 
-  k = find ((x == 1) & (sigma > 0) & (sigma < Inf));
-  if (any (k))
-    inv(k) = Inf;
-  endif
+  k = !(x >= 0) | !(x <= 1) | !(sigma > 0) | !(sigma < Inf);
+  inv(k) = NaN;
+
+  k = (x == 1) & (sigma > 0) & (sigma < Inf);
+  inv(k) = Inf;
 
-  k = find ((x > 0) & (x < 1) & (sigma > 0) & (sigma < Inf));
-  if (any (k))
-    if (isscalar (mu) && isscalar (sigma))
-      inv(k) = exp (mu) .* exp (sigma .* stdnormal_inv (x(k)));
-    else
-      inv(k) = exp (mu(k)) .* exp (sigma(k) .* stdnormal_inv (x(k)));
-    endif
+  k = (x >= 0) & (x < 1) & (sigma > 0) & (sigma < Inf);
+  if (isscalar (mu) && isscalar (sigma))
+    inv(k) = exp (mu) .* exp (sigma .* stdnormal_inv (x(k)));
+  else
+    inv(k) = exp (mu(k)) .* exp (sigma(k) .* stdnormal_inv (x(k)));
   endif
 
 endfunction
+
+
+%!shared x
+%! x = [-1 0 0.5 1 2];
+%!assert(logninv (x, ones(1,5), ones(1,5)), [NaN 0 e Inf NaN]);
+%!assert(logninv (x, 1, ones(1,5)), [NaN 0 e Inf NaN]);
+%!assert(logninv (x, ones(1,5), 1), [NaN 0 e Inf NaN]);
+%!assert(logninv (x, [1 1 NaN 0 1], 1), [NaN 0 NaN Inf NaN]);
+%!assert(logninv (x, 1, [1 0 NaN Inf 1]), [NaN NaN NaN NaN NaN]);
+%!assert(logninv ([x(1:2) NaN x(4:5)], 1, 2), [NaN 0 NaN Inf NaN]);
+
+%% Test class of input preserved
+%!assert(logninv ([x, NaN], 1, 1), [NaN 0 e Inf NaN NaN]);
+%!assert(logninv (single([x, NaN]), 1, 1), single([NaN 0 e Inf NaN NaN]));
+%!assert(logninv ([x, NaN], single(1), 1), single([NaN 0 e Inf NaN NaN]));
+%!assert(logninv ([x, NaN], 1, single(1)), single([NaN 0 e Inf NaN NaN]));
+
+%% Test input validation
+%!error logninv ()
+%!error logninv (1,2)
+%!error logninv (1,2,3,4)
+%!error logninv (ones(3),ones(2),ones(2))
+%!error logninv (ones(2),ones(3),ones(2))
+%!error logninv (ones(2),ones(2),ones(3))
+%!error logninv (i, 2, 2)
+%!error logninv (2, i, 2)
+%!error logninv (2, 2, i)
+
--- a/scripts/statistics/distributions/lognpdf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/lognpdf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,7 +18,8 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} lognpdf (@var{x}, @var{mu}, @var{sigma})
+## @deftypefn  {Function File} {} lognpdf (@var{x})
+## @deftypefnx {Function File} {} lognpdf (@var{x}, @var{mu}, @var{sigma})
 ## For each element of @var{x}, compute the probability density function
 ## (PDF) at @var{x} of the lognormal distribution with parameters
 ## @var{mu} and @var{sigma}.  If a random variable follows this distribution,
@@ -30,43 +32,65 @@
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: PDF of the log normal distribution
 
-function pdf = lognpdf (x, mu, sigma)
+function pdf = lognpdf (x, mu = 0, sigma = 1)
 
-  if (! ((nargin == 1) || (nargin == 3)))
+  if (nargin != 1 && nargin != 3)
     print_usage ();
   endif
 
-  if (nargin == 1)
-    mu = 0;
-    sigma = 1;
-  endif
-
-  ## The following "straightforward" implementation unfortunately does
-  ## not work for the special cases (Inf, ...)
-  ## pdf = (x > 0) ./ x .* normpdf (log (x), mu, sigma);
-  ## Hence ...
-
   if (!isscalar (mu) || !isscalar (sigma))
     [retval, x, mu, sigma] = common_size (x, mu, sigma);
     if (retval > 0)
-      error ("lognpdf: X, MU and SIGMA must be of common size or scalars");
+      error ("lognpdf: X, MU, and SIGMA must be of common size or scalars");
     endif
   endif
 
-  pdf = zeros (size (x));
-
-  k = find (isnan (x) | !(sigma > 0) | !(sigma < Inf));
-  if (any (k))
-    pdf(k) = NaN;
+  if (iscomplex (x) || iscomplex (mu) || iscomplex (sigma))
+    error ("lognpdf: X, MU, and SIGMA must not be complex");
   endif
 
-  k = find ((x > 0) & (x < Inf) & (sigma > 0) & (sigma < Inf));
-  if (any (k))
-    if (isscalar (mu) && isscalar (sigma))
-      pdf(k) = normpdf (log (x(k)), mu, sigma) ./ x(k);
-    else
-      pdf(k) = normpdf (log (x(k)), mu(k), sigma(k)) ./ x(k);
-    endif
+  if (isa (x, "single") || isa (mu, "single") || isa (sigma, "single"))
+    pdf = zeros (size (x), "single");
+  else
+    pdf = zeros (size (x));
+  endif
+
+  k = isnan (x) | !(sigma > 0) | !(sigma < Inf);
+  pdf(k) = NaN;
+
+  k = (x > 0) & (x < Inf) & (sigma > 0) & (sigma < Inf);
+  if (isscalar (mu) && isscalar (sigma))
+    pdf(k) = normpdf (log (x(k)), mu, sigma) ./ x(k);
+  else
+    pdf(k) = normpdf (log (x(k)), mu(k), sigma(k)) ./ x(k);
   endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 e Inf];
+%! y = [0, 0, 1/(e*sqrt(2*pi)) * exp(-1/2), 0];
+%!assert(lognpdf (x, zeros(1,4), ones(1,4)), y, eps);
+%!assert(lognpdf (x, 0, ones(1,4)), y, eps);
+%!assert(lognpdf (x, zeros(1,4), 1), y, eps);
+%!assert(lognpdf (x, [0 1 NaN 0], 1), [0 0 NaN y(4)], eps);
+%!assert(lognpdf (x, 0, [0 NaN Inf 1]), [NaN NaN NaN y(4)], eps);
+%!assert(lognpdf ([x, NaN], 0, 1), [y, NaN], eps);
+
+%% Test class of input preserved
+%!assert(lognpdf (single([x, NaN]), 0, 1), single([y, NaN]), eps("single"));
+%!assert(lognpdf ([x, NaN], single(0), 1), single([y, NaN]), eps("single"));
+%!assert(lognpdf ([x, NaN], 0, single(1)), single([y, NaN]), eps("single"));
+
+%% Test input validation
+%!error lognpdf ()
+%!error lognpdf (1,2)
+%!error lognpdf (1,2,3,4)
+%!error lognpdf (ones(3),ones(2),ones(2))
+%!error lognpdf (ones(2),ones(3),ones(2))
+%!error lognpdf (ones(2),ones(2),ones(3))
+%!error lognpdf (i, 2, 2)
+%!error lognpdf (2, i, 2)
+%!error lognpdf (2, 2, i)
+
--- a/scripts/statistics/distributions/lognrnd.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/lognrnd.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,76 +18,115 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} lognrnd (@var{mu}, @var{sigma}, @var{r}, @var{c})
-## @deftypefnx {Function File} {} lognrnd (@var{mu}, @var{sigma}, @var{sz})
-## Return an @var{r} by @var{c} matrix of random samples from the
-## lognormal distribution with parameters @var{mu} and @var{sigma}.  Both
-## @var{mu} and @var{sigma} must be scalar or of size @var{r} by @var{c}.
-## Or if @var{sz} is a vector, create a matrix of size @var{sz}.
+## @deftypefn  {Function File} {} lognrnd (@var{mu}, @var{sigma})
+## @deftypefnx {Function File} {} lognrnd (@var{mu}, @var{sigma}, @var{r})
+## @deftypefnx {Function File} {} lognrnd (@var{mu}, @var{sigma}, @var{r}, @var{c}, @dots{})
+## @deftypefnx {Function File} {} lognrnd (@var{mu}, @var{sigma}, [@var{sz}])
+## Return a matrix of random samples from the lognormal distribution with
+## parameters @var{mu} and @var{sigma}.
 ##
-## If @var{r} and @var{c} are omitted, the size of the result matrix is
-## the common size of @var{mu} and @var{sigma}.
+## When called with a single size argument, return a square matrix with
+## the dimension specified.  When called with more than one scalar argument the
+## first two arguments are taken as the number of rows and columns and any
+## further arguments specify additional matrix dimensions.  The size may also
+## be specified with a vector of dimensions @var{sz}.
+## 
+## If no size arguments are given then the result matrix is the common size of
+## @var{mu} and @var{sigma}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Random deviates from the log normal distribution
 
-function rnd = lognrnd (mu, sigma, r, c)
+function rnd = lognrnd (mu, sigma, varargin)
 
-  if (nargin > 1)
-    if (!isscalar(mu) || !isscalar(sigma))
-      [retval, mu, sigma] = common_size (mu, sigma);
-      if (retval > 0)
-        error ("lognrnd: MU and SIGMA must be of common size or scalar");
-      endif
+  if (nargin < 2)
+    print_usage ();
+  endif
+
+  if (!isscalar (mu) || !isscalar (sigma))
+    [retval, mu, sigma] = common_size (mu, sigma);
+    if (retval > 0)
+      error ("lognrnd: MU and SIGMA must be of common size or scalars");
     endif
   endif
 
-  if (nargin == 4)
-    if (! (isscalar (r) && (r > 0) && (r == round (r))))
-      error ("lognrnd: R must be a positive integer");
-    endif
-    if (! (isscalar (c) && (c > 0) && (c == round (c))))
-      error ("lognrnd: C must be a positive integer");
-    endif
-    sz = [r, c];
+  if (iscomplex (mu) || iscomplex (sigma))
+    error ("lognrnd: MU and SIGMA must not be complex");
+  endif
 
-    if (any (size (mu) != 1)
-        && ((length (size (mu)) != length (sz)) || any (size (mu) != sz)))
-      error ("lognrnd: MU and SIGMA must be scalar or of size [R, C]");
-    endif
-
+  if (nargin == 2)
+    sz = size (mu);
   elseif (nargin == 3)
-    if (isscalar (r) && (r > 0))
-      sz = [r, r];
-    elseif (isvector(r) && all (r > 0))
-      sz = r(:)';
+    if (isscalar (varargin{1}) && varargin{1} >= 0)
+      sz = [varargin{1}, varargin{1}];
+    elseif (isrow (varargin{1}) && all (varargin{1} >= 0))
+      sz = varargin{1};
     else
-      error ("lognrnd: R must be a positive integer or vector");
+      error ("lognrnd: dimension vector must be row vector of non-negative integers");
     endif
+  elseif (nargin > 3)
+    if (any (cellfun (@(x) (!isscalar (x) || x < 0), varargin)))
+      error ("lognrnd: dimensions must be non-negative integers");
+    endif
+    sz = [varargin{:}];
+  endif
 
-    if (any (size (mu) != 1)
-        && ((length (size (mu)) != length (sz)) || any (size (mu) != sz)))
-      error ("lognrnd: MU and SIGMA must be scalar or of size SZ");
-    endif
-  elseif (nargin == 2)
-    sz = size(mu);
+  if (!isscalar (mu) && !isequal (size (mu), sz))
+    error ("lognrnd: MU and SIGMA must be scalar or of size SZ");
+  endif
+
+  if (isa (mu, "single") || isa (sigma, "single"))
+    cls = "single";
   else
-    print_usage ();
+    cls = "double";
   endif
 
   if (isscalar (mu) && isscalar (sigma))
-    if  (!(sigma > 0) || !(sigma < Inf))
-      rnd = NaN (sz);
+    if ((sigma > 0) && (sigma < Inf))
+      rnd = exp (mu + sigma * randn (sz));
     else
-      rnd = exp(mu + sigma .* randn (sz));
+      rnd = NaN (sz, cls);
     endif
   else
     rnd = exp (mu + sigma .* randn (sz));
-    k = find ((sigma < 0) | (sigma == Inf));
-    if (any (k))
-      rnd(k) = NaN;
-    endif
+
+    k = (sigma < 0) | (sigma == Inf);
+    rnd(k) = NaN;
   endif
 
 endfunction
+
+
+%!assert(size (lognrnd (1,2)), [1, 1]);
+%!assert(size (lognrnd (ones(2,1), 2)), [2, 1]);
+%!assert(size (lognrnd (ones(2,2), 2)), [2, 2]);
+%!assert(size (lognrnd (1, 2*ones(2,1))), [2, 1]);
+%!assert(size (lognrnd (1, 2*ones(2,2))), [2, 2]);
+%!assert(size (lognrnd (1, 2, 3)), [3, 3]);
+%!assert(size (lognrnd (1, 2, [4 1])), [4, 1]);
+%!assert(size (lognrnd (1, 2, 4, 1)), [4, 1]);
+
+%% Test class of input preserved
+%!assert(class (lognrnd (1, 2)), "double");
+%!assert(class (lognrnd (single(1), 2)), "single");
+%!assert(class (lognrnd (single([1 1]), 2)), "single");
+%!assert(class (lognrnd (1, single(2))), "single");
+%!assert(class (lognrnd (1, single([2 2]))), "single");
+
+%% Test input validation
+%!error lognrnd ()
+%!error lognrnd (1)
+%!error lognrnd (ones(3),ones(2))
+%!error lognrnd (ones(2),ones(3))
+%!error lognrnd (i, 2)
+%!error lognrnd (2, i)
+%!error lognrnd (1,2, -1)
+%!error lognrnd (1,2, ones(2))
+%!error lognrnd (1, 2, [2 -1 2])
+%!error lognrnd (1,2, 1, ones(2))
+%!error lognrnd (1,2, 1, -1)
+%!error lognrnd (ones(2,2), 2, 3)
+%!error lognrnd (ones(2,2), 2, [3, 2])
+%!error lognrnd (ones(2,2), 2, 2, 3)
+
--- a/scripts/statistics/distributions/nbincdf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/nbincdf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -18,9 +19,13 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} nbincdf (@var{x}, @var{n}, @var{p})
-## For each element of @var{x}, compute the CDF at x of the Pascal
-## (negative binomial) distribution with parameters @var{n} and @var{p}.
+## For each element of @var{x}, compute the cumulative distribution function
+## (CDF) at @var{x} of the negative binomial distribution with
+## parameters @var{n} and @var{p}.
 ##
+## When @var{n} is integer this is the Pascal distribution.  When
+## @var{n} is extended to real numbers this is the Polya distribution.
+## 
 ## The number of failures in a Bernoulli experiment with success
 ## probability @var{p} before the @var{n}-th success follows this
 ## distribution.
@@ -35,58 +40,66 @@
     print_usage ();
   endif
 
-  if (!isscalar(n) || !isscalar(p))
+  if (!isscalar (n) || !isscalar (p))
     [retval, x, n, p] = common_size (x, n, p);
     if (retval > 0)
-      error ("nbincdf: X, N and P must be of common size or scalar");
+      error ("nbincdf: X, N, and P must be of common size or scalars");
     endif
   endif
 
-  cdf = zeros (size (x));
-
-  k = find (isnan (x) | (n < 1) | (n == Inf) | (n != round (n))
-            | (p < 0) | (p > 1));
-  if (any (k))
-    cdf(k) = NaN;
+  if (iscomplex (x) || iscomplex (n) || iscomplex (p))
+    error ("nbincdf: X, N, and P must not be complex");
   endif
 
-  k = find ((x == Inf) & (n > 0) & (n < Inf) & (n == round (n))
-            & (p >= 0) & (p <= 1));
-  if (any (k))
-    cdf(k) = 1;
+  if (isa (x, "single") || isa (n, "single") || isa (p, "single"))
+    cdf = zeros (size (x), "single");
+  else
+    cdf = zeros (size (x));
   endif
 
-  k = find ((x >= 0) & (x < Inf) & (x == round (x)) & (n > 0)
-            & (n < Inf) & (n == round (n)) & (p > 0) & (p <= 1));
-  if (any (k))
-    ## Does anyone know a better way to do the summation?
-    m = zeros (size (k));
-    x = floor (x(k));
-    y = cdf(k);
-    if (isscalar (n) && isscalar (p))
-      while (1)
-        l = find (m <= x);
-        if (any (l))
-          y(l) = y(l) + nbinpdf (m(l), n, p);
-          m(l) = m(l) + 1;
-        else
-          break;
-        endif
-      endwhile
-    else
-      n = n(k);
-      p = p(k);
-      while (1)
-        l = find (m <= x);
-        if (any (l))
-          y(l) = y(l) + nbinpdf (m(l), n(l), p(l));
-          m(l) = m(l) + 1;
-        else
-          break;
-        endif
-      endwhile
-    endif
-    cdf(k) = y;
+  k = (isnan (x) | isnan (n) | (n < 1) | (n == Inf) 
+       | (p < 0) | (p > 1) | isnan (p));
+  cdf(k) = NaN;
+
+  k = (x == Inf) & (n > 0) & (n < Inf) & (p >= 0) & (p <= 1);
+  cdf(k) = 1;
+
+  k = ((x >= 0) & (x < Inf) & (x == fix (x))
+       & (n > 0) & (n < Inf) & (p > 0) & (p <= 1));
+  if (isscalar (n) && isscalar (p))
+    cdf(k) = 1 - betainc (1-p, x(k)+1, n);
+  else
+    cdf(k) = 1 - betainc (1-p(k), x(k)+1, n(k));
   endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 1 2 Inf];
+%! y = [0 1/2 3/4 7/8 1];
+%!assert(nbincdf (x, ones(1,5), 0.5*ones(1,5)), y);
+%!assert(nbincdf (x, 1, 0.5*ones(1,5)), y);
+%!assert(nbincdf (x, ones(1,5), 0.5), y);
+%!assert(nbincdf ([x(1:3) 0 x(5)], [0 1 NaN 1.5 Inf], 0.5), [NaN 1/2 NaN nbinpdf(0,1.5,0.5) NaN], eps);
+%!assert(nbincdf (x, 1, 0.5*[-1 NaN 4 1 1]), [NaN NaN NaN y(4:5)]);
+%!assert(nbincdf ([x(1:2) NaN x(4:5)], 1, 0.5), [y(1:2) NaN y(4:5)]);
+
+%% Test class of input preserved
+%!assert(nbincdf ([x, NaN], 1, 0.5), [y, NaN]);
+%!assert(nbincdf (single([x, NaN]), 1, 0.5), single([y, NaN]));
+%!assert(nbincdf ([x, NaN], single(1), 0.5), single([y, NaN]));
+%!assert(nbincdf ([x, NaN], 1, single(0.5)), single([y, NaN]));
+
+%% Test input validation
+%!error nbincdf ()
+%!error nbincdf (1)
+%!error nbincdf (1,2)
+%!error nbincdf (1,2,3,4)
+%!error nbincdf (ones(3),ones(2),ones(2))
+%!error nbincdf (ones(2),ones(3),ones(2))
+%!error nbincdf (ones(2),ones(2),ones(3))
+%!error nbincdf (i, 2, 2)
+%!error nbincdf (2, i, 2)
+%!error nbincdf (2, 2, i)
+
--- a/scripts/statistics/distributions/nbininv.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/nbininv.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -18,10 +19,13 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} nbininv (@var{x}, @var{n}, @var{p})
-## For each element of @var{x}, compute the quantile at @var{x} of the
-## Pascal (negative binomial) distribution with parameters @var{n} and
-## @var{p}.
+## For each element of @var{x}, compute the quantile (the inverse of
+## the CDF) at @var{x} of the negative binomial distribution
+## with parameters @var{n} and @var{p}.
 ##
+## When @var{n} is integer this is the Pascal distribution.  When
+## @var{n} is extended to real numbers this is the Polya distribution.
+## 
 ## The number of failures in a Bernoulli experiment with success
 ## probability @var{p} before the @var{n}-th success follows this
 ## distribution.
@@ -36,58 +40,89 @@
     print_usage ();
   endif
 
-  if (!isscalar(n) || !isscalar(p))
+  if (!isscalar (n) || !isscalar (p))
     [retval, x, n, p] = common_size (x, n, p);
     if (retval > 0)
-      error ("nbininv: X, N and P must be of common size or scalar");
+      error ("nbininv: X, N, and P must be of common size or scalars");
     endif
   endif
 
-  inv = zeros (size (x));
-
-  k = find (isnan (x) | (x < 0) | (x > 1) | (n < 1) | (n == Inf)
-            | (n != round (n)) | (p < 0) | (p > 1));
-  if (any (k))
-    inv(k) = NaN;
+  if (iscomplex (x) || iscomplex (n) || iscomplex (p))
+    error ("nbininv: X, N, and P must not be complex");
   endif
 
-  k = find ((x == 1) & (n > 0) & (n < Inf) & (n == round (n))
-            & (p >= 0) & (p <= 1));
-  if (any (k))
-    inv(k) = Inf;
+  if (isa (x, "single") || isa (n, "single") || isa (p, "single"))
+    inv = zeros (size (x), "single");
+  else
+    inv = zeros (size (x));
   endif
 
+  k = (isnan (x) | (x < 0) | (x > 1) | isnan (n) | (n < 1) | (n == Inf)
+       | isnan (p) | (p < 0) | (p > 1));
+  inv(k) = NaN;
+
+  k = (x == 1) & (n > 0) & (n < Inf) & (p >= 0) & (p <= 1);
+  inv(k) = Inf;
+
   k = find ((x >= 0) & (x < 1) & (n > 0) & (n < Inf)
-            & (n == round (n)) & (p > 0) & (p <= 1));
-  if (any (k))
-    m = zeros (size (k));
-    x = x(k);
-    if (isscalar (n) && isscalar (p))
-      s = p ^ n * ones (size(k));
-      while (1)
-        l = find (s < x);
-        if (any (l))
-          m(l) = m(l) + 1;
-          s(l) = s(l) + nbinpdf (m(l), n, p);
-        else
-          break;
-        endif
-      endwhile
-    else
-      n = n(k);
-      p = p(k);
-      s = p .^ n;
-      while (1)
-        l = find (s < x);
-        if (any (l))
-          m(l) = m(l) + 1;
-          s(l) = s(l) + nbinpdf (m(l), n(l), p(l));
-        else
-          break;
-        endif
-      endwhile
-    endif
-    inv(k) = m;
+            & (p > 0) & (p <= 1));
+  m = zeros (size (k));
+  x = x(k);
+  if (isscalar (n) && isscalar (p))
+    s = p ^ n * ones (size (k));
+    while (1)
+      l = find (s < x);
+      if (any (l))
+        m(l) = m(l) + 1;
+        s(l) = s(l) + nbinpdf (m(l), n, p);
+      else
+        break;
+      endif
+    endwhile
+  else
+    n = n(k);
+    p = p(k);
+    s = p .^ n;
+    while (1)
+      l = find (s < x);
+      if (any (l))
+        m(l) = m(l) + 1;
+        s(l) = s(l) + nbinpdf (m(l), n(l), p(l));
+      else
+        break;
+      endif
+    endwhile
   endif
+  inv(k) = m;
 
 endfunction
+
+
+%!shared x
+%! x = [-1 0 3/4 1 2];
+%!assert(nbininv (x, ones(1,5), 0.5*ones(1,5)), [NaN 0 1 Inf NaN]);
+%!assert(nbininv (x, 1, 0.5*ones(1,5)), [NaN 0 1 Inf NaN]);
+%!assert(nbininv (x, ones(1,5), 0.5), [NaN 0 1 Inf NaN]);
+%!assert(nbininv (x, [1 0 NaN Inf 1], 0.5), [NaN NaN NaN NaN NaN]);
+%!assert(nbininv (x, [1 0 1.5 Inf 1], 0.5), [NaN NaN 2 NaN NaN]);
+%!assert(nbininv (x, 1, 0.5*[1 -Inf NaN Inf 1]), [NaN NaN NaN NaN NaN]);
+%!assert(nbininv ([x(1:2) NaN x(4:5)], 1, 0.5), [NaN 0 NaN Inf NaN]);
+
+%% Test class of input preserved
+%!assert(nbininv ([x, NaN], 1, 0.5), [NaN 0 1 Inf NaN NaN]);
+%!assert(nbininv (single([x, NaN]), 1, 0.5), single([NaN 0 1 Inf NaN NaN]));
+%!assert(nbininv ([x, NaN], single(1), 0.5), single([NaN 0 1 Inf NaN NaN]));
+%!assert(nbininv ([x, NaN], 1, single(0.5)), single([NaN 0 1 Inf NaN NaN]));
+
+%% Test input validation
+%!error nbininv ()
+%!error nbininv (1)
+%!error nbininv (1,2)
+%!error nbininv (1,2,3,4)
+%!error nbininv (ones(3),ones(2),ones(2))
+%!error nbininv (ones(2),ones(3),ones(2))
+%!error nbininv (ones(2),ones(2),ones(3))
+%!error nbininv (i, 2, 2)
+%!error nbininv (2, i, 2)
+%!error nbininv (2, 2, i)
+
--- a/scripts/statistics/distributions/nbinpdf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/nbinpdf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -19,9 +20,12 @@
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} nbinpdf (@var{x}, @var{n}, @var{p})
 ## For each element of @var{x}, compute the probability density function
-## (PDF) at @var{x} of the Pascal (negative binomial) distribution with
+## (PDF) at @var{x} of the negative binomial distribution with
 ## parameters @var{n} and @var{p}.
 ##
+## When @var{n} is integer this is the Pascal distribution.  When
+## @var{n} is extended to real numbers this is the Polya distribution.
+## 
 ## The number of failures in a Bernoulli experiment with success
 ## probability @var{p} before the @var{n}-th success follows this
 ## distribution.
@@ -36,36 +40,63 @@
     print_usage ();
   endif
 
-  if (!isscalar(n) || !isscalar(p))
+  if (!isscalar (n) || !isscalar (p))
     [retval, x, n, p] = common_size (x, n, p);
     if (retval > 0)
-      error ("nbinpdf: X, N and P must be of common size or scalar");
+      error ("nbinpdf: X, N, and P must be of common size or scalars");
     endif
   endif
 
-  pdf = zeros (size (x));
+  if (iscomplex (x) || iscomplex (n) || iscomplex (p))
+    error ("nbinpdf: X, N, and P must not be complex");
+  endif
 
-  k = find (isnan (x) | (n < 1) | (n == Inf) | (n != round (n))
-            | (p < 0) | (p > 1));
-  if (any (k))
-    pdf(k) = NaN;
+  if (isa (x, "single") || isa (n, "single") || isa (p, "single"))
+    pdf = NaN (size (x), "single");
+  else
+    pdf = NaN (size (x));
   endif
 
-  ## Just for the fun of it ...
-  k = find ((x == Inf) & (n > 0) & (n < Inf) & (n == round (n))
-            & (p == 0));
-  if (any (k))
-    pdf(k) = 1;
-  endif
+  ok = (x < Inf) & (x == fix (x)) & (n > 0) & (n < Inf) & (p >= 0) & (p <= 1);
+
+  k = (x < 0) & ok;
+  pdf(k) = 0;
 
-  k = find ((x >= 0) & (x < Inf) & (x == round (x)) & (n > 0)
-            & (n < Inf) & (n == round (n)) & (p > 0) & (p <= 1));
-  if (any (k))
-    if (isscalar (n) && isscalar (p))
-      pdf(k) = bincoeff (-n, x(k)) .* (p ^ n) .* ((p - 1) .^ x(k));
-    else
-      pdf(k) = bincoeff (-n(k), x(k)) .* (p(k) .^ n(k)) .* ((p(k) - 1) .^ x(k));
-    endif
+  k = (x >= 0) & ok;
+  if (isscalar (n) && isscalar (p))
+    pdf(k) = bincoeff (-n, x(k)) .* (p ^ n) .* ((p - 1) .^ x(k));
+  else
+    pdf(k) = bincoeff (-n(k), x(k)) .* (p(k) .^ n(k)) .* ((p(k) - 1) .^ x(k));
   endif
+  
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 1 2 Inf];
+%! y = [0 1/2 1/4 1/8 NaN];
+%!assert(nbinpdf (x, ones(1,5), 0.5*ones(1,5)), y);
+%!assert(nbinpdf (x, 1, 0.5*ones(1,5)), y);
+%!assert(nbinpdf (x, ones(1,5), 0.5), y);
+%!assert(nbinpdf (x, [0 1 NaN 1.5 Inf], 0.5), [NaN 1/2 NaN 1.875*0.5^1.5/4 NaN], eps);
+%!assert(nbinpdf (x, 1, 0.5*[-1 NaN 4 1 1]), [NaN NaN NaN y(4:5)]);
+%!assert(nbinpdf ([x, NaN], 1, 0.5), [y, NaN]);
+
+%% Test class of input preserved
+%!assert(nbinpdf (single([x, NaN]), 1, 0.5), single([y, NaN]));
+%!assert(nbinpdf ([x, NaN], single(1), 0.5), single([y, NaN]));
+%!assert(nbinpdf ([x, NaN], 1, single(0.5)), single([y, NaN]));
+
+%% Test input validation
+%!error nbinpdf ()
+%!error nbinpdf (1)
+%!error nbinpdf (1,2)
+%!error nbinpdf (1,2,3,4)
+%!error nbinpdf (ones(3),ones(2),ones(2))
+%!error nbinpdf (ones(2),ones(3),ones(2))
+%!error nbinpdf (ones(2),ones(2),ones(3))
+%!error nbinpdf (i, 2, 2)
+%!error nbinpdf (2, i, 2)
+%!error nbinpdf (2, 2, i)
+
--- a/scripts/statistics/distributions/nbinrnd.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/nbinrnd.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,85 +18,123 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} nbinrnd (@var{n}, @var{p}, @var{r}, @var{c})
-## @deftypefnx {Function File} {} nbinrnd (@var{n}, @var{p}, @var{sz})
-## Return an @var{r} by @var{c} matrix of random samples from the Pascal
-## (negative binomial) distribution with parameters @var{n} and @var{p}.
-## Both @var{n} and @var{p} must be scalar or of size @var{r} by @var{c}.
+## @deftypefn  {Function File} {} nbinrnd (@var{n}, @var{p})
+## @deftypefnx {Function File} {} nbinrnd (@var{n}, @var{p}, @var{r})
+## @deftypefnx {Function File} {} nbinrnd (@var{n}, @var{p}, @var{r}, @var{c}, @dots{})
+## @deftypefnx {Function File} {} nbinrnd (@var{n}, @var{p}, [@var{sz}])
+## Return a matrix of random samples from the negative binomial
+## distribution with parameters @var{n} and @var{p}.
 ##
-## If @var{r} and @var{c} are omitted, the size of the result matrix is
-## the common size of @var{n} and @var{p}.  Or if @var{sz} is a vector,
-## create a matrix of size @var{sz}.
+## When called with a single size argument, return a square matrix with
+## the dimension specified.  When called with more than one scalar argument the
+## first two arguments are taken as the number of rows and columns and any
+## further arguments specify additional matrix dimensions.  The size may also
+## be specified with a vector of dimensions @var{sz}.
+## 
+## If no size arguments are given then the result matrix is the common size of
+## @var{n} and @var{p}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Random deviates from the Pascal distribution
 
-function rnd = nbinrnd (n, p, r, c)
+function rnd = nbinrnd (n, p, varargin)
 
-  if (nargin > 1)
-    if (!isscalar(n) || !isscalar(p))
-      [retval, n, p] = common_size (n, p);
-      if (retval > 0)
-        error ("nbinrnd: N and P must be of common size or scalar");
-      endif
+  if (nargin < 2)
+    print_usage ();
+  endif
+
+  if (!isscalar (n) || !isscalar (p))
+    [retval, n, p] = common_size (n, p);
+    if (retval > 0)
+      error ("nbinrnd: N and P must be of common size or scalars");
     endif
   endif
 
-  if (nargin == 4)
-    if (! (isscalar (r) && (r > 0) && (r == round (r))))
-      error ("nbinrnd: R must be a positive integer");
-    endif
-    if (! (isscalar (c) && (c > 0) && (c == round (c))))
-      error ("nbinrnd: C must be a positive integer");
-    endif
-    sz = [r, c];
+  if (iscomplex (n) || iscomplex (p))
+    error ("nbinrnd: N and P must not be complex");
+  endif
 
-    if (any (size (n) != 1)
-        && ((length (size (n)) != length (sz)) || any (size (n) != sz)))
-      error ("nbinrnd: N and P must be scalar or of size [R, C]");
-    endif
-
+  if (nargin == 2)
+    sz = size (n);
   elseif (nargin == 3)
-    if (isscalar (r) && (r > 0))
-      sz = [r, r];
-    elseif (isvector(r) && all (r > 0))
-      sz = r(:)';
+    if (isscalar (varargin{1}) && varargin{1} >= 0)
+      sz = [varargin{1}, varargin{1}];
+    elseif (isrow (varargin{1}) && all (varargin{1} >= 0))
+      sz = varargin{1};
     else
-      error ("nbinrnd: R must be a positive integer or vector");
+      error ("nbinrnd: dimension vector must be row vector of non-negative integers");
     endif
+  elseif (nargin > 3)
+    if (any (cellfun (@(x) (!isscalar (x) || x < 0), varargin)))
+      error ("nbinrnd: dimensions must be non-negative integers");
+    endif
+    sz = [varargin{:}];
+  endif
 
-    if (any (size (n) != 1)
-        && ((length (size (n)) != length (sz)) || any (size (n) != sz)))
-      error ("nbinrnd: N and P must be scalar or of size SZ");
-    endif
-  elseif (nargin == 2)
-    sz = size(n);
+  if (!isscalar (n) && !isequal (size (n), sz))
+    error ("nbinrnd: N and P must be scalar or of size SZ");
+  endif
+
+  if (isa (n, "single") || isa (p, "single"))
+    cls = "single";
   else
-    print_usage ();
+    cls = "double";
   endif
 
   if (isscalar (n) && isscalar (p))
-    if ((n < 1) || (n == Inf) || (n != round (n)) || (p <= 0) || (p > 1));
-      rnd = NaN (sz);
-    elseif ((n > 0) && (n < Inf) && (n == round (n))
-            && (p > 0) && (p <= 1))
+    if ((n > 0) && (n < Inf) && (p > 0) && (p <= 1))
       rnd = randp ((1 - p) ./ p .* randg (n, sz));
+      if (strcmp (cls, "single"))
+        rnd = single (rnd);
+      endif
+    elseif ((n > 0) && (n < Inf) && (p == 0))
+      rnd = zeros (sz, cls);
     else
-      rnd = zeros (sz);
+      rnd = NaN (sz, cls);
     endif
   else
-    rnd = zeros (sz);
+    rnd = NaN (sz, cls);
 
-    k = find ((n < 1) | (n == Inf) | (n != round (n)) | (p <= 0) | (p > 1));
-    if (any (k))
-      rnd(k) = NaN;
-    endif
+    k = (n > 0) & (n < Inf) & (p == 0);
+    rnd(k) = 0;
 
-    k = find ((n > 0) & (n < Inf) & (n == round (n)) & (p > 0) & (p <= 1));
-    if (any (k))
-      rnd(k) = randp ((1 - p(k)) ./ p(k) .* randg (n(k), size(k)));
-    endif
+    k = (n > 0) & (n < Inf) & (p > 0) & (p <= 1);
+    rnd(k) = randp ((1 - p(k)) ./ p(k) .* randg (n(k)));
   endif
 
 endfunction
+
+
+%!assert(size (nbinrnd (2, 1/2)), [1, 1]);
+%!assert(size (nbinrnd (2*ones(2,1), 1/2)), [2, 1]);
+%!assert(size (nbinrnd (2*ones(2,2), 1/2)), [2, 2]);
+%!assert(size (nbinrnd (2, 1/2*ones(2,1))), [2, 1]);
+%!assert(size (nbinrnd (2, 1/2*ones(2,2))), [2, 2]);
+%!assert(size (nbinrnd (2, 1/2, 3)), [3, 3]);
+%!assert(size (nbinrnd (2, 1/2, [4 1])), [4, 1]);
+%!assert(size (nbinrnd (2, 1/2, 4, 1)), [4, 1]);
+
+%% Test class of input preserved
+%!assert(class (nbinrnd (2, 1/2)), "double");
+%!assert(class (nbinrnd (single(2), 1/2)), "single");
+%!assert(class (nbinrnd (single([2 2]), 1/2)), "single");
+%!assert(class (nbinrnd (2, single(1/2))), "single");
+%!assert(class (nbinrnd (2, single([1/2 1/2]))), "single");
+
+%% Test input validation
+%!error nbinrnd ()
+%!error nbinrnd (1)
+%!error nbinrnd (ones(3),ones(2))
+%!error nbinrnd (ones(2),ones(3))
+%!error nbinrnd (i, 2)
+%!error nbinrnd (2, i)
+%!error nbinrnd (1,2, -1)
+%!error nbinrnd (1,2, ones(2))
+%!error nbinrnd (1, 2, [2 -1 2])
+%!error nbinrnd (1,2, 1, ones(2))
+%!error nbinrnd (1,2, 1, -1)
+%!error nbinrnd (ones(2,2), 2, 3)
+%!error nbinrnd (ones(2,2), 2, [3, 2])
+%!error nbinrnd (ones(2,2), 2, 2, 3)
+
--- a/scripts/statistics/distributions/normcdf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/normcdf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,56 +18,82 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} normcdf (@var{x}, @var{m}, @var{s})
+## @deftypefn  {Function File} {} normcdf (@var{x})
+## @deftypefnx {Function File} {} normcdf (@var{x}, @var{mu}, @var{sigma})
 ## For each element of @var{x}, compute the cumulative distribution
 ## function (CDF) at @var{x} of the normal distribution with mean
-## @var{m} and standard deviation @var{s}.
+## @var{mu} and standard deviation @var{sigma}.
 ##
-## Default values are @var{m} = 0, @var{s} = 1.
+## Default values are @var{mu} = 0, @var{sigma} = 1.
 ## @end deftypefn
 
 ## Author: TT <Teresa.Twaroch@ci.tuwien.ac.at>
 ## Description: CDF of the normal distribution
 
-function cdf = normcdf (x, m, s)
+function cdf = normcdf (x, mu = 0, sigma = 1)
 
-  if (! ((nargin == 1) || (nargin == 3)))
+  if (nargin != 1 && nargin != 3)
     print_usage ();
   endif
 
-  if (nargin == 1)
-    m = 0;
-    s = 1;
-  endif
-
-  if (!isscalar (m) || !isscalar (s))
-    [retval, x, m, s] = common_size (x, m, s);
+  if (!isscalar (mu) || !isscalar (sigma))
+    [retval, x, mu, sigma] = common_size (x, mu, sigma);
     if (retval > 0)
-      error ("normcdf: X, M and S must be of common size or scalar");
+      error ("normcdf: X, MU, and SIGMA must be of common size or scalars");
     endif
   endif
 
-  sz = size (x);
-  cdf = zeros (sz);
+  if (iscomplex (x) || iscomplex (mu) || iscomplex (sigma))
+    error ("normcdf: X, MU, and SIGMA must not be complex");
+  endif
 
-  if (isscalar (m) && isscalar(s))
-    if (find (isinf (m) | isnan (m) | !(s > 0) | !(s < Inf)))
-      cdf = NaN (sz);
+  if (isa (x, "single") || isa (mu, "single") || isa (sigma, "single"));
+    cdf = zeros (size (x), "single");
+  else
+    cdf = zeros (size (x));
+  endif
+
+  if (isscalar (mu) && isscalar (sigma))
+    if (!isinf (mu) && !isnan (mu) && (sigma > 0) && (sigma < Inf))
+      cdf = stdnormal_cdf ((x - mu) / sigma);
     else
-      cdf =  stdnormal_cdf ((x - m) ./ s);
+      cdf = NaN (size (x), class (cdf));
     endif
   else
-    k = find (isinf (m) | isnan (m) | !(s > 0) | !(s < Inf));
-    if (any (k))
-      cdf(k) = NaN;
-    endif
+    k = isinf (mu) | isnan (mu) | !(sigma > 0) | !(sigma < Inf);
+    cdf(k) = NaN;
 
-    k = find (!isinf (m) & !isnan (m) & (s > 0) & (s < Inf));
-    if (any (k))
-      cdf(k) = stdnormal_cdf ((x(k) - m(k)) ./ s(k));
-    endif
+    k = ! k;
+    cdf(k) = stdnormal_cdf ((x(k) - mu(k)) ./ sigma(k));
   endif
 
-  cdf((s == 0) & (x == m)) = 0.5;
+endfunction
+
+
+%!shared x,y
+%! x = [-Inf 1 2 Inf];
+%! y = [0, 0.5, 1/2*(1+erf(1/sqrt(2))), 1];
+%!assert(normcdf (x, ones(1,4), ones(1,4)), y);
+%!assert(normcdf (x, 1, ones(1,4)), y);
+%!assert(normcdf (x, ones(1,4), 1), y);
+%!assert(normcdf (x, [0 -Inf NaN Inf], 1), [y(1) NaN NaN NaN]);
+%!assert(normcdf (x, 1, [Inf NaN -1 0]), [NaN NaN NaN NaN]);
+%!assert(normcdf ([x(1:2) NaN x(4)], 1, 1), [y(1:2) NaN y(4)]);
 
-endfunction
+%% Test class of input preserved
+%!assert(normcdf ([x, NaN], 1, 1), [y, NaN]);
+%!assert(normcdf (single([x, NaN]), 1, 1), single([y, NaN]), eps("single"));
+%!assert(normcdf ([x, NaN], single(1), 1), single([y, NaN]), eps("single"));
+%!assert(normcdf ([x, NaN], 1, single(1)), single([y, NaN]), eps("single"));
+
+%% Test input validation
+%!error normcdf ()
+%!error normcdf (1,2)
+%!error normcdf (1,2,3,4)
+%!error normcdf (ones(3),ones(2),ones(2))
+%!error normcdf (ones(2),ones(3),ones(2))
+%!error normcdf (ones(2),ones(2),ones(3))
+%!error normcdf (i, 2, 2)
+%!error normcdf (2, i, 2)
+%!error normcdf (2, 2, i)
+
--- a/scripts/statistics/distributions/norminv.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/norminv.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,62 +18,76 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} norminv (@var{x}, @var{m}, @var{s})
+## @deftypefn  {Function File} {} norminv (@var{x})
+## @deftypefnx {Function File} {} norminv (@var{x}, @var{mu}, @var{sigma})
 ## For each element of @var{x}, compute the quantile (the inverse of the
-## CDF) at @var{x} of the normal distribution with mean @var{m} and
-## standard deviation @var{s}.
+## CDF) at @var{x} of the normal distribution with mean @var{mu} and
+## standard deviation @var{sigma}.
 ##
-## Default values are @var{m} = 0, @var{s} = 1.
+## Default values are @var{mu} = 0, @var{sigma} = 1.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Quantile function of the normal distribution
 
-function inv = norminv (x, m, s)
+function inv = norminv (x, mu = 0, sigma = 1)
 
   if (nargin != 1 && nargin != 3)
     print_usage ();
   endif
 
-  if (nargin == 1)
-    m = 0;
-    s = 1;
-  endif
-
-  if (!isscalar (m) || !isscalar (s))
-    [retval, x, m, s] = common_size (x, m, s);
+  if (!isscalar (mu) || !isscalar (sigma))
+    [retval, x, mu, sigma] = common_size (x, mu, sigma);
     if (retval > 0)
-      error ("norminv: X, M and S must be of common size or scalars");
+      error ("norminv: X, MU, and SIGMA must be of common size or scalars");
     endif
   endif
 
-  sz = size (x);
-  inv = zeros (sz);
+  if (iscomplex (x) || iscomplex (mu) || iscomplex (sigma))
+    error ("norminv: X, MU, and SIGMA must not be complex");
+  endif
 
-  if (isscalar (m) && isscalar (s))
-    if (find (isinf (m) | isnan (m) | !(s > 0) | !(s < Inf)))
-      inv = NaN (sz);
-    else
-      inv =  m + s .* stdnormal_inv (x);
+  if (isa (x, "single") || isa (mu, "single") || isa (sigma, "single"))
+    inv = NaN (size (x), "single");
+  else
+    inv = NaN (size (x));
+  endif
+
+  if (isscalar (mu) && isscalar (sigma))
+    if (!isinf (mu) && !isnan (mu) && (sigma > 0) && (sigma < Inf))
+      inv =  mu + sigma * stdnormal_inv (x);
     endif
   else
-    k = find (isinf (m) | isnan (m) | !(s > 0) | !(s < Inf));
-    if (any (k))
-      inv(k) = NaN;
-    endif
-
-    k = find (!isinf (m) & !isnan (m) & (s > 0) & (s < Inf));
-    if (any (k))
-      inv(k) = m(k) + s(k) .* stdnormal_inv (x(k));
-    endif
+    k = !isinf (mu) & !isnan (mu) & (sigma > 0) & (sigma < Inf);
+    inv(k) = mu(k) + sigma(k) .* stdnormal_inv (x(k));
   endif
 
-  k = find ((s == 0) & (x > 0) & (x < 1));
-  if (any (k))
-    inv(k) = m(k);
-  endif
+endfunction
+
+
+%!shared x
+%! x = [-1 0 0.5 1 2];
+%!assert(norminv (x, ones(1,5), ones(1,5)), [NaN -Inf 1 Inf NaN]);
+%!assert(norminv (x, 1, ones(1,5)), [NaN -Inf 1 Inf NaN]);
+%!assert(norminv (x, ones(1,5), 1), [NaN -Inf 1 Inf NaN]);
+%!assert(norminv (x, [1 -Inf NaN Inf 1], 1), [NaN NaN NaN NaN NaN]);
+%!assert(norminv (x, 1, [1 0 NaN Inf 1]), [NaN NaN NaN NaN NaN]);
+%!assert(norminv ([x(1:2) NaN x(4:5)], 1, 1), [NaN -Inf NaN Inf NaN]);
 
-  inv((s == 0) & (x == 0)) = -Inf;
-  inv((s == 0) & (x == 1)) = Inf;
+%% Test class of input preserved
+%!assert(norminv ([x, NaN], 1, 1), [NaN -Inf 1 Inf NaN NaN]);
+%!assert(norminv (single([x, NaN]), 1, 1), single([NaN -Inf 1 Inf NaN NaN]));
+%!assert(norminv ([x, NaN], single(1), 1), single([NaN -Inf 1 Inf NaN NaN]));
+%!assert(norminv ([x, NaN], 1, single(1)), single([NaN -Inf 1 Inf NaN NaN]));
 
-endfunction
+%% Test input validation
+%!error norminv ()
+%!error norminv (1,2)
+%!error norminv (1,2,3,4)
+%!error norminv (ones(3),ones(2),ones(2))
+%!error norminv (ones(2),ones(3),ones(2))
+%!error norminv (ones(2),ones(2),ones(3))
+%!error norminv (i, 2, 2)
+%!error norminv (2, i, 2)
+%!error norminv (2, 2, i)
+
--- a/scripts/statistics/distributions/normpdf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/normpdf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,57 +18,81 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} normpdf (@var{x}, @var{m}, @var{s})
+## @deftypefn  {Function File} {} normpdf (@var{x})
+## @deftypefnx {Function File} {} normpdf (@var{x}, @var{mu}, @var{sigma})
 ## For each element of @var{x}, compute the probability density function
-## (PDF) at @var{x} of the normal distribution with mean @var{m} and
-## standard deviation @var{s}.
+## (PDF) at @var{x} of the normal distribution with mean @var{mu} and
+## standard deviation @var{sigma}.
 ##
-## Default values are @var{m} = 0, @var{s} = 1.
+## Default values are @var{mu} = 0, @var{sigma} = 1.
 ## @end deftypefn
 
 ## Author: TT <Teresa.Twaroch@ci.tuwien.ac.at>
 ## Description: PDF of the normal distribution
 
-function pdf = normpdf (x, m, s)
+function pdf = normpdf (x, mu = 0, sigma = 1)
 
   if (nargin != 1 && nargin != 3)
     print_usage ();
   endif
 
-  if (nargin == 1)
-    m = 0;
-    s = 1;
-  endif
-
-  if (!isscalar (m) || !isscalar (s))
-    [retval, x, m, s] = common_size (x, m, s);
+  if (!isscalar (mu) || !isscalar (sigma))
+    [retval, x, mu, sigma] = common_size (x, mu, sigma);
     if (retval > 0)
-      error ("normpdf: X, M and S must be of common size or scalars");
+      error ("normpdf: X, MU, and SIGMA must be of common size or scalars");
     endif
   endif
 
-  sz = size (x);
-  pdf = zeros (sz);
+  if (iscomplex (x) || iscomplex (mu) || iscomplex (sigma))
+    error ("normpdf: X, MU, and SIGMA must not be complex");
+  endif
 
-  if (isscalar (m) && isscalar (s))
-    if (find (isinf (m) | isnan (m) | !(s > 0) | !(s < Inf)))
-      pdf = NaN (sz);
+  if (isa (x, "single") || isa (mu, "single") || isa (sigma, "single"))
+    pdf = zeros (size (x), "single");
+  else
+    pdf = zeros (size (x));
+  endif
+
+  if (isscalar (mu) && isscalar (sigma))
+    if (!isinf (mu) && !isnan (mu) && (sigma > 0) && (sigma < Inf))
+      pdf = stdnormal_pdf ((x - mu) / sigma) / sigma;
     else
-      pdf = stdnormal_pdf ((x - m) ./ s) ./ s;
+      pdf = NaN (size (x), class (pdf));
     endif
   else
-    k = find (isinf (m) | isnan (m) | !(s > 0) | !(s < Inf));
-    if (any (k))
-      pdf(k) = NaN;
-    endif
+    k = isinf (mu) | !(sigma > 0) | !(sigma < Inf);
+    pdf(k) = NaN;
 
-    k = find (!isinf (m) & !isnan (m) & (s > 0) & (s < Inf));
-    if (any (k))
-      pdf(k) = stdnormal_pdf ((x(k) - m(k)) ./ s(k)) ./ s(k);
-    endif
+    k = !isinf (mu) & (sigma > 0) & (sigma < Inf);
+    pdf(k) = stdnormal_pdf ((x(k) - mu(k)) ./ sigma(k)) ./ sigma(k);
   endif
 
-  pdf((s == 0) & (x == m)) = Inf;
-  pdf((s == 0) & ((x < m) | (x > m))) = 0;
+endfunction
+
+
+%!shared x,y
+%! x = [-Inf 1 2 Inf];
+%! y = 1/sqrt(2*pi)*exp (-(x-1).^2/2);
+%!assert(normpdf (x, ones(1,4), ones(1,4)), y);
+%!assert(normpdf (x, 1, ones(1,4)), y);
+%!assert(normpdf (x, ones(1,4), 1), y);
+%!assert(normpdf (x, [0 -Inf NaN Inf], 1), [y(1) NaN NaN NaN]);
+%!assert(normpdf (x, 1, [Inf NaN -1 0]), [NaN NaN NaN NaN]);
+%!assert(normpdf ([x, NaN], 1, 1), [y, NaN]);
 
-endfunction
+%% Test class of input preserved
+%!assert(normpdf (single([x, NaN]), 1, 1), single([y, NaN]), eps("single"));
+%!assert(normpdf ([x, NaN], single(1), 1), single([y, NaN]), eps("single"));
+%!assert(normpdf ([x, NaN], 1, single(1)), single([y, NaN]), eps("single"));
+
+%% Test input validation
+%!error normpdf ()
+%!error normpdf (1,2)
+%!error normpdf (1,2,3,4)
+%!error normpdf (ones(3),ones(2),ones(2))
+%!error normpdf (ones(2),ones(3),ones(2))
+%!error normpdf (ones(2),ones(2),ones(3))
+%!error normpdf (i, 2, 2)
+%!error normpdf (2, i, 2)
+%!error normpdf (2, 2, i)
+
--- a/scripts/statistics/distributions/normrnd.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/normrnd.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,75 +18,114 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} normrnd (@var{m}, @var{s}, @var{r}, @var{c})
-## @deftypefnx {Function File} {} normrnd (@var{m}, @var{s}, @var{sz})
-## Return an @var{r} by @var{c}  or @code{size (@var{sz})} matrix of
-## random samples from the normal distribution with parameters mean @var{m}
-## and standard deviation @var{s}.  Both @var{m} and @var{s} must be scalar
-## or of size @var{r} by @var{c}.
+## @deftypefn  {Function File} {} normrnd (@var{mu}, @var{sigma})
+## @deftypefnx {Function File} {} normrnd (@var{mu}, @var{sigma}, @var{r})
+## @deftypefnx {Function File} {} normrnd (@var{mu}, @var{sigma}, @var{r}, @var{c}, @dots{})
+## @deftypefnx {Function File} {} normrnd (@var{mu}, @var{sigma}, [@var{sz}])
+## Return a matrix of random samples from the normal distribution with
+## parameters mean @var{mu} and standard deviation @var{sigma}.
 ##
-## If @var{r} and @var{c} are omitted, the size of the result matrix is
-## the common size of @var{m} and @var{s}.
+## When called with a single size argument, return a square matrix with
+## the dimension specified.  When called with more than one scalar argument the
+## first two arguments are taken as the number of rows and columns and any
+## further arguments specify additional matrix dimensions.  The size may also
+## be specified with a vector of dimensions @var{sz}.
+## 
+## If no size arguments are given then the result matrix is the common size of
+## @var{mu} and @var{sigma}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Random deviates from the normal distribution
 
-function rnd = normrnd (m, s, r, c)
+function rnd = normrnd (mu, sigma, varargin)
 
-  if (nargin > 1)
-    if (!isscalar (m) || !isscalar (s))
-      [retval, m, s] = common_size (m, s);
-      if (retval > 0)
-        error ("normrnd: M and S must be of common size or scalar");
-      endif
+  if (nargin < 2)
+    print_usage ();
+  endif
+
+  if (!isscalar (mu) || !isscalar (sigma))
+    [retval, mu, sigma] = common_size (mu, sigma);
+    if (retval > 0)
+      error ("normrnd: mu and sigma must be of common size or scalars");
     endif
   endif
 
-  if (nargin == 4)
-    if (! (isscalar (r) && (r > 0) && (r == round (r))))
-      error ("normrnd: R must be a positive integer");
-    endif
-    if (! (isscalar (c) && (c > 0) && (c == round (c))))
-      error ("normrnd: C must be a positive integer");
-    endif
-    sz = [r, c];
+  if (iscomplex (mu) || iscomplex (sigma))
+    error ("normrnd: MU and SIGMA must not be complex");
+  endif
 
-    if (any (size (m) != 1)
-        && (length (size (m)) != length (sz) || any (size (m) != sz)))
-      error ("normrnd: M and S must be scalar or of size [R, C]");
-    endif
+  if (nargin == 2)
+    sz = size (mu);
   elseif (nargin == 3)
-    if (isscalar (r) && (r > 0))
-      sz = [r, r];
-    elseif (isvector(r) && all (r > 0))
-      sz = r(:)';
+    if (isscalar (varargin{1}) && varargin{1} >= 0)
+      sz = [varargin{1}, varargin{1}];
+    elseif (isrow (varargin{1}) && all (varargin{1} >= 0))
+      sz = varargin{1};
     else
-      error ("normrnd: R must be a positive integer or vector");
+      error ("normrnd: dimension vector must be row vector of non-negative integers");
     endif
-
-    if (any (size (m) != 1)
-        && (length (size (m)) != length (sz) || any (size (m) != sz)))
-      error ("normrnd: M and S must be scalar or of size SZ");
+  elseif (nargin > 3)
+    if (any (cellfun (@(x) (!isscalar (x) || x < 0), varargin)))
+      error ("normrnd: dimensions must be non-negative integers");
     endif
-  elseif (nargin == 2)
-    sz = size(m);
-  else
-    print_usage ();
+    sz = [varargin{:}];
   endif
 
-  if (isscalar (m) && isscalar (s))
-    if (find (isnan (m) | isinf (m) | !(s > 0) | !(s < Inf)))
-      rnd = NaN (sz);
+  if (!isscalar (mu) && !isequal (size (mu), sz))
+    error ("normrnd: mu and sigma must be scalar or of size SZ");
+  endif
+
+  if (isa (mu, "single") || isa (sigma, "single"))
+    cls = "single";
+  else
+    cls = "double";
+  endif
+
+  if (isscalar (mu) && isscalar (sigma))
+    if (!isnan (mu) && !isinf (mu) && (sigma > 0) && (sigma < Inf))
+      rnd =  mu + sigma * randn (sz);
     else
-      rnd =  m + s .* randn (sz);
+      rnd = NaN (sz, cls);
     endif
   else
-    rnd = m + s .* randn (sz);
-    k = find (isnan (m) | isinf (m) | !(s > 0) | !(s < Inf));
-    if (any (k))
-      rnd(k) = NaN;
-    endif
+    rnd = mu + sigma .* randn (sz);
+    k = isnan (mu) | isinf (mu) | !(sigma > 0) | !(sigma < Inf);
+    rnd(k) = NaN;
   endif
 
 endfunction
+
+
+%!assert(size (normrnd (1,2)), [1, 1]);
+%!assert(size (normrnd (ones(2,1), 2)), [2, 1]);
+%!assert(size (normrnd (ones(2,2), 2)), [2, 2]);
+%!assert(size (normrnd (1, 2*ones(2,1))), [2, 1]);
+%!assert(size (normrnd (1, 2*ones(2,2))), [2, 2]);
+%!assert(size (normrnd (1, 2, 3)), [3, 3]);
+%!assert(size (normrnd (1, 2, [4 1])), [4, 1]);
+%!assert(size (normrnd (1, 2, 4, 1)), [4, 1]);
+
+%% Test class of input preserved
+%!assert(class (normrnd (1, 2)), "double");
+%!assert(class (normrnd (single(1), 2)), "single");
+%!assert(class (normrnd (single([1 1]), 2)), "single");
+%!assert(class (normrnd (1, single(2))), "single");
+%!assert(class (normrnd (1, single([2 2]))), "single");
+
+%% Test input validation
+%!error normrnd ()
+%!error normrnd (1)
+%!error normrnd (ones(3),ones(2))
+%!error normrnd (ones(2),ones(3))
+%!error normrnd (i, 2)
+%!error normrnd (2, i)
+%!error normrnd (1,2, -1)
+%!error normrnd (1,2, ones(2))
+%!error normrnd (1, 2, [2 -1 2])
+%!error normrnd (1,2, 1, ones(2))
+%!error normrnd (1,2, 1, -1)
+%!error normrnd (ones(2,2), 2, 3)
+%!error normrnd (ones(2,2), 2, [3, 2])
+%!error normrnd (ones(2,2), 2, 2, 3)
+
--- a/scripts/statistics/distributions/poisscdf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/poisscdf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -35,29 +36,55 @@
   if (!isscalar (lambda))
     [retval, x, lambda] = common_size (x, lambda);
     if (retval > 0)
-      error ("poisscdf: X and LAMBDA must be of common size or scalar");
+      error ("poisscdf: X and LAMBDA must be of common size or scalars");
     endif
   endif
 
-  cdf = zeros (size (x));
+  if (iscomplex (x) || iscomplex (lambda))
+    error ("poisscdf: X and LAMBDA must not be complex");
+  endif
 
-  k = find (isnan (x) | !(lambda > 0));
-  if (any (k))
-    cdf(k) = NaN;
+  if (isa (x, "single") || isa (lambda, "single"))
+    cdf = zeros (size (x), "single");
+  else
+    cdf = zeros (size (x));
   endif
 
-  k = find ((x == Inf) & (lambda > 0));
-  if (any (k))
-    cdf(k) = 1;
-  endif
+  k = isnan (x) | !(lambda > 0);
+  cdf(k) = NaN;
+
+  k = (x == Inf) & (lambda > 0);
+  cdf(k) = 1;
 
-  k = find ((x >= 0) & (x < Inf) & (lambda > 0));
-  if (any (k))
-    if (isscalar (lambda))
-      cdf(k) = 1 - gammainc (lambda, floor (x(k)) + 1);
-    else
-      cdf(k) = 1 - gammainc (lambda(k), floor (x(k)) + 1);
-    endif
+  k = (x >= 0) & (x < Inf) & (lambda > 0);
+  if (isscalar (lambda))
+    cdf(k) = 1 - gammainc (lambda, floor (x(k)) + 1);
+  else
+    cdf(k) = 1 - gammainc (lambda(k), floor (x(k)) + 1);
   endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 1 2 Inf];
+%! y = [0, gammainc(1, (x(2:4) +1), 'upper'), 1];
+%!assert(poisscdf (x, ones(1,5)), y);
+%!assert(poisscdf (x, 1), y);
+%!assert(poisscdf (x, [1 0 NaN 1 1]), [y(1) NaN NaN y(4:5)]);
+%!assert(poisscdf ([x(1:2) NaN Inf x(5)], 1), [y(1:2) NaN 1 y(5)]);
+
+%% Test class of input preserved
+%!assert(poisscdf ([x, NaN], 1), [y, NaN]);
+%!assert(poisscdf (single([x, NaN]), 1), single([y, NaN]), eps("single"));
+%!assert(poisscdf ([x, NaN], single(1)), single([y, NaN]), eps("single"));
+
+%% Test input validation
+%!error poisscdf ()
+%!error poisscdf (1)
+%!error poisscdf (1,2,3)
+%!error poisscdf (ones(3),ones(2))
+%!error poisscdf (ones(2),ones(3))
+%!error poisscdf (i, 2)
+%!error poisscdf (2, i)
+
--- a/scripts/statistics/distributions/poissinv.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/poissinv.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -18,7 +19,7 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} poissinv (@var{x}, @var{lambda})
-## For each component of @var{x}, compute the quantile (the inverse of
+## For each element of @var{x}, compute the quantile (the inverse of
 ## the CDF) at @var{x} of the Poisson distribution with parameter
 ## @var{lambda}.
 ## @end deftypefn
@@ -35,42 +36,68 @@
   if (!isscalar (lambda))
     [retval, x, lambda] = common_size (x, lambda);
     if (retval > 0)
-      error ("poissinv: X and LAMBDA must be of common size or scalar");
+      error ("poissinv: X and LAMBDA must be of common size or scalars");
     endif
   endif
 
-  inv = zeros (size (x));
-
-  k = find ((x < 0) | (x > 1) | isnan (x) | !(lambda > 0));
-  if (any (k))
-    inv(k) = NaN;
+  if (iscomplex (x) || iscomplex (lambda))
+    error ("poissinv: X and LAMBDA must not be complex");
   endif
 
-  k = find ((x == 1) & (lambda > 0));
-  if (any (k))
-    inv(k) = Inf;
+  if (isa (x, "single") || isa (lambda, "single"))
+    inv = zeros (size (x), "single");
+  else
+    inv = zeros (size (x));
   endif
 
+  k = (x < 0) | (x > 1) | isnan (x) | !(lambda > 0);
+  inv(k) = NaN;
+
+  k = (x == 1) & (lambda > 0);
+  inv(k) = Inf;
+
   k = find ((x > 0) & (x < 1) & (lambda > 0));
-  if (any (k))
-    if (isscalar (lambda))
-      cdf = exp (-lambda) * ones (size (k));
+  if (isscalar (lambda))
+    cdf = exp (-lambda) * ones (size (k));
+  else
+    cdf = exp (-lambda(k));
+  endif
+  
+  while (1)
+    m = find (cdf < x(k));
+    if (any (m))
+      inv(k(m)) += 1;
+      if (isscalar (lambda))
+        cdf(m) = cdf(m) + poisspdf (inv(k(m)), lambda);
+      else
+        cdf(m) = cdf(m) + poisspdf (inv(k(m)), lambda(k(m)));
+      endif
     else
-      cdf = exp (-lambda(k));
+      break;
     endif
-    while (1)
-      m = find (cdf < x(k));
-      if (any (m))
-        inv(k(m)) = inv(k(m)) + 1;
-        if (isscalar (lambda))
-          cdf(m) = cdf(m) + poisspdf (inv(k(m)), lambda);
-        else
-          cdf(m) = cdf(m) + poisspdf (inv(k(m)), lambda(k(m)));
-        endif
-      else
-        break;
-      endif
-    endwhile
-  endif
+  endwhile
 
 endfunction
+
+
+%!shared x
+%! x = [-1 0 0.5 1 2];
+%!assert(poissinv (x, ones(1,5)), [NaN 0 1 Inf NaN]);
+%!assert(poissinv (x, 1), [NaN 0 1 Inf NaN]);
+%!assert(poissinv (x, [1 0 NaN 1 1]), [NaN NaN NaN Inf NaN]);
+%!assert(poissinv ([x(1:2) NaN x(4:5)], 1), [NaN 0 NaN Inf NaN]);
+
+%% Test class of input preserved
+%!assert(poissinv ([x, NaN], 1), [NaN 0 1 Inf NaN NaN]);
+%!assert(poissinv (single([x, NaN]), 1), single([NaN 0 1 Inf NaN NaN]));
+%!assert(poissinv ([x, NaN], single(1)), single([NaN 0 1 Inf NaN NaN]));
+
+%% Test input validation
+%!error poissinv ()
+%!error poissinv (1)
+%!error poissinv (1,2,3)
+%!error poissinv (ones(3),ones(2))
+%!error poissinv (ones(2),ones(3))
+%!error poissinv (i, 2)
+%!error poissinv (2, i)
+
--- a/scripts/statistics/distributions/poisspdf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/poisspdf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -34,24 +35,51 @@
   if (!isscalar (lambda))
     [retval, x, lambda] = common_size (x, lambda);
     if (retval > 0)
-      error ("poisspdf: X and LAMBDA must be of common size or scalar");
+      error ("poisspdf: X and LAMBDA must be of common size or scalars");
     endif
   endif
 
-  pdf = zeros (size (x));
-
-  k = find (!(lambda > 0) | isnan (x));
-  if (any (k))
-    pdf(k) = NaN;
+  if (iscomplex (x) || iscomplex (lambda))
+    error ("poisspdf: X and LAMBDA must not be complex");
   endif
 
-  k = find ((x >= 0) & (x < Inf) & (x == round (x)) & (lambda > 0));
-  if (any (k))
-    if (isscalar (lambda))
-      pdf(k) = exp (x(k) .* log (lambda) - lambda - gammaln (x(k) + 1));
-    else
-      pdf(k) = exp (x(k) .* log (lambda(k)) - lambda(k) - gammaln (x(k) + 1));
-    endif
+  if (isa (x, "single") || isa (lambda, "single"))
+    pdf = zeros (size (x), "single");
+  else
+    pdf = zeros (size (x));
+  endif
+
+  k = isnan (x) | !(lambda > 0);
+  pdf(k) = NaN;
+
+  k = (x >= 0) & (x < Inf) & (x == fix (x)) & (lambda > 0);
+  if (isscalar (lambda))
+    pdf(k) = exp (x(k) * log (lambda) - lambda - gammaln (x(k) + 1));
+  else
+    pdf(k) = exp (x(k) .* log (lambda(k)) - lambda(k) - gammaln (x(k) + 1));
   endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 1 2 Inf];
+%! y = [0, exp(-1)*[1 1 0.5], 0];
+%!assert(poisspdf (x, ones(1,5)), y, eps);
+%!assert(poisspdf (x, 1), y, eps);
+%!assert(poisspdf (x, [1 0 NaN 1 1]), [y(1) NaN NaN y(4:5)], eps);
+%!assert(poisspdf ([x, NaN], 1), [y, NaN], eps);
+
+%% Test class of input preserved
+%!assert(poisspdf (single([x, NaN]), 1), single([y, NaN]), eps("single"));
+%!assert(poisspdf ([x, NaN], single(1)), single([y, NaN]), eps("single"));
+
+%% Test input validation
+%!error poisspdf ()
+%!error poisspdf (1)
+%!error poisspdf (1,2,3)
+%!error poisspdf (ones(3),ones(2))
+%!error poisspdf (ones(2),ones(3))
+%!error poisspdf (i, 2)
+%!error poisspdf (2, i)
+
--- a/scripts/statistics/distributions/poissrnd.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/poissrnd.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,73 +18,103 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} poissrnd (@var{lambda}, @var{r}, @var{c})
-## Return an @var{r} by @var{c} matrix of random samples from the
-## Poisson distribution with parameter @var{lambda}, which must be a
-## scalar or of size @var{r} by @var{c}.
+## @deftypefn  {Function File} {} poissrnd (@var{lambda})
+## @deftypefnx {Function File} {} poissrnd (@var{lambda}, @var{r})
+## @deftypefnx {Function File} {} poissrnd (@var{lambda}, @var{r}, @var{c}, @dots{})
+## @deftypefnx {Function File} {} poissrnd (@var{lambda}, [@var{sz}])
+## Return a matrix of random samples from the Poisson distribution with
+## parameter @var{lambda}.
 ##
-## If @var{r} and @var{c} are omitted, the size of the result matrix is
-## the size of @var{lambda}.
+## When called with a single size argument, return a square matrix with
+## the dimension specified.  When called with more than one scalar argument the
+## first two arguments are taken as the number of rows and columns and any
+## further arguments specify additional matrix dimensions.  The size may also
+## be specified with a vector of dimensions @var{sz}.
+## 
+## If no size arguments are given then the result matrix is the size of
+## @var{lambda}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Random deviates from the Poisson distribution
 
-function rnd = poissrnd (lambda, r, c)
-
-  if (nargin == 3)
-    if (! (isscalar (r) && (r > 0) && (r == round (r))))
-      error ("poissrnd: R must be a positive integer");
-    endif
-    if (! (isscalar (c) && (c > 0) && (c == round (c))))
-      error ("poissrnd: C must be a positive integer");
-    endif
-    sz = [r, c];
+function rnd = poissrnd (lambda, varargin)
 
-    if (any (size (lambda) != 1)
-        && ((length (size (lambda)) != length (sz)) || any (size (lambda) != sz)))
-      error ("poissrnd: LAMBDA must be scalar or of size [R, C]");
-    endif
-  elseif (nargin == 2)
-    if (isscalar (r) && (r > 0))
-      sz = [r, r];
-    elseif (isvector(r) && all (r > 0))
-      sz = r(:)';
-    else
-      error ("poissrnd: R must be a positive integer or vector");
-    endif
-
-    if (any (size (lambda) != 1)
-        && ((length (size (lambda)) != length (sz)) || any (size (lambda) != sz)))
-      error ("poissrnd: LAMBDA must be scalar or of size sz");
-    endif
-  elseif (nargin == 1)
-    sz = size (lambda);
-  else
+  if (nargin < 1)
     print_usage ();
   endif
 
-  if (isscalar (lambda))
+  if (nargin == 1)
+    sz = size (lambda);
+  elseif (nargin == 2)
+    if (isscalar (varargin{1}) && varargin{1} >= 0)
+      sz = [varargin{1}, varargin{1}];
+    elseif (isrow (varargin{1}) && all (varargin{1} >= 0))
+      sz = varargin{1};
+    else
+      error ("poissrnd: dimension vector must be row vector of non-negative integers");
+    endif
+  elseif (nargin > 2)
+    if (any (cellfun (@(x) (!isscalar (x) || x < 0), varargin)))
+      error ("poissrnd: dimensions must be non-negative integers");
+    endif
+    sz = [varargin{:}];
+  endif
 
-    if (!(lambda >= 0) || !(lambda < Inf))
-      rnd = NaN (sz);
-    elseif (lambda > 0 && lambda < Inf)
-      rnd = randp(lambda, sz);
+  if (!isscalar (lambda) && !isequal (size (lambda), sz))
+    error ("poissrnd: LAMBDA must be scalar or of size SZ");
+  endif
+
+  if (iscomplex (lambda))
+    error ("poissrnd: LAMBDA must not be complex");
+  endif
+
+  if (isa (lambda, "single"))
+    cls = "single";
+  else
+    cls = "double";
+  endif
+
+  if (isscalar (lambda))
+    if (lambda > 0 && lambda < Inf)
+      rnd = randp (lambda, sz);
+      if (strcmp (cls, "single"))
+        rnd = single (rnd);
+      endif
     else
-      rnd = zeros (sz);
+      rnd = NaN (sz, cls);
     endif
   else
-    rnd = zeros (sz);
+    rnd = NaN (sz, cls);
 
-    k = find (!(lambda >= 0) | !(lambda < Inf));
-    if (any (k))
-      rnd(k) = NaN;
-    endif
-
-    k = find ((lambda > 0) & (lambda < Inf));
-    if (any (k))
-      rnd(k) = randp(lambda(k), size(k));
-    endif
+    k = (lambda > 0) & (lambda < Inf);
+    rnd(k) = randp (lambda(k));
   endif
 
 endfunction
+
+
+%!assert(size (poissrnd (2)), [1, 1]);
+%!assert(size (poissrnd (ones(2,1))), [2, 1]);
+%!assert(size (poissrnd (ones(2,2))), [2, 2]);
+%!assert(size (poissrnd (1, 3)), [3, 3]);
+%!assert(size (poissrnd (1, [4 1])), [4, 1]);
+%!assert(size (poissrnd (1, 4, 1)), [4, 1]);
+
+%% Test class of input preserved
+%!assert(class (poissrnd (2)), "double");
+%!assert(class (poissrnd (single(2))), "single");
+%!assert(class (poissrnd (single([2 2]))), "single");
+
+%% Test input validation
+%!error poissrnd ()
+%!error poissrnd (1, -1)
+%!error poissrnd (1, ones(2))
+%!error poissrnd (1, 2, ones(2))
+%!error poissrnd (i)
+%!error poissrnd (1, 2, -1)
+%!error poissrnd (1, [2 -1 2])
+%!error poissrnd (ones(2,2), 3)
+%!error poissrnd (ones(2,2), [3, 2])
+%!error poissrnd (ones(2,2), 2, 3)
+
--- a/scripts/statistics/distributions/stdnormal_cdf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/stdnormal_cdf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -18,8 +19,9 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} stdnormal_cdf (@var{x})
-## For each component of @var{x}, compute the CDF of the standard normal
-## distribution at @var{x}.
+## For each element of @var{x}, compute the cumulative distribution
+## function (CDF) at @var{x} of the standard normal distribution
+## (mean = 0, standard deviation = 1).
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
@@ -31,9 +33,8 @@
     print_usage ();
   endif
 
-  sz = size (x);
-  if (numel(x) == 0)
-    error ("stdnormal_cdf: X must not be empty");
+  if (iscomplex (x))
+    error ("stdnormal_cdf: X must not be complex");
   endif
 
   cdf = erfc (x / (-sqrt(2))) / 2;
@@ -41,5 +42,16 @@
 endfunction
 
 
+%!shared x,y
+%! x = [-Inf 0 1 Inf];
+%! y = [0, 0.5, 1/2*(1+erf(1/sqrt(2))), 1];
+%!assert(stdnormal_cdf ([x, NaN]), [y, NaN]);
 
+%% Test class of input preserved
+%!assert(stdnormal_cdf (single([x, NaN])), single([y, NaN]), eps("single"));
 
+%% Test input validation
+%!error stdnormal_cdf ()
+%!error stdnormal_cdf (1,2)
+%!error stdnormal_cdf (i)
+
--- a/scripts/statistics/distributions/stdnormal_inv.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/stdnormal_inv.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -18,8 +19,9 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} stdnormal_inv (@var{x})
-## For each component of @var{x}, compute the quantile (the
-## inverse of the CDF) at @var{x} of the standard normal distribution.
+## For each element of @var{x}, compute the quantile (the
+## inverse of the CDF) at @var{x} of the standard normal distribution
+## (mean = 0, standard deviation = 1).
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
@@ -31,6 +33,25 @@
     print_usage ();
   endif
 
+  if (iscomplex (x))
+    error ("stdnormal_inv: X must not be complex");
+  endif
+
   inv = sqrt (2) * erfinv (2 * x - 1);
 
 endfunction
+
+
+%!shared x
+%! x = [-1 0 0.5 1 2];
+%!assert(stdnormal_inv (x), [NaN -Inf 0 Inf NaN]);
+
+%% Test class of input preserved
+%!assert(stdnormal_inv ([x, NaN]), [NaN -Inf 0 Inf NaN NaN]);
+%!assert(stdnormal_inv (single([x, NaN])), single([NaN -Inf 0 Inf NaN NaN]));
+
+%% Test input validation
+%!error stdnormal_inv ()
+%!error stdnormal_inv (1,2)
+%!error stdnormal_inv (i)
+
--- a/scripts/statistics/distributions/stdnormal_pdf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/stdnormal_pdf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -19,7 +20,8 @@
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} stdnormal_pdf (@var{x})
 ## For each element of @var{x}, compute the probability density function
-## (PDF) of the standard normal distribution at @var{x}.
+## (PDF) at @var{x} of the standard normal distribution (mean = 0,
+## standard deviation = 1).
 ## @end deftypefn
 
 ## Author: TT <Teresa.Twaroch@ci.tuwien.ac.at>
@@ -31,17 +33,25 @@
     print_usage ();
   endif
 
-  sz = size(x);
-  pdf = zeros (sz);
-
-  k = find (isnan (x));
-  if (any (k))
-    pdf(k) = NaN;
+  if (iscomplex (x))
+    error ("stdnormal_pdf: X must not be complex");
   endif
 
-  k = find (!isinf (x));
-  if (any (k))
-    pdf (k) = (2 * pi)^(- 1/2) * exp (- x(k) .^ 2 / 2);
-  endif
+  pdf = (2 * pi)^(- 1/2) * exp (- x .^ 2 / 2);
 
 endfunction
+
+
+%!shared x,y
+%! x = [-Inf 0 1 Inf];
+%! y = 1/sqrt(2*pi)*exp (-x.^2/2);
+%!assert(stdnormal_pdf ([x, NaN]), [y, NaN], eps);
+
+%% Test class of input preserved
+%!assert(stdnormal_pdf (single([x, NaN])), single([y, NaN]), eps("single"));
+
+%% Test input validation
+%!error stdnormal_pdf ()
+%!error stdnormal_pdf (1,2)
+%!error stdnormal_pdf (i)
+
--- a/scripts/statistics/distributions/stdnormal_rnd.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/stdnormal_rnd.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,39 +18,57 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} stdnormal_rnd (@var{r}, @var{c})
-## @deftypefnx {Function File} {} stdnormal_rnd (@var{sz})
-## Return an @var{r} by @var{c} or @code{size (@var{sz})} matrix of
-## random numbers from the standard normal distribution.
+## @deftypefn  {Function File} {} stdnormal_rnd (@var{r})
+## @deftypefnx {Function File} {} stdnormal_rnd (@var{r}, @var{c}, @dots{})
+## @deftypefnx {Function File} {} stdnormal_rnd ([@var{sz}])
+## Return a matrix of random samples from the standard normal distribution
+## (mean = 0, standard deviation = 1).
+##
+## When called with a single size argument, return a square matrix with
+## the dimension specified.  When called with more than one scalar argument the
+## first two arguments are taken as the number of rows and columns and any
+## further arguments specify additional matrix dimensions.  The size may also
+## be specified with a vector of dimensions @var{sz}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Random deviates from the standard normal distribution
 
-function rnd = stdnormal_rnd (r, c)
+function rnd = stdnormal_rnd (varargin)
 
-  if (nargin != 1 && nargin != 2)
+  if (nargin < 1)
     print_usage ();
   endif
 
-  if (nargin == 2)
-    if (! (isscalar (r) && (r > 0) && (r == round (r))))
-      error ("stdnormal_rnd: R must be a positive integer");
-    endif
-    if (! (isscalar (c) && (c > 0) && (c == round (c))))
-      error ("stdnormal_rnd: C must be a positive integer");
+  if (nargin == 1)
+    if (isscalar (varargin{1}) && varargin{1} >= 0)
+      sz = [varargin{1}, varargin{1}];
+    elseif (isrow (varargin{1}) && all (varargin{1} >= 0))
+      sz = varargin{1};
+    else
+      error ("stdnormal_rnd: dimension vector must be row vector of non-negative integers");
     endif
-    sz = [r, c];
-  else
-    if (isscalar (r) && (r > 0))
-      sz = [r, r];
-    elseif (isvector(r) && all (r > 0))
-      sz = r(:)';
-    else
-      error ("stdnormal_rnd: R must be a positive integer or vector");
+  elseif (nargin > 1)
+    if (any (cellfun (@(x) (!isscalar (x) || x < 0), varargin)))
+      error ("stdnormal_rnd: dimensions must be non-negative integers");
     endif
+    sz = [varargin{:}];
   endif
 
   rnd = randn (sz);
 
 endfunction
+
+
+%!assert(size (stdnormal_rnd (3)), [3, 3]);
+%!assert(size (stdnormal_rnd ([4 1])), [4, 1]);
+%!assert(size (stdnormal_rnd (4,1)), [4, 1]);
+
+%% Test input validation
+%!error stdnormal_rnd ()
+%!error stdnormal_rnd (-1)
+%!error stdnormal_rnd (ones(2))
+%!error stdnormal_rnd ([2 -1 2])
+%!error stdnormal_rnd (1, ones(2))
+%!error stdnormal_rnd (1, -1)
+
--- a/scripts/statistics/distributions/tcdf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/tcdf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -35,33 +36,59 @@
   if (!isscalar (n))
     [retval, x, n] = common_size (x, n);
     if (retval > 0)
-      error ("tcdf: X and N must be of common size or scalar");
+      error ("tcdf: X and N must be of common size or scalars");
     endif
   endif
 
-  cdf = zeros (size (x));
+  if (iscomplex (x) || iscomplex (n))
+    error ("tcdf: X and N must not be complex");
+  endif
 
-  k = find (isnan (x) | !(n > 0));
-  if (any (k))
-    cdf(k) = NaN;
+  if (isa (x, "single") || isa (n, "single"))
+    cdf = zeros (size (x), "single");
+  else
+    cdf = zeros (size (x));
   endif
 
-  k = find ((x == Inf) & (n > 0));
-  if (any (k))
-    cdf(k) = 1;
+  k = !isinf (x) & (n > 0);
+  if (isscalar (n))
+    cdf(k) = betainc (1 ./ (1 + x(k) .^ 2 / n), n/2, 1/2) / 2;
+  else
+    cdf(k) = betainc (1 ./ (1 + x(k) .^ 2 ./ n(k)), n(k)/2, 1/2) / 2;
+  endif
+  k &= (x > 0);
+  if (any (k(:)))
+    cdf(k) = 1 - cdf(k);
   endif
 
-  k = find ((x > -Inf) & (x < Inf) & (n > 0));
-  if (any (k))
-    if (isscalar (n))
-      cdf(k) = betainc (1 ./ (1 + x(k) .^ 2 ./ n), n / 2, 1 / 2) / 2;
-    else
-      cdf(k) = betainc (1 ./ (1 + x(k) .^ 2 ./ n(k)), n(k) / 2, 1 / 2) / 2;
-    endif
-    ind = find (x(k) > 0);
-    if (any (ind))
-      cdf(k(ind)) = 1 - cdf(k(ind));
-    endif
-  endif
+  k = isnan (x) | !(n > 0);
+  cdf(k) = NaN;
+
+  k = (x == Inf) & (n > 0);
+  cdf(k) = 1;
 
 endfunction
+
+
+%!shared x,y
+%! x = [-Inf 0 1 Inf];
+%! y = [0 1/2 3/4 1];
+%!assert(tcdf (x, ones(1,4)), y, eps);
+%!assert(tcdf (x, 1), y, eps);
+%!assert(tcdf (x, [0 1 NaN 1]), [NaN 1/2 NaN 1], eps);
+%!assert(tcdf ([x(1:2) NaN x(4)], 1), [y(1:2) NaN y(4)], eps);
+
+%% Test class of input preserved
+%!assert(tcdf ([x, NaN], 1), [y, NaN], eps);
+%!assert(tcdf (single([x, NaN]), 1), single([y, NaN]), eps("single"));
+%!assert(tcdf ([x, NaN], single(1)), single([y, NaN]), eps("single"));
+
+%% Test input validation
+%!error tcdf ()
+%!error tcdf (1)
+%!error tcdf (1,2,3)
+%!error tcdf (ones(3),ones(2))
+%!error tcdf (ones(2),ones(3))
+%!error tcdf (i, 2)
+%!error tcdf (2, i)
+
--- a/scripts/statistics/distributions/tinv.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/tinv.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -18,11 +19,10 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} tinv (@var{x}, @var{n})
-## For each probability value @var{x}, compute the inverse of the
-## cumulative distribution function (CDF) of the t (Student)
-## distribution with degrees of freedom @var{n}.  This function is
-## analogous to looking in a table for the t-value of a single-tailed
-## distribution.
+## For each element of @var{x}, compute the quantile (the inverse of
+## the CDF) at @var{x} of the t (Student) distribution with @var{n} 
+## degrees of freedom.  This function is analogous to looking in a table
+## for the t-value of a single-tailed distribution.
 ## @end deftypefn
 
 ## For very large n, the "correct" formula does not really work well,
@@ -41,44 +41,68 @@
   if (!isscalar (n))
     [retval, x, n] = common_size (x, n);
     if (retval > 0)
-      error ("tinv: X and N must be of common size or scalar");
+      error ("tinv: X and N must be of common size or scalars");
     endif
   endif
 
-  inv = zeros (size (x));
-
-  k = find ((x < 0) | (x > 1) | isnan (x) | !(n > 0));
-  if (any (k))
-    inv(k) = NaN;
+  if (iscomplex (x) || iscomplex (n))
+    error ("tinv: X and N must not be complex");
   endif
 
-  k = find ((x == 0) & (n > 0));
-  if (any (k))
-    inv(k) = -Inf;
-  endif
-
-  k = find ((x == 1) & (n > 0));
-  if (any (k))
-    inv(k) = Inf;
+  if (isa (x, "single") || isa (n, "single"))
+    inv = NaN (size (x), "single");
+  else
+    inv = NaN (size (x));
   endif
 
-  k = find ((x > 0) & (x < 1) & (n > 0) & (n < 10000));
-  if (any (k))
-    if (isscalar (n))
-      inv(k) = (sign (x(k) - 1/2)
-                .* sqrt (n .* (1 ./ betainv (2*min (x(k), 1 - x(k)),
-                                                 n/2, 1/2) - 1)));
-    else
+  k = (x == 0) & (n > 0);
+  inv(k) = -Inf;
+
+  k = (x == 1) & (n > 0);
+  inv(k) = Inf;
+
+  if (isscalar (n))
+    k = (x > 0) & (x < 1);
+    if ((n > 0) && (n < 10000))
       inv(k) = (sign (x(k) - 1/2)
-                .* sqrt (n(k) .* (1 ./ betainv (2*min (x(k), 1 - x(k)),
-                                                 n(k)/2, 1/2) - 1)));
+                .* sqrt (n * (1 ./ betainv (2*min (x(k), 1 - x(k)),
+                                            n/2, 1/2) - 1)));
+    elseif (n >= 10000)
+      ## For large n, use the quantiles of the standard normal
+      inv(k) = stdnormal_inv (x(k));
     endif
-  endif
+  else
+    k = (x > 0) & (x < 1) & (n > 0) & (n < 10000);
+    inv(k) = (sign (x(k) - 1/2)
+              .* sqrt (n(k) .* (1 ./ betainv (2*min (x(k), 1 - x(k)),
+                                              n(k)/2, 1/2) - 1)));
 
-  ## For large n, use the quantiles of the standard normal
-  k = find ((x > 0) & (x < 1) & (n >= 10000));
-  if (any (k))
+    ## For large n, use the quantiles of the standard normal
+    k = (x > 0) & (x < 1) & (n >= 10000);
     inv(k) = stdnormal_inv (x(k));
   endif
 
 endfunction
+
+
+%!shared x
+%! x = [-1 0 0.5 1 2];
+%!assert(tinv (x, ones(1,5)), [NaN -Inf 0 Inf NaN]);
+%!assert(tinv (x, 1), [NaN -Inf 0 Inf NaN], eps);
+%!assert(tinv (x, [1 0 NaN 1 1]), [NaN NaN NaN Inf NaN], eps);
+%!assert(tinv ([x(1:2) NaN x(4:5)], 1), [NaN -Inf NaN Inf NaN]);
+
+%% Test class of input preserved
+%!assert(tinv ([x, NaN], 1), [NaN -Inf 0 Inf NaN NaN], eps);
+%!assert(tinv (single([x, NaN]), 1), single([NaN -Inf 0 Inf NaN NaN]), eps("single"));
+%!assert(tinv ([x, NaN], single(1)), single([NaN -Inf 0 Inf NaN NaN]), eps("single"));
+
+%% Test input validation
+%!error tinv ()
+%!error tinv (1)
+%!error tinv (1,2,3)
+%!error tinv (ones(3),ones(2))
+%!error tinv (ones(2),ones(3))
+%!error tinv (i, 2)
+%!error tinv (2, i)
+
--- a/scripts/statistics/distributions/tpdf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/tpdf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -35,26 +36,58 @@
   if (!isscalar (n))
     [retval, x, n] = common_size (x, n);
     if (retval > 0)
-      error ("tpdf: X and N must be of common size or scalar");
+      error ("tpdf: X and N must be of common size or scalars");
     endif
   endif
 
-  pdf = zeros (size (x));
+  if (iscomplex (x) || iscomplex (n))
+    error ("tpdf: X and N must not be complex");
+  endif
 
-  k = find (isnan (x) | !(n > 0) | !(n < Inf));
-  if (any (k))
-    pdf(k) = NaN;
+  if (isa (x, "single") || isa (n, "single"))
+    pdf = zeros (size (x), "single");
+  else
+    pdf = zeros (size (x));
   endif
 
-  k = find (!isinf (x) & !isnan (x) & (n > 0) & (n < Inf));
-  if (any (k))
-    if (isscalar (n))
-      pdf(k) = (exp (- (n + 1) .* log (1 + x(k) .^ 2 ./ n)/2)
-                / (sqrt (n) * beta (n/2, 1/2)));
-    else
-      pdf(k) = (exp (- (n(k) + 1) .* log (1 + x(k) .^ 2 ./ n(k))/2)
-                ./ (sqrt (n(k)) .* beta (n(k)/2, 1/2)));
-    endif
+  k = isnan (x) | !(n > 0) | !(n < Inf);
+  pdf(k) = NaN;
+
+  k = !isinf (x) & !isnan (x) & (n > 0) & (n < Inf);
+  if (isscalar (n))
+    pdf(k) = (exp (- (n + 1) * log (1 + x(k) .^ 2 / n)/2)
+              / (sqrt (n) * beta (n/2, 1/2)));
+  else
+    pdf(k) = (exp (- (n(k) + 1) .* log (1 + x(k) .^ 2 ./ n(k))/2)
+              ./ (sqrt (n(k)) .* beta (n(k)/2, 1/2)));
   endif
 
 endfunction
+
+
+%!test
+%! x = rand (10,1);
+%! y = 1./(pi * (1 + x.^2));
+%! assert(tpdf (x, 1), y, 5*eps);
+
+%!shared x,y
+%! x = [-Inf 0 0.5 1 Inf];
+%! y = 1./(pi * (1 + x.^2));
+%!assert(tpdf (x, ones(1,5)), y, eps);
+%!assert(tpdf (x, 1), y, eps);
+%!assert(tpdf (x, [0 NaN 1 1 1]), [NaN NaN y(3:5)], eps);
+
+%% Test class of input preserved
+%!assert(tpdf ([x, NaN], 1), [y, NaN]);
+%!assert(tpdf (single([x, NaN]), 1), single([y, NaN]), eps("single"));
+%!assert(tpdf ([x, NaN], single(1)), single([y, NaN]), eps("single"));
+
+%% Test input validation
+%!error tpdf ()
+%!error tpdf (1)
+%!error tpdf (1,2,3)
+%!error tpdf (ones(3),ones(2))
+%!error tpdf (ones(2),ones(3))
+%!error tpdf (i, 2)
+%!error tpdf (2, i)
+
--- a/scripts/statistics/distributions/trnd.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/trnd.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,74 +18,100 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} trnd (@var{n}, @var{r}, @var{c})
-## @deftypefnx {Function File} {} trnd (@var{n}, @var{sz})
-## Return an @var{r} by @var{c} matrix of random samples from the t
-## (Student) distribution with @var{n} degrees of freedom.  @var{n} must
-## be a scalar or of size @var{r} by @var{c}.  Or if @var{sz} is a
-## vector create a matrix of size @var{sz}.
+## @deftypefn  {Function File} {} trnd (@var{n})
+## @deftypefnx {Function File} {} trnd (@var{n}, @var{r})
+## @deftypefnx {Function File} {} trnd (@var{n}, @var{r}, @var{c}, @dots{})
+## @deftypefnx {Function File} {} trnd (@var{n}, [@var{sz}])
+## Return a matrix of random samples from the t (Student) distribution with
+## @var{n} degrees of freedom.
 ##
-## If @var{r} and @var{c} are omitted, the size of the result matrix is
-## the size of @var{n}.
+## When called with a single size argument, return a square matrix with
+## the dimension specified.  When called with more than one scalar argument the
+## first two arguments are taken as the number of rows and columns and any
+## further arguments specify additional matrix dimensions.  The size may also
+## be specified with a vector of dimensions @var{sz}.
+## 
+## If no size arguments are given then the result matrix is the size of
+## @var{n}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Random deviates from the t distribution
 
-function rnd = trnd (n, r, c)
-
-  if (nargin == 3)
-    if (! (isscalar (r) && (r > 0) && (r == round (r))))
-      error ("trnd: R must be a positive integer");
-    endif
-    if (! (isscalar (c) && (c > 0) && (c == round (c))))
-      error ("trnd: C must be a positive integer");
-    endif
-    sz = [r, c];
+function rnd = trnd (n, varargin)
 
-    if (any (size (n) != 1)
-        && ((length (size (n)) != length (sz)) || any (size (n) != sz)))
-      error ("trnd: N must be scalar or of size SZ");
-    endif
-  elseif (nargin == 2)
-    if (isscalar (r) && (r > 0))
-      sz = [r, r];
-    elseif (isvector(r) && all (r > 0))
-      sz = r(:)';
-    else
-      error ("trnd: R must be a positive integer or vector");
-    endif
-
-    if (any (size (n) != 1)
-        && ((length (size (n)) != length (sz)) || any (size (n) != sz)))
-      error ("trnd: N must be scalar or of size SZ");
-    endif
-  elseif (nargin == 1)
-    sz = size (n);
-  else
+  if (nargin < 1)
     print_usage ();
   endif
 
+  if (nargin == 1)
+    sz = size (n);
+  elseif (nargin == 2)
+    if (isscalar (varargin{1}) && varargin{1} >= 0)
+      sz = [varargin{1}, varargin{1}];
+    elseif (isrow (varargin{1}) && all (varargin{1} >= 0))
+      sz = varargin{1};
+    else
+      error ("trnd: dimension vector must be row vector of non-negative integers");
+    endif
+  elseif (nargin > 2)
+    if (any (cellfun (@(x) (!isscalar (x) || x < 0), varargin)))
+      error ("trnd: dimensions must be non-negative integers");
+    endif
+    sz = [varargin{:}];
+  endif
+
+  if (!isscalar (n) && !isequal (size (n), sz))
+    error ("trnd: N must be scalar or of size SZ");
+  endif
+
+  if (iscomplex (n))
+    error ("trnd: N must not be complex");
+  endif
+
+  if (isa (n, "single"))
+    cls = "single";
+  else
+    cls = "double";
+  endif
+
   if (isscalar (n))
-    if (!(n > 0) || !(n < Inf))
-      rnd = NaN (sz);
-    elseif ((n > 0) && (n < Inf))
-      rnd = randn(sz) ./ sqrt(2*randg(n/2,sz)./n);
+    if ((n > 0) && (n < Inf))
+      rnd = randn (sz) ./ sqrt (2*randg (n/2, sz) / n);
     else
-      rnd = zeros (size (n));
+      rnd = NaN (sz, cls);
     endif
   else
-    rnd = zeros (size (n));
+    rnd = NaN (sz, cls);
 
-    k = find (!(n > 0) | !(n < Inf));
-    if (any (k))
-      rnd(k) = NaN;
-    endif
-
-    k = find ((n > 0) & (n < Inf));
-    if (any (k))
-      rnd(k) = randn(size(k)) ./ sqrt(2*randg(n(k)/2,size(k))./n(k));
-    endif
+    k = (n > 0) & (n < Inf);
+    rnd(k) = randn (sum (k(:)), 1) ./ sqrt (2*randg (n(k)/2) ./ n(k))(:);
   endif
 
 endfunction
+
+
+%!assert(size (trnd (2)), [1, 1]);
+%!assert(size (trnd (ones(2,1))), [2, 1]);
+%!assert(size (trnd (ones(2,2))), [2, 2]);
+%!assert(size (trnd (1, 3)), [3, 3]);
+%!assert(size (trnd (1, [4 1])), [4, 1]);
+%!assert(size (trnd (1, 4, 1)), [4, 1]);
+
+%% Test class of input preserved
+%!assert(class (trnd (1)), "double");
+%!assert(class (trnd (single(1))), "single");
+%!assert(class (trnd (single([1 1]))), "single");
+
+%% Test input validation
+%!error trnd ()
+%!error trnd (1, -1)
+%!error trnd (1, ones(2))
+%!error trnd (i)
+%!error trnd (1, [2 -1 2])
+%!error trnd (1, 2, ones(2))
+%!error trnd (1, 2, -1)
+%!error trnd (ones(2,2), 3)
+%!error trnd (ones(2,2), [3, 2])
+%!error trnd (ones(2,2), 2, 3)
+
--- a/scripts/statistics/distributions/unidcdf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/unidcdf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 2007-2011 David Bateman
 ##
 ## This file is part of Octave.
@@ -17,26 +18,72 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} unidcdf (@var{x}, @var{v})
+## @deftypefn {Function File} {} unidcdf (@var{x}, @var{n})
 ## For each element of @var{x}, compute the cumulative distribution
-## function (CDF) at @var{x} of a discrete uniform distribution which
-## assumes the values in @var{v} with equal probability.
-## If @var{v} is a scalar then @code{1/@var{v}} is the probability of a
-## single element.
+## function (CDF) at @var{x} of a discrete uniform distribution which assumes
+## the integer values 1--@var{n} with equal probability.
 ## @end deftypefn
 
-function cdf = unidcdf (x, v)
+function cdf = unidcdf (x, n)
 
   if (nargin != 2)
     print_usage ();
   endif
 
-  if (isscalar(v))
-    v = [1:v].';
+  if (! isscalar (n))
+    [retval, x, n] = common_size (x, n);
+    if (retval > 0)
+      error ("unidcdf: X and N must be of common size or scalars");
+    endif
+  endif
+
+  if (iscomplex (x) || iscomplex (n))
+    error ("unidcdf: X and N must not be complex");
+  endif
+
+  if (isa (x, "single") || isa (n, "single"))
+    cdf = zeros (size (x), "single");
   else
-    v = v(:);
+    cdf = zeros (size (x));
+  endif
+
+  knan = isnan (x) | ! (n > 0 & n == fix (n));
+  if (any (knan(:)))
+    cdf(knan) = NaN;
   endif
 
-  cdf = discrete_cdf (x, v, ones(size(v)));
+  k = (x >= n) & !knan;  
+  cdf(k) = 1;
+
+  k = (x >= 1) & (x < n) & !knan;
+  if (isscalar (n))
+    cdf(k) = floor (x(k)) / n;
+  else
+    cdf(k) = floor (x(k)) ./ n(k);
+  endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [0 1 2.5 10 11];
+%! y = [0, 0.1 0.2 1.0 1.0];
+%!assert(unidcdf (x, 10*ones(1,5)), y);
+%!assert(unidcdf (x, 10), y);
+%!assert(unidcdf (x, 10*[0 1 NaN 1 1]), [NaN 0.1 NaN y(4:5)]);
+%!assert(unidcdf ([x(1:2) NaN Inf x(5)], 10), [y(1:2) NaN 1 y(5)]);
+
+%% Test class of input preserved
+%!assert(unidcdf ([x, NaN], 10), [y, NaN]);
+%!assert(unidcdf (single([x, NaN]), 10), single([y, NaN]));
+%!assert(unidcdf ([x, NaN], single(10)), single([y, NaN]));
+
+%% Test input validation
+%!error unidcdf ()
+%!error unidcdf (1)
+%!error unidcdf (1,2,3)
+%!error unidcdf (ones(3),ones(2))
+%!error unidcdf (ones(2),ones(3))
+%!error unidcdf (i, 2)
+%!error unidcdf (2, i)
+
--- a/scripts/statistics/distributions/unidinv.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/unidinv.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 2007-2011 David Bateman
 ##
 ## This file is part of Octave.
@@ -17,25 +18,64 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} unidinv (@var{x}, @var{v})
-## For each component of @var{x}, compute the quantile (the inverse of
-## the CDF) at @var{x} of the discrete uniform distribution which assumes the
-## values in @var{v} with equal probability.
-## If @var{v} is a scalar then @code{1/@var{v}} is the probability of a
-## single element.
+## @deftypefn {Function File} {} unidinv (@var{x}, @var{n})
+## For each element of @var{x}, compute the quantile (the inverse of
+## the CDF) at @var{x} of the discrete uniform distribution which assumes
+## the integer values 1--@var{n} with equal probability.
 ## @end deftypefn
 
-function inv = unidinv (x, v)
+function inv = unidinv (x, n)
 
   if (nargin != 2)
     print_usage ();
   endif
 
-  if (isscalar(v))
-    v = [1:v].';
+  if (! isscalar (n))
+    [retval, x, n] = common_size (x, n);
+    if (retval > 0)
+      error ("unidcdf: X and N must be of common size or scalars");
+    endif
+  endif
+
+  if (iscomplex (x) || iscomplex (n))
+    error ("unidinv: X and N must not be complex");
+  endif
+
+  if (isa (x, "single") || isa (n, "single"))
+    inv = NaN (size (x), "single");
   else
-    v = v(:);
+    inv = NaN (size (x));
+  endif
+
+  ## For Matlab compatibility, unidinv(0) = NaN
+  k = (x > 0) & (x <= 1) & (n > 0 & n == fix (n));
+  if (isscalar (n))
+    inv(k) = floor (x(k) * n);
+  else
+    inv(k) = floor (x(k) .* n(k));
   endif
 
-  inv = discrete_inv (x, v, ones(size(v)));
 endfunction
+
+
+%!shared x
+%! x = [-1 0 0.5 1 2];
+%!assert(unidinv (x, 10*ones(1,5)), [NaN NaN 5 10 NaN], eps);
+%!assert(unidinv (x, 10), [NaN NaN 5 10 NaN], eps);
+%!assert(unidinv (x, 10*[0 1 NaN 1 1]), [NaN NaN NaN 10 NaN], eps);
+%!assert(unidinv ([x(1:2) NaN x(4:5)], 10), [NaN NaN NaN 10 NaN], eps);
+
+%% Test class of input preserved
+%!assert(unidinv ([x, NaN], 10), [NaN NaN 5 10 NaN NaN], eps);
+%!assert(unidinv (single([x, NaN]), 10), single([NaN NaN 5 10 NaN NaN]), eps);
+%!assert(unidinv ([x, NaN], single(10)), single([NaN NaN 5 10 NaN NaN]), eps);
+
+%% Test input validation
+%!error unidinv ()
+%!error unidinv (1)
+%!error unidinv (1,2,3)
+%!error unidinv (ones(3),ones(2))
+%!error unidinv (ones(2),ones(3))
+%!error unidinv (i, 2)
+%!error unidinv (2, i)
+
--- a/scripts/statistics/distributions/unidpdf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/unidpdf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 2007-2011 David Bateman
 ##
 ## This file is part of Octave.
@@ -17,25 +18,70 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} unidpdf (@var{x}, @var{v})
+## @deftypefn {Function File} {} unidpdf (@var{x}, @var{n})
 ## For each element of @var{x}, compute the probability density function
 ## (PDF) at @var{x} of a discrete uniform distribution which assumes
-## the values in @var{v} with equal probability.
-## If @var{v} is a scalar then @code{1/@var{v}} is the probability of a
-## single element.
+## the integer values 1--@var{n} with equal probability.
+##
+## Warning: The underlying implementation uses the double class and
+## will only be accurate for @var{n} @leq{} @code{bitmax} 
+## (@w{@math{2^{53} - 1}} on IEEE-754 compatible systems).
 ## @end deftypefn
 
-function pdf = unidpdf (x, v)
+function pdf = unidpdf (x, n)
 
   if (nargin != 2)
     print_usage ();
   endif
 
-  if (isscalar(v))
-    v = [1:v].';
+  if (! isscalar (n))
+    [retval, x, n] = common_size (x, n);
+    if (retval > 0)
+      error ("unidpdf: X and N must be of common size or scalars");
+    endif
+  endif
+
+  if (iscomplex (x) || iscomplex (n))
+    error ("unidpdf: X and N must not be complex");
+  endif
+
+  if (isa (x, "single") || isa (n, "single"))
+    pdf = zeros (size (x), "single");
   else
-    v = v(:);
+    pdf = zeros (size (x));
   endif
 
-  pdf = discrete_pdf (x, v, ones(size(v)));
+  k = isnan (x) | ! (n > 0 & n == fix (n));
+  pdf(k) = NaN;
+
+  k = !k & (x >= 1) & (x <= n) & (x == fix (x));
+  if (isscalar (n))
+    pdf(k) = 1 / n;
+  else
+    pdf(k) = 1 ./ n(k);
+  endif
+
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 1 2 10 11];
+%! y = [0 0 0.1 0.1 0.1 0];
+%!assert(unidpdf (x, 10*ones(1,6)), y);
+%!assert(unidpdf (x, 10), y);
+%!assert(unidpdf (x, 10*[0 NaN 1 1 1 1]), [NaN NaN y(3:6)]);
+%!assert(unidpdf ([x, NaN], 10), [y, NaN]);
+
+%% Test class of input preserved
+%!assert(unidpdf (single([x, NaN]), 10), single([y, NaN]));
+%!assert(unidpdf ([x, NaN], single(10)), single([y, NaN]));
+
+%% Test input validation
+%!error unidpdf ()
+%!error unidpdf (1)
+%!error unidpdf (1,2,3)
+%!error unidpdf (ones(3),ones(2))
+%!error unidpdf (ones(2),ones(3))
+%!error unidpdf (i, 2)
+%!error unidpdf (2, i)
+
--- a/scripts/statistics/distributions/unidrnd.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/unidrnd.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 2005-2011 John W. Eaton
 ##
 ## This file is part of Octave.
@@ -17,44 +18,94 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} unidrnd (@var{mx});
-## @deftypefnx {Function File} {} unidrnd (@var{mx}, @var{v});
-## @deftypefnx {Function File} {} unidrnd (@var{mx}, @var{m}, @var{n}, @dots{});
-## Return random values from a discrete uniform distribution with maximum
-## value(s) given by the integer @var{mx} (which may be a scalar or
-## multi-dimensional array).
+## @deftypefn  {Function File} {} unidrnd (@var{n})
+## @deftypefnx {Function File} {} unidrnd (@var{n}, @var{r})
+## @deftypefnx {Function File} {} unidrnd (@var{n}, @var{r}, @var{c}, @dots{})
+## @deftypefnx {Function File} {} unidrnd (@var{n}, [@var{sz}])
+## Return a matrix of random samples from the discrete uniform distribution
+## which assumes the integer values 1--@var{n} with equal probability.
+## @var{n} may be a scalar or a multi-dimensional array.
 ##
-## If @var{mx} is a scalar, the size of the result is specified by
-## the vector @var{v}, or by the optional arguments @var{m}, @var{n},
-## @dots{}.  Otherwise, the size of the result is the same as the size
-## of @var{mx}.
+## When called with a single size argument, return a square matrix with
+## the dimension specified.  When called with more than one scalar argument the
+## first two arguments are taken as the number of rows and columns and any
+## further arguments specify additional matrix dimensions.  The size may also
+## be specified with a vector of dimensions @var{sz}.
+## 
+## If no size arguments are given then the result matrix is the size of
+## @var{n}.
 ## @end deftypefn
 
 ## Author: jwe
 
-function retval = unidrnd (n, varargin)
+function rnd = unidrnd (n, varargin)
+
+  if (nargin < 1)
+    print_usage ();
+  endif
+
   if (nargin == 1)
-    dims = size (n);
+    sz = size (n);
   elseif (nargin == 2)
-    if (rows (varargin{1}) == 1 && columns (varargin{1}) > 1)
-      dims = varargin{1};
+    if (isscalar (varargin{1}) && varargin{1} >= 0)
+      sz = [varargin{1}, varargin{1}];
+    elseif (isrow (varargin{1}) && all (varargin{1} >= 0))
+      sz = varargin{1};
     else
-      error ("unidrnd: invalid dimension vector");
+      error ("unidrnd: dimension vector must be row vector of non-negative integers");
     endif
   elseif (nargin > 2)
-    for i = 1:nargin-1
-      if (! isscalar (varargin{i}))
-        error ("unidrnd: expecting scalar dimensions");
-      endif
-    endfor
-    dims = [varargin{:}];
+    if (any (cellfun (@(x) (!isscalar (x) || x < 0), varargin)))
+      error ("unidrnd: dimensions must be non-negative integers");
+    endif
+    sz = [varargin{:}];
+  endif
+
+  if (!isscalar (n) && !isequal (size (n), sz))
+    error ("unidrnd: N must be scalar or of size SZ");
+  endif
+
+  if (iscomplex (n))
+    error ("unidrnd: N must not be complex");
+  endif
+
+  if (isa (n, "single"))
+    cls = "single";
+  else
+    cls = "double";
+  endif
+
+  if (isscalar (n))
+    if (n > 0 && n == fix (n))
+      rnd = ceil (rand (sz) * n);
+    else
+      rnd = NaN (sz, cls);
+    endif
   else
-    print_usage ();
+    rnd = ceil (rand (sz) .* n);
+
+    k = ! (n > 0 & n == fix (n));
+    rnd(k) = NaN;
   endif
-  if (isscalar (n)
-      || (length (size (n)) == length (dims) && all (size (n) == dims)))
-    retval = ceil (rand (dims) .* n);
-  else
-    error ("unidrnd: dimension mismatch");
-  endif
+
 endfunction
+
+
+%!assert(size (unidrnd (2)), [1, 1]);
+%!assert(size (unidrnd (ones(2,1))), [2, 1]);
+%!assert(size (unidrnd (ones(2,2))), [2, 2]);
+%!assert(size (unidrnd (10, [4 1])), [4, 1]);
+%!assert(size (unidrnd (10, 4, 1)), [4, 1]);
+
+%% Test class of input preserved
+%!assert(class (unidrnd (2)), "double");
+%!assert(class (unidrnd (single(2))), "single");
+%!assert(class (unidrnd (single([2 2]))), "single");
+
+%% Test input validation
+%!error unidrnd ()
+%!error unidrnd (10, [1;2;3])
+%!error unidrnd (10, 2, ones(2))
+%!error unidrnd (10*ones(2), 2, 1)
+%!error unidrnd (i)
+
--- a/scripts/statistics/distributions/unifcdf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/unifcdf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,9 +18,11 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} unifcdf (@var{x}, @var{a}, @var{b})
-## Return the CDF at @var{x} of the uniform distribution on [@var{a},
-## @var{b}], i.e., PROB (uniform (@var{a}, @var{b}) @leq{} x).
+## @deftypefn  {Function File} {} unifcdf (@var{x})
+## @deftypefnx {Function File} {} unifcdf (@var{x}, @var{a}, @var{b})
+## For each element of @var{x}, compute the cumulative distribution
+## function (CDF) at @var{x} of the uniform distribution on the interval
+## [@var{a}, @var{b}].
 ##
 ## Default values are @var{a} = 0, @var{b} = 1.
 ## @end deftypefn
@@ -27,44 +30,69 @@
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: CDF of the uniform distribution
 
-function cdf = unifcdf (x, a, b)
+function cdf = unifcdf (x, a = 0, b = 1)
 
   if (nargin != 1 && nargin != 3)
     print_usage ();
   endif
 
-  if (nargin == 1)
-    a = 0;
-    b = 1;
-  endif
-
-  if (!isscalar (a) || !isscalar(b))
+  if (!isscalar (a) || !isscalar (b))
     [retval, x, a, b] = common_size (x, a, b);
     if (retval > 0)
-      error ("unifcdf: X, A and B must be of common size or scalar");
+      error ("unifcdf: X, A, and B must be of common size or scalars");
     endif
   endif
 
-  sz = size (x);
-  cdf = zeros (sz);
+  if (iscomplex (x) || iscomplex (a) || iscomplex (b))
+    error ("unifcdf: X, A, and B must not be complex");
+  endif
 
-  k = find (isnan (x) | !(a < b));
-  if (any (k))
-    cdf(k) = NaN;
+  if (isa (x, "single") || isa (a, "single") || isa (b, "single"))
+    cdf = zeros (size (x), "single");
+  else
+    cdf = zeros (size (x));
   endif
 
-  k = find ((x >= b) & (a < b));
-  if (any (k))
-    cdf(k) = 1;
-  endif
+  k = isnan (x) | !(a < b);
+  cdf(k) = NaN;
+
+  k = (x >= b) & (a < b);
+  cdf(k) = 1;
 
-  k = find ((x > a) & (x < b));
-  if (any (k))
-    if (isscalar (a) && isscalar(b))
-      cdf(k) = (x(k) < b) .* (x(k) - a) ./ (b - a);
-    else
-      cdf(k) = (x(k) < b(k)) .* (x(k) - a(k)) ./ (b(k) - a(k));
-    endif
+  k = (x > a) & (x < b);
+  if (isscalar (a) && isscalar (b))
+    cdf(k) = (x(k) < b) .* (x(k) - a) / (b - a);
+  else
+    cdf(k) = (x(k) < b(k)) .* (x(k) - a(k)) ./ (b(k) - a(k));
   endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 0.5 1 2] + 1;
+%! y = [0 0 0.5 1 1];
+%!assert(unifcdf (x, ones(1,5), 2*ones(1,5)), y);
+%!assert(unifcdf (x, 1, 2*ones(1,5)), y);
+%!assert(unifcdf (x, ones(1,5), 2), y);
+%!assert(unifcdf (x, [2 1 NaN 1 1], 2), [NaN 0 NaN 1 1]);
+%!assert(unifcdf (x, 1, 2*[0 1 NaN 1 1]), [NaN 0 NaN 1 1]);
+%!assert(unifcdf ([x(1:2) NaN x(4:5)], 1, 2), [y(1:2) NaN y(4:5)]);
+
+%% Test class of input preserved
+%!assert(unifcdf ([x, NaN], 1, 2), [y, NaN]);
+%!assert(unifcdf (single([x, NaN]), 1, 2), single([y, NaN]));
+%!assert(unifcdf ([x, NaN], single(1), 2), single([y, NaN]));
+%!assert(unifcdf ([x, NaN], 1, single(2)), single([y, NaN]));
+
+%% Test input validation
+%!error unifcdf ()
+%!error unifcdf (1,2)
+%!error unifcdf (1,2,3,4)
+%!error unifcdf (ones(3),ones(2),ones(2))
+%!error unifcdf (ones(2),ones(3),ones(2))
+%!error unifcdf (ones(2),ones(2),ones(3))
+%!error unifcdf (i, 2, 2)
+%!error unifcdf (2, i, 2)
+%!error unifcdf (2, 2, i)
+
--- a/scripts/statistics/distributions/unifinv.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/unifinv.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,9 +18,11 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} unifinv (@var{x}, @var{a}, @var{b})
+## @deftypefn  {Function File} {} unifinv (@var{x})
+## @deftypefnx {Function File} {} unifinv (@var{x}, @var{a}, @var{b})
 ## For each element of @var{x}, compute the quantile (the inverse of the
-## CDF) at @var{x} of the uniform distribution on [@var{a}, @var{b}].
+## CDF) at @var{x} of the uniform distribution on the interval
+## [@var{a}, @var{b}].
 ##
 ## Default values are @var{a} = 0, @var{b} = 1.
 ## @end deftypefn
@@ -27,39 +30,62 @@
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Quantile function of the uniform distribution
 
-function inv = unifinv (x, a, b)
+function inv = unifinv (x, a = 0, b = 1)
 
   if (nargin != 1 && nargin != 3)
     print_usage ();
   endif
 
-  if (nargin == 1)
-    a = 0;
-    b = 1;
-  endif
-
-  if (!isscalar (a) || !isscalar(b))
+  if (!isscalar (a) || !isscalar (b))
     [retval, x, a, b] = common_size (x, a, b);
     if (retval > 0)
-      error ("unifinv: X, A and B must be of common size or scalar");
+      error ("unifinv: X, A, and B must be of common size or scalars");
     endif
   endif
 
-  sz = size (x);
-  inv = zeros (sz);
-
-  k = find ((x < 0) | (x > 1) | isnan (x) | !(a < b));
-  if (any (k))
-    inv(k) = NaN;
+  if (iscomplex (x) || iscomplex (a) || iscomplex (b))
+    error ("unifinv: X, A, and B must not be complex");
   endif
 
-  k = find ((x >= 0) & (x <= 1) & (a < b));
-  if (any (k))
-    if (isscalar (a) && isscalar(b))
-      inv(k) = a + x(k) .* (b - a);
-    else
-      inv(k) = a(k) + x(k) .* (b(k) - a(k));
-    endif
+  if (isa (x, "single") || isa (a, "single") || isa (b, "single"))
+    inv = NaN (size (x), "single");
+  else
+    inv = NaN (size (x));
+  endif
+
+  k = (x >= 0) & (x <= 1) & (a < b);
+  if (isscalar (a) && isscalar (b))
+    inv(k) = a + x(k) * (b - a);
+  else
+    inv(k) = a(k) + x(k) .* (b(k) - a(k));
   endif
 
 endfunction
+
+
+%!shared x
+%! x = [-1 0 0.5 1 2];
+%!assert(unifinv (x, ones(1,5), 2*ones(1,5)), [NaN 1 1.5 2 NaN]);
+%!assert(unifinv (x, 1, 2*ones(1,5)), [NaN 1 1.5 2 NaN]);
+%!assert(unifinv (x, ones(1,5), 2), [NaN 1 1.5 2 NaN]);
+%!assert(unifinv (x, [1 2 NaN 1 1], 2), [NaN NaN NaN 2 NaN]);
+%!assert(unifinv (x, 1, 2*[1 0 NaN 1 1]), [NaN NaN NaN 2 NaN]);
+%!assert(unifinv ([x(1:2) NaN x(4:5)], 1, 2), [NaN 1 NaN 2 NaN]);
+
+%% Test class of input preserved
+%!assert(unifinv ([x, NaN], 1, 2), [NaN 1 1.5 2 NaN NaN]);
+%!assert(unifinv (single([x, NaN]), 1, 2), single([NaN 1 1.5 2 NaN NaN]));
+%!assert(unifinv ([x, NaN], single(1), 2), single([NaN 1 1.5 2 NaN NaN]));
+%!assert(unifinv ([x, NaN], 1, single(2)), single([NaN 1 1.5 2 NaN NaN]));
+
+%% Test input validation
+%!error unifinv ()
+%!error unifinv (1,2)
+%!error unifinv (1,2,3,4)
+%!error unifinv (ones(3),ones(2),ones(2))
+%!error unifinv (ones(2),ones(3),ones(2))
+%!error unifinv (ones(2),ones(2),ones(3))
+%!error unifinv (i, 2, 2)
+%!error unifinv (2, i, 2)
+%!error unifinv (2, 2, i)
+
--- a/scripts/statistics/distributions/unifpdf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/unifpdf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,9 +18,10 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} unifpdf (@var{x}, @var{a}, @var{b})
-## For each element of @var{x}, compute the PDF at @var{x} of the uniform
-## distribution on [@var{a}, @var{b}].
+## @deftypefn  {Function File} {} unifpdf (@var{x})
+## @deftypefnx {Function File} {} unifpdf (@var{x}, @var{a}, @var{b})
+## For each element of @var{x}, compute the probability density function (PDF)
+## at @var{x} of the uniform distribution on the interval [@var{a}, @var{b}].
 ##
 ## Default values are @var{a} = 0, @var{b} = 1.
 ## @end deftypefn
@@ -27,39 +29,65 @@
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: PDF of the uniform distribution
 
-function pdf = unifpdf (x, a, b)
+function pdf = unifpdf (x, a = 0, b = 1)
 
   if (nargin != 1 && nargin != 3)
     print_usage ();
   endif
 
-  if (nargin == 1)
-    a = 0;
-    b = 1;
-  endif
-
-  if (!isscalar (a) || !isscalar(b))
+  if (!isscalar (a) || !isscalar (b))
     [retval, x, a, b] = common_size (x, a, b);
     if (retval > 0)
-      error ("unifpdf: X, A and B must be of common size or scalars");
+      error ("unifpdf: X, A, and B must be of common size or scalars");
     endif
   endif
 
-  sz = size (x);
-  pdf = zeros (sz);
-
-  k = find (isnan (x) | !(a < b));
-  if (any (k))
-    pdf(k) = NaN;
+  if (iscomplex (x) || iscomplex (a) || iscomplex (b))
+    error ("unifpdf: X, A, and B must not be complex");
   endif
 
-  k = find ((x >= a) & (x <= b));
-  if (any (k))
-    if (isscalar (a) && isscalar(b))
-      pdf(k) = 1 ./ (b - a);
-    else
-      pdf(k) = 1 ./ (b(k) - a(k));
-    endif
+  if (isa (x, "single") || isa (a, "single") || isa (b, "single"))
+    pdf = zeros (size (x), "single");
+  else
+    pdf = zeros (size (x));
+  endif
+
+  k = isnan (x) | !(a < b);
+  pdf(k) = NaN;
+
+  k = (x >= a) & (x <= b) & (a < b);
+  if (isscalar (a) && isscalar (b))
+    pdf(k) = 1 / (b - a);
+  else
+    pdf(k) = 1 ./ (b(k) - a(k));
   endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 0.5 1 2] + 1;
+%! y = [0 1 1 1 0];
+%!assert(unifpdf (x, ones(1,5), 2*ones(1,5)), y);
+%!assert(unifpdf (x, 1, 2*ones(1,5)), y);
+%!assert(unifpdf (x, ones(1,5), 2), y);
+%!assert(unifpdf (x, [2 NaN 1 1 1], 2), [NaN NaN y(3:5)]);
+%!assert(unifpdf (x, 1, 2*[0 NaN 1 1 1]), [NaN NaN y(3:5)]);
+%!assert(unifpdf ([x, NaN], 1, 2), [y, NaN]);
+
+%% Test class of input preserved
+%!assert(unifpdf (single([x, NaN]), 1, 2), single([y, NaN]));
+%!assert(unifpdf (single([x, NaN]), single(1), 2), single([y, NaN]));
+%!assert(unifpdf ([x, NaN], 1, single(2)), single([y, NaN]));
+
+%% Test input validation
+%!error unifpdf ()
+%!error unifpdf (1,2)
+%!error unifpdf (1,2,3,4)
+%!error unifpdf (ones(3),ones(2),ones(2))
+%!error unifpdf (ones(2),ones(3),ones(2))
+%!error unifpdf (ones(2),ones(2),ones(3))
+%!error unifpdf (i, 2, 2)
+%!error unifpdf (2, i, 2)
+%!error unifpdf (2, 2, i)
+
--- a/scripts/statistics/distributions/unifrnd.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/unifrnd.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,75 +18,115 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} unifrnd (@var{a}, @var{b}, @var{r}, @var{c})
-## @deftypefnx {Function File} {} unifrnd (@var{a}, @var{b}, @var{sz})
-## Return an @var{r} by @var{c} or a @code{size (@var{sz})} matrix of
-## random samples from the uniform distribution on [@var{a}, @var{b}].
-## Both @var{a} and @var{b} must be scalar or of size @var{r} by @var{c}.
+## @deftypefn  {Function File} {} unifrnd (@var{a}, @var{b})
+## @deftypefnx {Function File} {} unifrnd (@var{a}, @var{b}, @var{r})
+## @deftypefnx {Function File} {} unifrnd (@var{a}, @var{b}, @var{r}, @var{c}, @dots{})
+## @deftypefnx {Function File} {} unifrnd (@var{a}, @var{b}, [@var{sz}])
+## Return a matrix of random samples from the uniform distribution on
+## [@var{a}, @var{b}].
 ##
-## If @var{r} and @var{c} are omitted, the size of the result matrix is
-## the common size of @var{a} and @var{b}.
+## When called with a single size argument, return a square matrix with
+## the dimension specified.  When called with more than one scalar argument the
+## first two arguments are taken as the number of rows and columns and any
+## further arguments specify additional matrix dimensions.  The size may also
+## be specified with a vector of dimensions @var{sz}.
+## 
+## If no size arguments are given then the result matrix is the common size of
+## @var{a} and @var{b}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Random deviates from the uniform distribution
 
-function rnd = unifrnd (a, b, r, c)
+function rnd = unifrnd (a, b, varargin)
 
-  if (nargin > 1)
-    if (!isscalar(a) || !isscalar(b))
-      [retval, a, b] = common_size (a, b);
-      if (retval > 0)
-        error ("unifrnd: A and B must be of common size or scalar");
-      endif
+  if (nargin < 2)
+    print_usage ();
+  endif
+
+  if (!isscalar (a) || !isscalar (b))
+    [retval, a, b] = common_size (a, b);
+    if (retval > 0)
+      error ("unifrnd: A and B must be of common size or scalars");
     endif
   endif
 
-  if (nargin == 4)
-    if (! (isscalar (r) && (r > 0) && (r == round (r))))
-      error ("unifrnd: R must be a positive integer");
-    endif
-    if (! (isscalar (c) && (c > 0) && (c == round (c))))
-      error ("unifrnd: C must be a positive integer");
-    endif
-    sz = [r, c];
-
-    if (any (size (a) != 1)
-        && (length (size (a)) != length (sz) || any (size (a) != sz)))
-      error ("unifrnd: A and B must be scalar or of size [R, C]");
-    endif
-  elseif (nargin == 3)
-    if (isscalar (r) && (r > 0))
-      sz = [r, r];
-    elseif (isvector(r) && all (r > 0))
-      sz = r(:)';
-    else
-      error ("unifrnd: R must be a positive integer or vector");
-    endif
-
-    if (any (size (a) != 1)
-        && (length (size (a)) != length (sz) || any (size (a) != sz)))
-      error ("unifrnd: A and B must be scalar or of size SZ");
-    endif
-  elseif (nargin == 2)
-    sz = size(a);
-  else
-    print_usage ();
+  if (iscomplex (a) || iscomplex (b))
+    error ("unifrnd: A and B must not be complex");
   endif
 
-  if (isscalar(a) && isscalar(b))
-    if (find (!(-Inf < a) | !(a < b) | !(b < Inf)))
-      rnd = NaN(sz);
+  if (nargin == 2)
+    sz = size (a);
+  elseif (nargin == 3)
+    if (isscalar (varargin{1}) && varargin{1} >= 0)
+      sz = [varargin{1}, varargin{1}];
+    elseif (isrow (varargin{1}) && all (varargin{1} >= 0))
+      sz = varargin{1};
     else
-      rnd =  a + (b - a) .* rand (sz);
+      error ("unifrnd: dimension vector must be row vector of non-negative integers");
+    endif
+  elseif (nargin > 3)
+    if (any (cellfun (@(x) (!isscalar (x) || x < 0), varargin)))
+      error ("unifrnd: dimensions must be non-negative integers");
+    endif
+    sz = [varargin{:}];
+  endif
+
+  if (!isscalar (a) && !isequal (size (a), sz))
+    error ("unifrnd: A and B must be scalar or of size SZ");
+  endif
+
+  if (isa (a, "single") || isa (b, "single"))
+    cls = "single";
+  else
+    cls = "double";
+  endif
+
+  if (isscalar (a) && isscalar (b))
+    if ((-Inf < a) && (a < b) && (b < Inf))
+      rnd =  a + (b - a) * rand (sz);
+    else
+      rnd = NaN (sz, cls);
     endif
   else
     rnd =  a + (b - a) .* rand (sz);
 
-    k = find (!(-Inf < a) | !(a < b) | !(b < Inf));
-    if (any (k))
-      rnd(k) = NaN;
-    endif
+    k = !(-Inf < a) | !(a < b) | !(b < Inf);
+    rnd(k) = NaN;
   endif
 
 endfunction
+
+
+%!assert(size (unifrnd (1,2)), [1, 1]);
+%!assert(size (unifrnd (ones(2,1), 2)), [2, 1]);
+%!assert(size (unifrnd (ones(2,2), 2)), [2, 2]);
+%!assert(size (unifrnd (1, 2*ones(2,1))), [2, 1]);
+%!assert(size (unifrnd (1, 2*ones(2,2))), [2, 2]);
+%!assert(size (unifrnd (1, 2, 3)), [3, 3]);
+%!assert(size (unifrnd (1, 2, [4 1])), [4, 1]);
+%!assert(size (unifrnd (1, 2, 4, 1)), [4, 1]);
+
+%% Test class of input preserved
+%!assert(class (unifrnd (1, 2)), "double");
+%!assert(class (unifrnd (single(1), 2)), "single");
+%!assert(class (unifrnd (single([1 1]), 2)), "single");
+%!assert(class (unifrnd (1, single(2))), "single");
+%!assert(class (unifrnd (1, single([2 2]))), "single");
+
+%% Test input validation
+%!error unifrnd ()
+%!error unifrnd (1)
+%!error unifrnd (ones(3),ones(2))
+%!error unifrnd (ones(2),ones(3))
+%!error unifrnd (i, 2)
+%!error unifrnd (2, i)
+%!error unifrnd (1,2, -1)
+%!error unifrnd (1,2, ones(2))
+%!error unifrnd (1, 2, [2 -1 2])
+%!error unifrnd (1,2, 1, ones(2))
+%!error unifrnd (1,2, 1, -1)
+%!error unifrnd (ones(2,2), 2, 3)
+%!error unifrnd (ones(2,2), 2, [3, 2])
+%!error unifrnd (ones(2,2), 2, 2, 3)
+
--- a/scripts/statistics/distributions/wblcdf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/wblcdf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,7 +18,9 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} wblcdf (@var{x}, @var{scale}, @var{shape})
+## @deftypefn  {Function File} {} wblcdf (@var{x})
+## @deftypefnx {Function File} {} wblcdf (@var{x}, @var{scale})
+## @deftypefnx {Function File} {} wblcdf (@var{x}, @var{scale}, @var{shape})
 ## Compute the cumulative distribution function (CDF) at @var{x} of the
 ## Weibull distribution with scale parameter @var{scale} and shape
 ## parameter @var{shape}, which is
@@ -28,59 +31,83 @@
 ## @ifnottex
 ##
 ## @example
-## 1 - exp(-(x/scale)^shape)
+## 1 - exp (-(x/scale)^shape)
 ## @end example
 ##
 ## @noindent
 ## for @var{x} @geq{} 0.
+##
+## Default values are @var{scale} = 1, @var{shape} = 1.
 ## @end ifnottex
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: CDF of the Weibull distribution
 
-function cdf = wblcdf (x, scale, shape)
+function cdf = wblcdf (x, scale = 1, shape = 1)
 
   if (nargin < 1 || nargin > 3)
     print_usage ();
   endif
 
-  if (nargin < 3)
-    shape = 1;
-  endif
-
-  if (nargin < 2)
-    scale = 1;
-  endif
-
   if (!isscalar (shape) || !isscalar (scale))
     [retval, x, shape, scale] = common_size (x, shape, scale);
     if (retval > 0)
-      error ("wblcdf: X, SCALE and SHAPE must be of common size or scalar");
+      error ("wblcdf: X, SCALE, and SHAPE must be of common size or scalars");
     endif
   endif
 
-  cdf = NaN (size (x));
-
-  ok = ((shape > 0) & (shape < Inf) & (scale > 0) & (scale < Inf));
+  if (iscomplex (x) || iscomplex (scale) || iscomplex (shape))
+    error ("wblcdf: X, SCALE, and SHAPE must not be complex");
+  endif
 
-  k = find ((x <= 0) & ok);
-  if (any (k))
-    cdf(k) = 0;
+  if (isa (x, "single") || isa (scale, "single") || isa (shape, "single"))
+    cdf = NaN (size (x), "single");
+  else
+    cdf = NaN (size (x));
   endif
 
-  k = find ((x > 0) & (x < Inf) & ok);
-  if (any (k))
-    if (isscalar (shape) && isscalar (scale))
-      cdf(k) = 1 - exp (- (x(k) / scale) .^ shape);
-    else
-      cdf(k) = 1 - exp (- (x(k) ./ scale(k)) .^ shape(k));
-    endif
-  endif
+  ok = (shape > 0) & (shape < Inf) & (scale > 0) & (scale < Inf);
+
+  k = (x <= 0) & ok;
+  cdf(k) = 0;
 
-  k = find ((x == Inf) & ok);
-  if (any (k))
-    cdf(k) = 1;
+  k = (x == Inf) & ok;
+  cdf(k) = 1;
+
+  k = (x > 0) & (x < Inf) & ok;
+  if (isscalar (shape) && isscalar (scale))
+    cdf(k) = 1 - exp (- (x(k) / scale) .^ shape);
+  else
+    cdf(k) = 1 - exp (- (x(k) ./ scale(k)) .^ shape(k));
   endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 0.5 1 Inf];
+%! y = [0, 1-exp(-x(2:4)), 1];
+%!assert(wblcdf (x, ones(1,5), ones(1,5)), y);
+%!assert(wblcdf (x, 1, ones(1,5)), y);
+%!assert(wblcdf (x, ones(1,5), 1), y);
+%!assert(wblcdf (x, [0 1 NaN Inf 1], 1), [NaN 0 NaN NaN 1]);
+%!assert(wblcdf (x, 1, [0 1 NaN Inf 1]), [NaN 0 NaN NaN 1]);
+%!assert(wblcdf ([x(1:2) NaN x(4:5)], 1, 1), [y(1:2) NaN y(4:5)]);
+
+%% Test class of input preserved
+%!assert(wblcdf ([x, NaN], 1, 1), [y, NaN]);
+%!assert(wblcdf (single([x, NaN]), 1, 1), single([y, NaN]));
+%!assert(wblcdf ([x, NaN], single(1), 1), single([y, NaN]));
+%!assert(wblcdf ([x, NaN], 1, single(1)), single([y, NaN]));
+
+%% Test input validation
+%!error wblcdf ()
+%!error wblcdf (1,2,3,4)
+%!error wblcdf (ones(3),ones(2),ones(2))
+%!error wblcdf (ones(2),ones(3),ones(2))
+%!error wblcdf (ones(2),ones(2),ones(3))
+%!error wblcdf (i, 2, 2)
+%!error wblcdf (2, i, 2)
+%!error wblcdf (2, 2, i)
+
--- a/scripts/statistics/distributions/wblinv.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/wblinv.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,57 +18,82 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} wblinv (@var{x}, @var{scale}, @var{shape})
+## @deftypefn  {Function File} {} wblinv (@var{x})
+## @deftypefnx {Function File} {} wblinv (@var{x}, @var{scale})
+## @deftypefnx {Function File} {} wblinv (@var{x}, @var{scale}, @var{shape})
 ## Compute the quantile (the inverse of the CDF) at @var{x} of the
 ## Weibull distribution with scale parameter @var{scale} and shape
 ## parameter @var{shape}.
+##
+## Default values are @var{scale} = 1, @var{shape} = 1.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Quantile function of the Weibull distribution
 
-function inv = wblinv (x, scale, shape)
+function inv = wblinv (x, scale = 1, shape = 1)
 
   if (nargin < 1 || nargin > 3)
     print_usage ();
   endif
 
-  if (nargin < 3)
-    shape = 1;
-  endif
-
-  if (nargin < 2)
-    scale = 1;
-  endif
-
   if (!isscalar (scale) || !isscalar (shape))
     [retval, x, scale, shape] = common_size (x, scale, shape);
     if (retval > 0)
-      error ("wblinv: X, SCALE and SHAPE must be of common size or scalar");
+      error ("wblinv: X, SCALE, and SHAPE must be of common size or scalars");
     endif
   endif
 
-  inv = NaN (size (x));
-
-  ok = ((scale > 0) & (scale < Inf) & (shape > 0) & (shape < Inf));
+  if (iscomplex (x) || iscomplex (scale) || iscomplex (shape))
+    error ("wblinv: X, SCALE, and SHAPE must not be complex");
+  endif
 
-  k = find ((x == 0) & ok);
-  if (any (k))
-    inv(k) = 0;
+  if (isa (x, "single") || isa (scale, "single") || isa (shape, "single"))
+    inv = NaN (size (x), "single");
+  else
+    inv = NaN (size (x));
   endif
 
-  k = find ((x > 0) & (x < 1) & ok);
-  if (any (k))
-    if (isscalar (scale) && isscalar (shape))
-      inv(k) = scale * (- log (1 - x(k))) .^ (1 / shape);
-    else
-      inv(k) = scale(k) .* (- log (1 - x(k))) .^ (1 ./ shape(k));
-    endif
-  endif
+  ok = (scale > 0) & (scale < Inf) & (shape > 0) & (shape < Inf);
+
+  k = (x == 0) & ok;
+  inv(k) = 0;
 
-  k = find ((x == 1) & ok);
-  if (any (k))
-    inv(k) = Inf;
+  k = (x == 1) & ok;
+  inv(k) = Inf;
+
+  k = (x > 0) & (x < 1) & ok;
+  if (isscalar (scale) && isscalar (shape))
+    inv(k) = scale * (- log (1 - x(k))) .^ (1 / shape);
+  else
+    inv(k) = scale(k) .* (- log (1 - x(k))) .^ (1 ./ shape(k));
   endif
 
 endfunction
+
+
+%!shared x
+%! x = [-1 0 0.63212055882855778 1 2];
+%!assert(wblinv (x, ones(1,5), ones(1,5)), [NaN 0 1 Inf NaN], eps);
+%!assert(wblinv (x, 1, ones(1,5)), [NaN 0 1 Inf NaN], eps);
+%!assert(wblinv (x, ones(1,5), 1), [NaN 0 1 Inf NaN], eps);
+%!assert(wblinv (x, [1 -1 NaN Inf 1], 1), [NaN NaN NaN NaN NaN]);
+%!assert(wblinv (x, 1, [1 -1 NaN Inf 1]), [NaN NaN NaN NaN NaN]);
+%!assert(wblinv ([x(1:2) NaN x(4:5)], 1, 1), [NaN 0 NaN Inf NaN]);
+
+%% Test class of input preserved
+%!assert(wblinv ([x, NaN], 1, 1), [NaN 0 1 Inf NaN NaN], eps);
+%!assert(wblinv (single([x, NaN]), 1, 1), single([NaN 0 1 Inf NaN NaN]), eps("single"));
+%!assert(wblinv ([x, NaN], single(1), 1), single([NaN 0 1 Inf NaN NaN]), eps("single"));
+%!assert(wblinv ([x, NaN], 1, single(1)), single([NaN 0 1 Inf NaN NaN]), eps("single"));
+
+%% Test input validation
+%!error wblinv ()
+%!error wblinv (1,2,3,4)
+%!error wblinv (ones(3),ones(2),ones(2))
+%!error wblinv (ones(2),ones(3),ones(2))
+%!error wblinv (ones(2),ones(2),ones(3))
+%!error wblinv (i, 2, 2)
+%!error wblinv (2, i, 2)
+%!error wblinv (2, 2, i)
+
--- a/scripts/statistics/distributions/wblpdf.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/wblpdf.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,7 +18,9 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} wblpdf (@var{x}, @var{scale}, @var{shape})
+## @deftypefn  {Function File} {} wblpdf (@var{x})
+## @deftypefnx {Function File} {} wblpdf (@var{x}, @var{scale})
+## @deftypefnx {Function File} {} wblpdf (@var{x}, @var{scale}, @var{shape})
 ## Compute the probability density function (PDF) at @var{x} of the
 ## Weibull distribution with scale parameter @var{scale} and shape
 ## parameter @var{shape} which is given by
@@ -27,57 +30,83 @@
 ## @ifnottex
 ##
 ## @example
-##    shape * scale^(-shape) * x^(shape-1) * exp(-(x/scale)^shape)
+##    shape * scale^(-shape) * x^(shape-1) * exp (-(x/scale)^shape)
 ## @end example
 ##
 ## @end ifnottex
 ## @noindent
 ## for @var{x} @geq{} 0.
+##
+## Default values are @var{scale} = 1, @var{shape} = 1.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: PDF of the Weibull distribution
 
-function pdf = wblpdf (x, scale, shape)
+function pdf = wblpdf (x, scale = 1, shape = 1)
 
   if (nargin < 1 || nargin > 3)
     print_usage ();
   endif
 
-  if (nargin < 3)
-    shape = 1;
-  endif
-
-  if (nargin < 2)
-    scale = 1;
-  endif
-
   if (!isscalar (scale) || !isscalar (shape))
     [retval, x, scale, shape] = common_size (x, scale, shape);
     if (retval > 0)
-      error ("wblpdf: X, SCALE and SHAPE must be of common size or scalar");
+      error ("wblpdf: X, SCALE, and SHAPE must be of common size or scalars");
     endif
   endif
 
-  pdf = NaN (size (x));
-  ok = ((scale > 0) & (scale < Inf) & (shape > 0) & (shape < Inf));
+  if (iscomplex (x) || iscomplex (scale) || iscomplex (shape))
+    error ("wblpdf: X, SCALE, and SHAPE must not be complex");
+  endif
 
-  k = find ((x > -Inf) & (x < 0) & ok);
-  if (any (k))
-    pdf(k) = 0;
+  if (isa (x, "single") || isa (scale, "single") || isa (shape, "single"))
+    pdf = NaN (size (x), "single");
+  else
+    pdf = NaN (size (x));
   endif
 
-  k = find ((x >= 0) & (x < Inf) & ok);
-  if (any (k))
-    if (isscalar (scale) && isscalar (shape))
-      pdf(k) = (shape .* (scale .^ -shape)
-                .* (x(k) .^ (shape - 1))
-                .* exp(- (x(k) / scale) .^ shape));
-    else
-      pdf(k) = (shape(k) .* (scale(k) .^ -shape(k))
-                .* (x(k) .^ (shape(k) - 1))
-                .* exp(- (x(k) ./ scale(k)) .^ shape(k)));
-    endif
+  ok = ((scale > 0) & (scale < Inf) & (shape > 0) & (shape < Inf));
+
+  k = (x < 0) & ok;
+  pdf(k) = 0;
+
+  k = (x >= 0) & (x < Inf) & ok;
+  if (isscalar (scale) && isscalar (shape))
+    pdf(k) = (shape * (scale .^ -shape)
+              .* (x(k) .^ (shape - 1))
+              .* exp (- (x(k) / scale) .^ shape));
+  else
+    pdf(k) = (shape(k) .* (scale(k) .^ -shape(k))
+              .* (x(k) .^ (shape(k) - 1))
+              .* exp (- (x(k) ./ scale(k)) .^ shape(k)));
   endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 0.5 1 Inf];
+%! y = [0, exp(-x(2:4)), NaN];
+%!assert(wblpdf (x, ones(1,5), ones(1,5)), y);
+%!assert(wblpdf (x, 1, ones(1,5)), y);
+%!assert(wblpdf (x, ones(1,5), 1), y);
+%!assert(wblpdf (x, [0 NaN Inf 1 1], 1), [NaN NaN NaN y(4:5)]);
+%!assert(wblpdf (x, 1, [0 NaN Inf 1 1]), [NaN NaN NaN y(4:5)]);
+%!assert(wblpdf ([x, NaN], 1, 1), [y, NaN]);
+
+%% Test class of input preserved
+%!assert(wblpdf (single([x, NaN]), 1, 1), single([y, NaN]));
+%!assert(wblpdf ([x, NaN], single(1), 1), single([y, NaN]));
+%!assert(wblpdf ([x, NaN], 1, single(1)), single([y, NaN]));
+
+%% Test input validation
+%!error wblpdf ()
+%!error wblpdf (1,2,3,4)
+%!error wblpdf (ones(3),ones(2),ones(2))
+%!error wblpdf (ones(2),ones(3),ones(2))
+%!error wblpdf (ones(2),ones(2),ones(3))
+%!error wblpdf (i, 2, 2)
+%!error wblpdf (2, i, 2)
+%!error wblpdf (2, 2, i)
+
--- a/scripts/statistics/distributions/wblrnd.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/distributions/wblrnd.m	Tue Sep 20 15:38:24 2011 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,78 +18,115 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} wblrnd (@var{scale}, @var{shape}, @var{r}, @var{c})
-## @deftypefnx {Function File} {} wblrnd (@var{scale}, @var{shape}, @var{sz})
-## Return an @var{r} by @var{c} matrix of random samples from the
-## Weibull distribution with parameters @var{scale} and @var{shape}
-## which must be scalar or of size @var{r} by @var{c}.  Or if @var{sz}
-## is a vector return a matrix of size @var{sz}.
+## @deftypefn  {Function File} {} wblrnd (@var{scale}, @var{shape})
+## @deftypefnx {Function File} {} wblrnd (@var{scale}, @var{shape}, @var{r})
+## @deftypefnx {Function File} {} wblrnd (@var{scale}, @var{shape}, @var{r}, @var{c}, @dots{})
+## @deftypefnx {Function File} {} wblrnd (@var{scale}, @var{shape}, [@var{sz}])
+## Return a matrix of random samples from the Weibull distribution with
+## parameters @var{scale} and @var{shape}.
 ##
-## If @var{r} and @var{c} are omitted, the size of the result matrix is
-## the common size of @var{alpha} and @var{sigma}.
+## When called with a single size argument, return a square matrix with
+## the dimension specified.  When called with more than one scalar argument the
+## first two arguments are taken as the number of rows and columns and any
+## further arguments specify additional matrix dimensions.  The size may also
+## be specified with a vector of dimensions @var{sz}.
+## 
+## If no size arguments are given then the result matrix is the common size of
+## @var{scale} and @var{shape}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Random deviates from the Weibull distribution
 
-function rnd = wblrnd (scale, shape, r, c)
+function rnd = wblrnd (scale, shape, varargin)
 
-  if (nargin > 1)
-    if (!isscalar(scale) || !isscalar(shape))
-      [retval, scale, shape] = common_size (scale, shape);
-      if (retval > 0)
-        error ("wblrnd: SCALE and SHAPE must be of common size or scalar");
-      endif
+  if (nargin < 2)
+    print_usage ();
+  endif
+
+  if (!isscalar (scale) || !isscalar (shape))
+    [retval, scale, shape] = common_size (scale, shape);
+    if (retval > 0)
+      error ("wblrnd: SCALE and SHAPE must be of common size or scalars");
     endif
   endif
 
-  if (nargin == 4)
-    if (! (isscalar (r) && (r > 0) && (r == round (r))))
-      error ("wblrnd: R must be a positive integer");
-    endif
-    if (! (isscalar (c) && (c > 0) && (c == round (c))))
-      error ("wblrnd: C must be a positive integer");
-    endif
-    sz = [r, c];
+  if (iscomplex (scale) || iscomplex (shape))
+    error ("wblrnd: SCALE and SHAPE must not be complex");
+  endif
 
-    if (any (size (scale) != 1)
-        && ((length (size (scale)) != length (sz))
-            || any (size (scale) != sz)))
-      error ("wblrnd: SCALE and SHAPE must be scalar or of size [R, C]");
-    endif
+  if (nargin == 2)
+    sz = size (scale);
   elseif (nargin == 3)
-    if (isscalar (r) && (r > 0))
-      sz = [r, r];
-    elseif (isvector(r) && all (r > 0))
-      sz = r(:)';
+    if (isscalar (varargin{1}) && varargin{1} >= 0)
+      sz = [varargin{1}, varargin{1}];
+    elseif (isrow (varargin{1}) && all (varargin{1} >= 0))
+      sz = varargin{1};
     else
-      error ("wblrnd: R must be a positive integer or vector");
+      error ("wblrnd: dimension vector must be row vector of non-negative integers");
     endif
+  elseif (nargin > 3)
+    if (any (cellfun (@(x) (!isscalar (x) || x < 0), varargin)))
+      error ("wblrnd: dimensions must be non-negative integers");
+    endif
+    sz = [varargin{:}];
+  endif
 
-    if (any (size (scale) != 1)
-        && ((length (size (scale)) != length (sz))
-            || any (size (scale) != sz)))
-      error ("wblrnd: SCALE and SHAPE must be scalar or of size SZ");
-    endif
-  elseif (nargin == 2)
-    sz = size(scale);
+  if (!isscalar (scale) && !isequal (size (scale), sz))
+    error ("wblrnd: SCALE and SHAPE must be scalar or of size SZ");
+  endif
+
+  if (isa (scale, "single") || isa (shape, "single"))
+    cls = "single";
   else
-    print_usage ();
+    cls = "double";
   endif
 
   if (isscalar (scale) && isscalar (shape))
-    if (scale > 0 && scale < Inf && shape > 0 && shape < Inf)
-      rnd = scale .* rande(sz) .^ (1./shape);
+    if ((scale > 0) && (scale < Inf) && (shape > 0) && (shape < Inf))
+      rnd = scale * rande (sz) .^ (1/shape);
     else
-      rnd = NaN (sz);
+      rnd = NaN (sz, cls);
     endif
   else
-    rnd = scale .* rande(sz) .^ (1./shape);
-    k = find ((scale <= 0) | (scale == Inf) | ((shape <= 0) & (shape == Inf)));
-    if (any(k))
-      rnd(k) = NaN;
-    endif
+    rnd = scale .* rande (sz) .^ (1./shape);
+
+    k = (scale <= 0) | (scale == Inf) | (shape <= 0) | (shape == Inf);
+    rnd(k) = NaN;
   endif
 
 endfunction
 
+
+%!assert(size (wblrnd (1,2)), [1, 1]);
+%!assert(size (wblrnd (ones(2,1), 2)), [2, 1]);
+%!assert(size (wblrnd (ones(2,2), 2)), [2, 2]);
+%!assert(size (wblrnd (1, 2*ones(2,1))), [2, 1]);
+%!assert(size (wblrnd (1, 2*ones(2,2))), [2, 2]);
+%!assert(size (wblrnd (1, 2, 3)), [3, 3]);
+%!assert(size (wblrnd (1, 2, [4 1])), [4, 1]);
+%!assert(size (wblrnd (1, 2, 4, 1)), [4, 1]);
+
+%% Test class of input preserved
+%!assert(class (wblrnd (1, 2)), "double");
+%!assert(class (wblrnd (single(1), 2)), "single");
+%!assert(class (wblrnd (single([1 1]), 2)), "single");
+%!assert(class (wblrnd (1, single(2))), "single");
+%!assert(class (wblrnd (1, single([2 2]))), "single");
+
+%% Test input validation
+%!error wblrnd ()
+%!error wblrnd (1)
+%!error wblrnd (ones(3),ones(2))
+%!error wblrnd (ones(2),ones(3))
+%!error wblrnd (i, 2)
+%!error wblrnd (2, i)
+%!error wblrnd (1,2, -1)
+%!error wblrnd (1,2, ones(2))
+%!error wblrnd (1, 2, [2 -1 2])
+%!error wblrnd (1,2, 1, ones(2))
+%!error wblrnd (1,2, 1, -1)
+%!error wblrnd (ones(2,2), 2, 3)
+%!error wblrnd (ones(2,2), 2, [3, 2])
+%!error wblrnd (ones(2,2), 2, 2, 3)
+
--- a/scripts/statistics/tests/cor_test.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/tests/cor_test.m	Tue Sep 20 15:38:24 2011 -0400
@@ -91,7 +91,7 @@
   m = method (1);
 
   if (m == "p")
-    r = cor (x, y);
+    r = corr (x, y);
     df = n - 2;
     t.method = "Pearson's product moment correlation";
     t.params = df;
--- a/scripts/statistics/tests/wilcoxon_test.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/statistics/tests/wilcoxon_test.m	Tue Sep 20 15:38:24 2011 -0400
@@ -23,7 +23,7 @@
 ## @var{y}) == 1/2.  Under the null, the test statistic @var{z}
 ## approximately follows a standard normal distribution when @var{n} > 25.
 ##
-## @strong{Warning}: This function assumes a normal distribution for @var{z}
+## @strong{Caution:} This function assumes a normal distribution for @var{z}
 ## and thus is invalid for @var{n} @leq{} 25.
 ##
 ## With the optional argument string @var{alt}, the alternative of
--- a/scripts/strings/base2dec.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/strings/base2dec.m	Tue Sep 20 15:38:24 2011 -0400
@@ -28,10 +28,12 @@
 ## @end group
 ## @end example
 ##
-## If @var{s} is a matrix, returns a column vector with one value per
+## If @var{s} is a string matrix, return a column vector with one value per
 ## row of @var{s}.  If a row contains invalid symbols then the
-## corresponding value will be NaN@.  Rows are right-justified before
-## converting so that trailing spaces are ignored.
+## corresponding value will be NaN@.  
+##
+## If @var{s} is a cell array of strings, return a column vector with one
+## value per cell element in @var{s}.
 ##
 ## If @var{base} is a string, the characters of @var{base} are used as the
 ## symbols for the digits of @var{s}.  Space (' ') may not be used as a
@@ -55,6 +57,12 @@
     print_usage ();
   endif
 
+  if (iscellstr (s))
+    s = char (s);
+  elseif (! ischar (s))
+    error ("base2dec: S must be a string or cellstring");
+  endif
+
   symbols = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
   if (ischar (base))
     symbols = base;
@@ -89,9 +97,11 @@
 
 endfunction
 
+
 %!assert(base2dec ("11120", 3), 123);
 %!assert(base2dec ("yyyzx", "xyz"), 123);
 %!assert(base2dec ("-1", 2), NaN);
+%!assert(base2dec ({"A1", "1A"}, 16), [161; 26]);
 
 %%Test input validation
 %!error base2dec ();
--- a/scripts/strings/bin2dec.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/strings/bin2dec.m	Tue Sep 20 15:38:24 2011 -0400
@@ -28,8 +28,11 @@
 ## @end group
 ## @end example
 ##
-## If @var{s} is a string matrix, return a column vector of converted
-## numbers, one per row of @var{s}.  Invalid rows evaluate to NaN.
+## If @var{s} is a string matrix, return a column vector with one converted
+## number per row of @var{s}; Invalid rows evaluate to NaN@.
+##
+## If @var{s} is a cell array of strings, return a column vector with one
+## converted number per cell element in @var{s}.
 ## @seealso{dec2bin, base2dec, hex2dec}
 ## @end deftypefn
 
@@ -38,17 +41,19 @@
 
 function d = bin2dec (s)
 
-  if (nargin == 1 && ischar (s))
-    d = base2dec (s, 2);
-  else
+  if (nargin != 1)
     print_usage ();
   endif
 
+  d = base2dec (s, 2);
+
 endfunction
 
+
 %!assert(bin2dec ("0000"), 0);
 %!assert(bin2dec ("1110"), 14);
 %!assert(bin2dec ("11111111111111111111111111111111111111111111111111111"), 2^53-1);
+%!assert(bin2dec ({"1110", "1111"}), [14; 15]);
 
 %%Test input validation
 %!error bin2dec ();
--- a/scripts/strings/deblank.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/strings/deblank.m	Tue Sep 20 15:38:24 2011 -0400
@@ -18,10 +18,22 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} deblank (@var{s})
-## Remove trailing blanks and nulls from @var{s}.  If @var{s}
+## Remove trailing whitespace and nulls from @var{s}.  If @var{s}
 ## is a matrix, @var{deblank} trims each row to the length of longest
-## string.  If @var{s} is a cell array, operate recursively on each
-## element of the cell array.
+## string.  If @var{s} is a cell array of strings, operate recursively on each
+## string element.
+##
+## Examples:
+## @example
+## @group
+## deblank ("    abc  ")
+##      @result{}  "    abc"
+##
+## deblank ([" abc   "; "   def   "])
+##      @result{}  [" abc  " ; "   def"]
+## @end group
+## @end example
+## @seealso{strtrim}
 ## @end deftypefn
 
 ## Author: Kurt Hornik <Kurt.Hornik@wu-wien.ac.at>
@@ -33,53 +45,44 @@
     print_usage ();
   endif
 
-  char_arg = ischar (s);
-
-  if (char_arg || isnumeric (s))
+  if (ischar (s))
 
-    if (! isempty (s))
-      if (char_arg)
-        k = find (! isspace (s) & s != "\0");
-      else
-        warning ("deblank: expecting character string argument");
-        k = find (s != 0);
-      endif
-
-      if (isempty (k))
-        s = resize (s, 0, 0);
-      else
-        s = s(:,1:ceil (max (k) / rows (s)));
-      endif
+    k = find (! isspace (s) & s != "\0");
+    if (isempty (s) || isempty (k))
+      s = "";
+    else
+      s = s(:,1:ceil (max (k) / rows (s)));
     endif
 
-  elseif (iscell(s))
+  elseif (iscell (s))
 
-    s = cellfun (@deblank, s, "uniformoutput", false);
+    char_idx = cellfun ("isclass", s, "char");
+    cell_idx = cellfun ("isclass", s, "cell");
+    if (! all (char_idx | cell_idx))  
+      error ("deblank: S argument must be a string or cellstring");
+    endif
+
+    ## Divide work load.  Recursive cellfun deblank call is slow
+    ## and avoided where possible.
+    s(char_idx) = regexprep (s(char_idx), "[\\s\v\\0]+$", '');
+    s(cell_idx) = cellfun ("deblank", s(cell_idx), "UniformOutput", false);
 
   else
-    error ("deblank: expecting character string argument");
+    error ("deblank: S argument must be a string or cellstring");
   endif
 
 endfunction
 
-%!assert (strcmp (deblank (" f o o  "), " f o o"));
-
-%!assert (deblank ([]), [])
-%!assert (deblank ({}), {})
-%!assert (deblank (""), "")
-
-%!assert (deblank ([0,0,0]), [])
-%!assert (deblank ('   '), '')
-%!assert (deblank ("   "), "")
 
-%!assert (typeinfo (deblank ("   ")), "string")
-%!assert (typeinfo (deblank ('   ')), "sq_string")
-
-%!assert (deblank ([1,2,0]), [1,2])
-%!assert (deblank ([1,2,0,32]), [1,2,0,32])
+%!assert (deblank (" f o o \0"), " f o o");
+%!assert (deblank ('   '), '');
+%!assert (deblank ("   "), "");
+%!assert (deblank (""), "");
+%!assert (deblank ({}), {});
+%!assert (deblank ({" abc   ", {"   def   "}}), {" abc", {"   def"}});
 
-%!assert (deblank (int8 ([1,2,0])), int8 ([1,2]))
+%!error <Invalid call to deblank> deblank ();
+%!error <Invalid call to deblank> deblank ("foo", "bar");
+%!error <argument must be a string> deblank (1);
+%!error <argument must be a string> deblank ({[]});
 
-%!error deblank ();
-
-%!error deblank ("foo", "bar");
--- a/scripts/strings/dec2base.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/strings/dec2base.m	Tue Sep 20 15:38:24 2011 -0400
@@ -29,8 +29,9 @@
 ## @end group
 ## @end example
 ##
-## If @var{d} is a vector, return a string matrix with one row per value,
-## padded with leading zeros to the width of the largest value.
+## If @var{d} is a matrix or cell array, return a string matrix with one
+## row per element in @var{d}, padded with leading zeros to the width of 
+## the largest value.
 ##
 ## If @var{base} is a string then the characters of @var{base} are used as
 ## the symbols for the digits of @var{d}.  Space (' ') may not be used
@@ -57,13 +58,17 @@
     print_usage ();
   endif
 
+  if (iscell (d))
+    d = cell2mat (d);
+  endif
+
   # Create column vector for algorithm
-  if (columns (d) > 1 || !isvector (d))
+  if (! iscolumn (d))
     d = d(:);
   endif
 
-  if (any (d < 0 | d != fix (d)))
-    error ("dec2base: input must be non-negative integers");
+  if (! isnumeric (d) || iscomplex (d) || any (d < 0 | d != fix (d)))
+    error ("dec2base: input must be real non-negative integers");
   endif
 
   symbols = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
@@ -93,7 +98,7 @@
   ## determine digits for each number
   digits = zeros (length (d), max_len);
   for k = max_len:-1:1
-    digits(:,k) = mod(d, base);
+    digits(:,k) = mod (d, base);
     d = round ((d - digits(:,k)) / base);
   endfor
 
@@ -112,41 +117,45 @@
 
 endfunction
 
+
 %!test
-%! s0='';
-%! for n=1:13
-%!   for b=2:16
-%!     pp=dec2base(b^n+1,b);
-%!     assert(dec2base(b^n,b),['1',s0,'0']);
-%!     assert(dec2base(b^n+1,b),['1',s0,'1']);
+%! s0 = '';
+%! for n = 1:13
+%!   for b = 2:16
+%!     pp = dec2base (b^n+1, b);
+%!     assert (dec2base(b^n, b), ['1',s0,'0']);
+%!     assert (dec2base(b^n+1, b), ['1',s0,'1']);
 %!   end
-%!   s0=[s0,'0'];
+%!   s0 = [s0,'0'];
 %! end
 
 %!test
 %! digits='0123456789ABCDEF';
-%! for n=1:13
-%!   for b=2:16
-%!     pm=dec2base(b^n-1,b);
-%!     assert(length(pm),n);
-%!     assert(all(pm==digits(b)));
+%! for n = 1:13
+%!   for b = 2:16
+%!     pm = dec2base(b^n-1, b);
+%!     assert (length (pm), n);
+%!     assert (all (pm==digits(b)));
 %!   end
 %! end
 
 %!test
-%! for b=2:16
-%!   assert(dec2base(0,b),'0');
+%! for b = 2:16
+%!   assert (dec2base (0, b), '0');
 %! end
 
-%!assert(dec2base(0,2,4), "0000");
-%!assert(dec2base(2^51-1,2), ...
+%!assert(dec2base (0, 2, 4), "0000");
+%!assert(dec2base (2^51-1, 2), ...
 %!       '111111111111111111111111111111111111111111111111111');
-%!assert(dec2base(uint64(2)^63-1,16), '7FFFFFFFFFFFFFFF');
+%!assert(dec2base(uint64(2)^63-1, 16), '7FFFFFFFFFFFFFFF');
+%!assert(dec2base({1, 2; 3, 4}, 2, 3), ["001"; "011"; "010"; "100"]);
 
 %%Test input validation
 %!error dec2base ()
 %!error dec2base (1)
 %!error dec2base (1, 2, 3, 4)
+%!error dec2base ("A")
+%!error dec2base (2i)
 %!error dec2base (-1)
 %!error dec2base (1.1)
 %!error dec2base (1,"ABA")
--- a/scripts/strings/dec2bin.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/strings/dec2bin.m	Tue Sep 20 15:38:24 2011 -0400
@@ -28,8 +28,9 @@
 ## @end group
 ## @end example
 ##
-## If @var{d} is a vector, returns a string matrix, one row per value,
-## padded with leading zeros to the width of the largest value.
+## If @var{d} is a matrix or cell array, return a string matrix with one
+## row per element in @var{d}, padded with leading zeros to the width of 
+## the largest value.
 ##
 ## The optional second argument, @var{len}, specifies the minimum
 ## number of digits in the result.
@@ -51,8 +52,10 @@
 
 endfunction
 
-%!assert(strcmp (dec2bin (14), "1110"));
-%!assert(strcmp (dec2bin (14, 6), "001110"));
+
+%!assert(dec2bin (14), "1110");
+%!assert(dec2bin (14, 6), "001110");
+%!assert(dec2bin ({1, 2; 3, 4}), ["001"; "011"; "010"; "100"]);
 
 %%Test input validation
 %!error dec2bin ();
--- a/scripts/strings/dec2hex.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/strings/dec2hex.m	Tue Sep 20 15:38:24 2011 -0400
@@ -28,8 +28,9 @@
 ## @end group
 ## @end example
 ##
-## If @var{d} is a vector, return a string matrix, one row per value,
-## padded with leading zeros to the width of the largest value.
+## If @var{d} is a matrix or cell array, return a string matrix with one
+## row per element in @var{d}, padded with leading zeros to the width of 
+## the largest value.
 ##
 ## The optional second argument, @var{len}, specifies the minimum
 ## number of digits in the result.
@@ -51,8 +52,10 @@
 
 endfunction
 
-%!assert(strcmpi (dec2hex (2748), "abc"));
-%!assert(strcmpi (dec2hex (2748, 5), "00abc"));
+
+%!assert(dec2hex (2748), "ABC");
+%!assert(dec2hex (2748, 5), "00ABC");
+%!assert(dec2hex ({2748, 2746}), ["ABC"; "ABA"]);
 
 %% Test input validation
 %!error dec2hex ();
--- a/scripts/strings/hex2dec.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/strings/hex2dec.m	Tue Sep 20 15:38:24 2011 -0400
@@ -30,8 +30,12 @@
 ## @end group
 ## @end example
 ##
-## If @var{s} is a string matrix, returns a column vector of converted
-## numbers, one per row of @var{s}.  Invalid rows evaluate to NaN.
+## If @var{s} is a string matrix, return a column vector with one converted
+## number per row of @var{s}; Invalid rows evaluate to NaN@.
+##
+## If @var{s} is a cell array of strings, return a column vector with one
+## converted number per cell element in @var{s}.
+##
 ## @seealso{dec2hex, base2dec, bin2dec}
 ## @end deftypefn
 
@@ -40,17 +44,19 @@
 
 function d = hex2dec (s)
 
-  if (nargin == 1 && ischar (s))
-    d = base2dec (s, 16);
-  else
+  if (nargin != 1)
     print_usage ();
   endif
 
+  d = base2dec (s, 16);
+
 endfunction
 
+
 %!assert(hex2dec ("0000"), 0);
 %!assert(hex2dec ("1FFFFFFFFFFFFF"), 2^53-1);
-%!assert(hex2dec ("12b") == 299 && hex2dec ("12B") == 299);
+%!assert(hex2dec (["12b"; "12B"]), [299; 299]);
+%!assert(hex2dec ({"A1", "1A"}), [161; 26]);
 
 %%Test input validation
 %!error hex2dec ();
--- a/scripts/strings/index.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/strings/index.m	Tue Sep 20 15:38:24 2011 -0400
@@ -62,13 +62,13 @@
 
   if (strcmp (direction, "last"))
     if (iscell (f))
-      n = cellfun (@min, f);
+      n = cellfun ("min", f);
     else
       n = f(end);
     endif
   elseif (strcmp (direction, "first"))
     if (iscell (f))
-      n = cellfun (@max, f);
+      n = cellfun ("max", f);
     else
       n = f(1);
     endif
--- a/scripts/strings/mat2str.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/strings/mat2str.m	Tue Sep 20 15:38:24 2011 -0400
@@ -28,7 +28,7 @@
 ## scalar then both real and imaginary parts of the matrix are printed
 ## to the same precision.  Otherwise @code{@var{n} (1)} defines the
 ## precision of the real part and @code{@var{n} (2)} defines the
-## precision of the imaginary part.  The default for @var{n} is 17.
+## precision of the imaginary part.  The default for @var{n} is 15.
 ##
 ## If the argument 'class' is given, then the class of @var{x} is
 ## included in the string in such a way that the eval will result in the
@@ -56,13 +56,13 @@
 
   if (nargin < 2 || isempty (n))
     ## Default precision
-    n = 17;
+    n = 15;
   endif
 
   if (nargin < 3)
     if (ischar (n))
       cls = n;
-      n = 17;
+      n = 15;
     else
       cls = "";
     endif
@@ -137,3 +137,4 @@
 %!assert (mat2str (true), "true");
 %!assert (mat2str (false), "false");
 %!assert (mat2str (logical (eye (2))), "[true,false;false,true]");
+%!assert (mat2str (0.7), "0.7")
--- a/scripts/strings/strcat.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/strings/strcat.m	Tue Sep 20 15:38:24 2011 -0400
@@ -61,14 +61,14 @@
     elseif (nargin > 1)
       ## Convert to cells of strings
       uo = "uniformoutput";
-      reals = cellfun (@isreal, varargin);
+      reals = cellfun ("isreal", varargin);
       if (any (reals))
-        varargin(reals) = cellfun (@char, varargin(reals), uo, false);
+        varargin(reals) = cellfun ("char", varargin(reals), uo, false);
       endif
-      chars = cellfun (@ischar, varargin);
+      chars = cellfun ("isclass", varargin, "char");
       allchar = all (chars);
-      varargin(chars) = cellfun (@cellstr, varargin(chars), uo, false);
-      if (! all (cellfun (@iscell, varargin)))
+      varargin(chars) = cellfun ("cellstr", varargin(chars), uo, false);
+      if (! all (cellfun ("isclass", varargin, "cell")))
         error ("strcat: inputs must be strings or cells of strings");
       endif
 
@@ -81,7 +81,7 @@
       endif
 
       ## Cellfun handles everything for us.
-      st = cellfun (@horzcat, varargin{:}, uo, false);
+      st = cellfun ("horzcat", varargin{:}, uo, false);
 
       if (allchar)
         ## If all inputs were strings, return strings.
--- a/scripts/strings/strmatch.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/strings/strmatch.m	Tue Sep 20 15:38:24 2011 -0400
@@ -19,13 +19,15 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} strmatch (@var{s}, @var{A}, "exact")
-## Return indices of entries of @var{A} that match the string @var{s}.
-## The second argument @var{A} may be a string matrix or a cell array of
-## strings.  If the third argument @code{"exact"} is not given, then
+## @deftypefn  {Function File} {} strmatch (@var{s}, @var{A})
+## @deftypefnx {Function File} {} strmatch (@var{s}, @var{A}, "exact")
+## Return indices of entries of @var{A} which begin with the string @var{s}.
+## The second argument @var{A} must be a string, character matrix, or a cell
+## array of strings.  If the third argument @code{"exact"} is not given, then
 ## @var{s} only needs to match @var{A} up to the length of @var{s}.
-## Trailing whitespace is ignored.
-## Results are returned as a column vector.
+## Trailing spaces and nulls in @var{s} and @var{A} are ignored when matching.
+## option.
+##
 ## For example:
 ##
 ## @example
@@ -33,13 +35,16 @@
 ## strmatch ("apple", "apple juice")
 ##      @result{} 1
 ##
-## strmatch ("apple", ["apple pie"; "apple juice"; "an apple"])
+## strmatch ("apple", ["apple  "; "apple juice"; "an apple"])
 ##      @result{} [1; 2]
 ##
-## strmatch ("apple", @{"apple pie"; "apple juice"; "tomato"@})
-##      @result{} [1; 2]
+## strmatch ("apple", ["apple  "; "apple juice"; "an apple"], "exact")
+##      @result{} [1]
 ## @end group
 ## @end example
+##
+## @strong{Caution:} @code{strmatch} is scheduled for deprecation.  Use
+## @code{strcmpi} or @code{strncmpi} in all new code.
 ## @seealso{strfind, findstr, strcmp, strncmp, strcmpi, strncmpi, find}
 ## @end deftypefn
 
@@ -52,29 +57,19 @@
     print_usage ();
   endif
 
-  if (! ischar (s))
+  if (! ischar (s) || (! isempty (s) && ! isvector (s)))
     error ("strmatch: S must be a string");
+  elseif (! (ischar (A) || iscellstr (A)))
+    error ("strmatch: A must be a string or cell array of strings");
   endif
 
-  ## Truncate trailing whitespace.
-  s = strtrimr (s);
-
+  ## Trim blanks and nulls from search string
+  s = regexprep (s, "[ \\0]+$", '');
   len = length (s);
 
   exact = nargin == 3 && ischar (exact) && strcmp (exact, "exact");
 
-  if (iscell (A))
-    if (len > 0)
-      idx = find (strncmp (s, A, len));
-    else
-      idx = find (strcmp (s, A));
-    endif
-    if (exact)
-      ## We can't just use strcmp, because we need to ignore whitespace.
-      B = cellfun (@strtrimr, A(idx), "uniformoutput", false);
-      idx = idx (strcmp (s, B));
-    endif
-  elseif (ischar (A))
+  if (ischar (A))
     [nr, nc] = size (A);
     if (len > nc)
       idx = [];
@@ -82,34 +77,43 @@
       match = all (bsxfun (@eq, A(:,1:len), s), 2);
       if (exact)
         AA = A(:,len+1:nc);
-        match &= all (AA == "\0" | AA == " ", 2);
+        match &= all (AA == " " | AA == "\0", 2);
       endif
       idx = find (match);
     endif
   else
-    error ("strmatch: A must be a string or cell array of strings");
+    if (len > 0)
+      idx = find (strncmp (s, A, len));
+    else
+      idx = find (strcmp (s, A));
+    endif
+    if (exact)
+      ## We can't just use strcmp, because we need to ignore spaces at end.
+      B = regexprep (A(idx), "[ \\0]+$", '');
+      idx = idx(strcmp (s, B));
+    endif
   endif
 
 endfunction
 
-## Removes nuls and blanks from the end of the array
-function s = strtrimr (s)
-  blnks = s == "\0" | s == " ";
-  i = find (blnks, 1, "last");
-  if (i && all (blnks(i:end)))
-    s = s(1:i-1);
-  endif
-endfunction
 
-%!error <Invalid call to strmatch> strmatch();
-%!error <Invalid call to strmatch> strmatch("a", "aaa", "exact", 1);
 %!assert (strmatch("a", {"aaa", "bab", "bbb"}), 1);
 %!assert (strmatch ("apple", "apple juice"), 1);
-%!assert (strmatch ("apple", ["apple pie"; "apple juice"; "an apple"]),
-%!        [1; 2]);
-%!assert (strmatch ("apple", {"apple pie"; "apple juice"; "tomato"}),
-%!        [1; 2]);
+%!assert (strmatch ("apple", ["apple pie"; "apple juice"; "an apple"]), [1; 2]);
+%!assert (strmatch ("apple", {"apple pie"; "apple juice"; "tomato"}), [1; 2]);
 %!assert (strmatch ("apple pie", "apple"), []);
-%!assert (strmatch ("a b", {"a b", "a c", "c d"}));
-%!assert (strmatch ("", {"", "foo", "bar", ""}), [1, 4])
-%!assert (strmatch ('', { '', '% comment line', 'var a = 5', ''}, 'exact'), [1,4])
+%!assert (strmatch ("a ", "a"), 1);
+%!assert (strmatch ("a", "a \0", "exact"), 1);
+%!assert (strmatch ("a b", {"a b", "a c", "c d"}), 1);
+%!assert (strmatch ("", {"", "foo", "bar", ""}), [1, 4]);
+%!assert (strmatch ('', { '', '% comment', 'var a = 5', ''}, 'exact'), [1,4]);
+
+%% Test input validation
+%!error <Invalid call to strmatch> strmatch();
+%!error <Invalid call to strmatch> strmatch("a");
+%!error <Invalid call to strmatch> strmatch("a", "aaa", "exact", 1);
+%!error <S must be a string> strmatch(1, "aaa");
+%!error <S must be a string> strmatch(char ("a", "bb"), "aaa");
+%!error <A must be a string> strmatch("a", 1);
+%!error <A must be a string> strmatch("a", {"hello", [1]});
+
--- a/scripts/strings/strsplit.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/strings/strsplit.m	Tue Sep 20 15:38:24 2011 -0400
@@ -28,7 +28,7 @@
 function s = strsplit (p, sep, strip_empty = false)
 
   if (nargin < 2 || nargin > 3 || ! ischar (p) || rows (p) > 1
-      || ! ischar (sep) || ! islogical (strip_empty))
+      || ! ischar (sep) || ! isscalar (strip_empty))
     print_usage ();
   endif
 
--- a/scripts/strings/strtrim.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/strings/strtrim.m	Tue Sep 20 15:38:24 2011 -0400
@@ -18,20 +18,21 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} strtrim (@var{s})
-## Remove leading and trailing whitespace and nulls from @var{s}.  If
+## Remove leading and trailing whitespace from @var{s}.  If
 ## @var{s} is a matrix, @var{strtrim} trims each row to the length of
-## longest string.  If @var{s} is a cell array, operate recursively on
-## each element of the cell array.  For example:
+## longest string.  If @var{s} is a cell array of strings, operate recursively
+## on each string element.  For example:
 ##
 ## @example
 ## @group
 ## strtrim ("    abc  ")
-##      @result{} "abc"
+##      @result{}  "abc"
 ##
 ## strtrim ([" abc   "; "   def   "])
-##      @result{} ["abc  "; "  def"]
+##      @result{}  ["abc  "  ; "  def"]
 ## @end group
 ## @end example
+## @seealso{deblank}
 ## @end deftypefn
 
 ## Author: John Swensen <jpswensen@jhu.edu>
@@ -46,19 +47,28 @@
 
   if (ischar (s))
 
-    k = find (! isspace (s) & s != "\0");
+    k = find (! isspace (s));
     if (isempty (s) || isempty (k))
       s = "";
     else
       s = s(:, ceil (min (k) / rows (s)):ceil (max (k) / rows (s)));
     endif
 
-  elseif (iscell(s))
+  elseif (iscell (s))
 
-    s = regexprep (s, "^[\\s\v\\0]+|[\\s\v\\0]+$", '');
+    char_idx = cellfun ("isclass", s, "char");
+    cell_idx = cellfun ("isclass", s, "cell");
+    if (! all (char_idx | cell_idx))  
+      error ("strtrim: S argument must be a string or cellstring");
+    endif
+
+    ## Divide work load.  Recursive cellfun strtrim call is slow
+    ## and avoided where possible.
+    s(char_idx) = regexprep (s(char_idx), "^[\\s\v]+|[\\s\v]+$", '');
+    s(cell_idx) = cellfun ("strtrim", s(cell_idx), "UniformOutput", false);
 
   else
-    error ("strtrim: S argument must be a string");
+    error ("strtrim: S argument must be a string or cellstring");
   endif
 
 endfunction
@@ -69,8 +79,10 @@
 %!assert (strtrim ("abc"), "abc");
 %!assert (strtrim ([" abc   "; "   def   "]), ["abc  "; "  def"]);
 %!assert (strtrim ({" abc   "; "   def   "}), {"abc"; "def"});
+%!assert (strtrim ({" abc   ", {"   def   "}}), {"abc", {"def"}});
 
 %!error <Invalid call to strtrim> strtrim ();
 %!error <Invalid call to strtrim> strtrim ("abc", "def");
 %!error <argument must be a string> strtrim (1);
+%!error <argument must be a string> strtrim ({[]});
 
--- a/scripts/strings/untabify.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/strings/untabify.m	Tue Sep 20 15:38:24 2011 -0400
@@ -52,64 +52,72 @@
 
 function s = untabify (t, tw = 8, dblank = false)
 
- if (nargin > 0 && nargin < 4 && (ischar (t) || iscellstr (t)))
-   if (ischar (t))
-     s = replace_tabs (t, tw);
-   else
-     s = cellfun (@(str) replace_tabs (str, tw), t, "uniformoutput", false);
-   endif
-   if (dblank)
-     s = deblank (s);
-   endif
- else
-   print_usage ();
- endif
+  if (nargin < 1 || nargin > 3)
+    print_usage ();
+  elseif (! (ischar (t) || iscellstr (t)))
+    error ("untabify: T must be a string or cellstring");
+  endif
+
+  if (ischar (t))
+    s = replace_tabs (t, tw);
+  else
+    s = cellfun (@(str) replace_tabs (str, tw), t, "uniformoutput", false);
+  endif
+
+  if (dblank)
+    s = deblank (s);
+  endif
 
 endfunction
 
 function s = replace_tabs (t, tw)
- if (ndims (t) == 2)
-   if (isempty (t))
-     s = t;
-   else
-     nr = rows (t);
-     sc = cell (nr, 1);
-     for j = 1:nr
-       n = 1:numel(t(j,:));
-       m = find (t(j,:) == "\t");
-       t(j,m) = " ";
-       for i = 1:numel(m)
-         k = tw * ceil (n(m(i)) / tw);
-         dn = k - n(m(i));
-         n(m(i):end) += dn;
-       endfor
-       sc{j} = blanks (n(end));
-       sc{j}(n) = t(j,:);
-     endfor
-     s = char (sc);
-   endif
- else
-   error ("untabify: character strings to untabify must have 2 dimensions");
- endif
+
+  if (ndims (t) != 2)
+    error ("untabify: character strings to untabify must have 2 dimensions");
+  endif
+
+  if (isempty (t))
+    s = t;
+  else
+    nr = rows (t);
+    sc = cell (nr, 1);
+    for j = 1:nr
+      n = 1:numel(t(j,:));
+      m = find (t(j,:) == "\t");
+      t(j,m) = " ";
+      for i = 1:numel(m)
+        k = tw * ceil (n(m(i)) / tw);
+        dn = k - n(m(i));
+        n(m(i):end) += dn;
+      endfor
+      sc{j} = blanks (n(end));
+      sc{j}(n) = t(j,:);
+    endfor
+    s = char (sc);
+  endif
+
 endfunction
 
+
 %!test
 %! s = untabify ("\thello\t");
-%! assert (isequal (s, horzcat (blanks(8), "hello   ")))
+%! assert (s, [blanks(8) "hello" blanks(3)]);
+
+%!test
+%! s = untabify ("\thello\t", 2);
+%! assert (s, [blanks(2) "hello" blanks(1)]);
 
 %!test
 %! s = untabify ("\thello\t", 4, true);
-%! assert (isequal (s, horzcat (blanks(4), "hello")))
+%! assert (s, [blanks(4) "hello"]);
 
-%!test
-%! s = untabify ("\thello\t", 2, true);
-%! assert (isequal (s, horzcat (blanks(2), "hello")))
+%!assert (isempty (untabify ("")))
 
 %!test
-%! s = untabify ("");
-%! assert (isempty (s))
+%! s = char (randi ([97 97+25], 3, 3));
+%! assert (untabify (s), char (untabify (cellstr (s))));
 
-%!test
-%! s = char (fix (100 + 10*rand (3,3)));
-%! assert (isequal (untabify (s), untabify ({s}){1}))
+%!error untabify ()
+%!error untabify (1,2,3,4)
+%!error <must be a string> untabify (1)
 
--- a/scripts/strings/validatestring.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/strings/validatestring.m	Tue Sep 20 15:38:24 2011 -0400
@@ -118,7 +118,7 @@
     ## are the matches a substring of each other, if so, choose the
     ## shortest.  If not, raise an error.
     match_idx = find (matches);
-    match_l = cellfun (@length, strarray(match_idx));
+    match_l = cellfun ("length", strarray(match_idx));
     longest_idx = find (match_l == max (match_l), 1);
     shortest_idx = find (match_l == min (match_l), 1);
     longest = strarray(match_idx)(longest_idx);
--- a/scripts/testfun/demo.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/testfun/demo.m	Tue Sep 20 15:38:24 2011 -0400
@@ -17,35 +17,39 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Command} {} demo @var{name} @var{n}
+## @deftypefn  {Command} {} demo @var{name}
+## @deftypefnx {Command} {} demo @var{name} @var{n}
+## @deftypefnx {Function File} {} demo ('@var{name}')
 ## @deftypefnx {Function File} {} demo ('@var{name}', @var{n})
 ##
-## Runs any examples associated with the function '@var{name}'.
+## Run example code block @var{n} associated with the function @var{name}.
+## If @var{n} is not specified, all examples are run.
+##
 ## Examples are stored in the script file, or in a file with the same
-## name but no extension somewhere on your path.  To keep them separate
-## from the usual script code, all lines are prefixed by @code{%!}.  Each
-## example is introduced by the keyword 'demo' flush left to the prefix,
-## with no intervening spaces.  The remainder of the example can contain
-## arbitrary Octave code.  For example:
+## name but no extension located on Octave's load path.  To keep examples
+## separate from regular script code, all lines are prefixed by @code{%!}.  Each
+## example must also be introduced by the keyword 'demo' flush left to the
+## prefix with no intervening spaces.  The remainder of the example can
+## contain arbitrary Octave code.  For example:
 ##
 ## @example
 ## @group
-##    %!demo
-##    %! t=0:0.01:2*pi; x = sin(t);
-##    %! plot(t,x)
-##    %! %-------------------------------------------------
-##    %! % the figure window shows one cycle of a sine wave
+##   %!demo
+##   %! t=0:0.01:2*pi; x = sin(t);
+##   %! plot (t,x)
+##   %! %-------------------------------------------------
+##   %! % the figure window shows one cycle of a sine wave
 ## @end group
 ## @end example
 ##
 ## Note that the code is displayed before it is executed, so a simple
-## comment at the end suffices.  It is generally not necessary to use
-## disp or printf within the demo.
+## comment at the end suffices for labeling what is being shown.  It is
+## generally not necessary to use @code{disp} or @code{printf} within the demo.
 ##
 ## Demos are run in a function environment with no access to external
-## variables.  This means that all demos in your function must use
-## separate initialization code.  Alternatively, you can combine your
-## demos into one huge demo, with the code:
+## variables.  This means that every demo must have separate initialization
+## code.  Alternatively, all demos can be combined into a single large demo
+## with the code
 ##
 ## @example
 ##    %! input("Press <enter> to continue: ","s");
@@ -53,11 +57,13 @@
 ##
 ## @noindent
 ## between the sections, but this is discouraged.  Other techniques
-## include using multiple plots by saying figure between each, or
-## using subplot to put multiple plots in the same window.
+## to avoid multiple initialization blocks include using multiple plots
+## with a new @code{figure} command between each plot, or using @code{subplot}
+## to put multiple plots in the same window.
 ##
-## Also, since demo evaluates inside a function context, you cannot
-## define new functions inside a demo.  Instead you will have to
+## Also, because demo evaluates within a function context, you cannot
+## define new functions inside a demo.  If you must have function blocks,
+## rather than just anonymous functions or inline functions, you will have to
 ## use @code{eval(example('function',n))} to see them.  Because eval only
 ## evaluates one line, or one statement if the statement crosses
 ## multiple lines, you must wrap your demo in "if 1 <demo stuff> endif"
@@ -73,6 +79,7 @@
 ##   %! endif
 ## @end group
 ## @end example
+##
 ## @seealso{test, example}
 ## @end deftypefn
 
@@ -88,20 +95,19 @@
 
   if (nargin < 2)
     n = 0;
-  elseif (strcmp ("char", class (n)))
+  elseif (ischar (n))
     n = str2double (n);
-  endif 
+  endif
 
   [code, idx] = test (name, "grabdemo");
-  if (length (idx) == 0)
-    warning ("demo not available for %s", name);
+  if (isempty (idx))
+    warning ("no demo available for %s", name);
     return;
   elseif (n >= length (idx))
     warning ("only %d demos available for %s", length (idx) - 1, name);
     return;
   endif
 
-
   if (n > 0)
     doidx = n;
   else
@@ -123,7 +129,7 @@
       __demo__;
     catch
       ## Let the programmer know which demo failed.
-      printf ("%s example %d: failed\n%s\n", name, doidx(i), __error_text__);
+      printf ("%s example %d: failed\n%s\n", name, doidx(i), lasterr ());
     end_try_catch
     clear __demo__;
   endfor
@@ -132,6 +138,9 @@
 
 %!demo
 %! t=0:0.01:2*pi; x = sin(t);
-%! plot(t,x)
+%! plot (t,x)
 %! %-------------------------------------------------
 %! % the figure window shows one cycle of a sine wave
+
+%!error demo ();
+%!error demo (1, 2, 3);
--- a/scripts/testfun/example.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/testfun/example.m	Tue Sep 20 15:38:24 2011 -0400
@@ -17,16 +17,18 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Command} {} example @var{name} @var{n}
+## @deftypefn  {Command} {} example @var{name}
+## @deftypefnx {Command} {} example @var{name} @var{n}
+## @deftypefnx {Function File} {} example ('@var{name}')
 ## @deftypefnx {Function File} {} example ('@var{name}', @var{n})
-## @deftypefnx {Function File} {[@var{x}, @var{idx}] =} example ('@var{name}', @var{n})
+## @deftypefnx {Function File} {[@var{s}, @var{idx}] =} example (@dots{})
 ##
-##  Display the code for example @var{n} associated with the function
-## '@var{name}', but do not run it.  If @var{n} is not given, all examples
+## Display the code for example @var{n} associated with the function
+## '@var{name}', but do not run it.  If @var{n} is not specified, all examples
 ## are displayed.
 ##
-## Called with output arguments, the examples are returned in the form of
-## a string @var{x}, with @var{idx} indicating the ending position of the
+## When called with output arguments, the examples are returned in the form of
+## a string @var{s}, with @var{idx} indicating the ending position of the
 ## various examples.
 ##
 ## See @code{demo} for a complete explanation.
@@ -41,9 +43,9 @@
 
   if (nargin < 2)
     n = 0;
-  elseif (strcmp ("char", class (n)))
+  elseif (ischar (n))
     n = str2double (n);
-  endif 
+  endif
 
   [code, idx] = test (name, "grabdemo");
   if (nargout > 0)
@@ -65,15 +67,16 @@
     else
       doidx = 1:length(idx)-1;
     endif
-    if (length (idx) == 0)
-      warning ("example not available for %s", name);
+    if (isempty (idx))
+      warning ("no example available for %s", name);
+      return;
     elseif (n >= length(idx))
       warning ("only %d examples available for %s", length(idx)-1, name);
-      doidx = [];
+      return;
     endif
 
     for i = 1:length (doidx)
-      block = code (idx(doidx(i)):idx(doidx(i)+1)-1);
+      block = code(idx(doidx(i)):idx(doidx(i)+1)-1);
       printf ("%s example %d:%s\n\n", name, doidx(i), block);
     endfor
   endif
@@ -82,17 +85,18 @@
 
 %!## warning: don't modify the demos without modifying the tests!
 %!demo
-%! example('example');
+%! example ('example');
 %!demo
-%! t=0:0.01:2*pi; x=sin(t);
-%! plot(t,x)
+%! t=0:0.01:2*pi; x = sin(t);
+%! plot (t,x)
 
-%!assert (example('example',1), "\n example('example');");
+%!assert (example('example',1), "\n example ('example');");
 %!test
-%! [code, idx] = example('example');
+%! [code, idx] = example ('example');
 %! assert (code, ...
-%!         "\n example('example');\n t=0:0.01:2*pi; x=sin(t);\n plot(t,x)")
-%! assert (idx, [1, 22, 59]);
+%!         "\n example ('example');\n t=0:0.01:2*pi; x = sin(t);\n plot (t,x)")
+%! assert (idx, [1, 23, 63]);
 
+%% Test input validation
 %!error example;
-%!error example('example',3,5)
+%!error example('example', 3, 5)
--- a/scripts/testfun/fail.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/testfun/fail.m	Tue Sep 20 15:38:24 2011 -0400
@@ -129,15 +129,16 @@
 
 endfunction
 
-%!fail ('[1,2]*[2,3]','nonconformant')
-%!fail ("fail('[1,2]*[2;3]','nonconformant')","expected error <nonconformant> but got none")
-%!fail ("fail('[1,2]*[2,3]','usage:')","expected error <usage:>\nbut got.*nonconformant")
-%!fail ("warning('test warning')",'warning','test warning');
+
+%!fail ('[1,2]*[2,3]', 'nonconformant')
+%!fail ("fail('[1,2]*[2;3]', 'nonconformant')", "expected error <nonconformant> but got none")
+%!fail ("fail('[1,2]*[2,3]','usage:')", "expected error <usage:>\nbut got.*nonconformant")
+%!fail ("warning('test warning')", 'warning','test warning');
 
-%!# fail ("warning('next test')",'warning','next test');  ## only allowed one warning test?!?
+##% !fail ("warning('next test')",'warning','next test');  ## only allowed one warning test?!?
 
-## Comment out the following tests if you don't want to see what
-## errors look like
-% !fail ('a*[2;3]', 'nonconformant')
-% !fail ('a*[2,3]', 'usage:')
-% !fail ("warning('warning failure')", 'warning', 'success')
+%% Test that fail() itself will generate an error
+%!error fail ("1");
+%!error <undefined> fail ('a*[2;3]', 'nonconformant')
+%!error <expected error>  fail ('a*[2,3]', 'usage:')
+%!error <warning failure> fail ("warning('warning failure')", 'warning', 'success')
--- a/scripts/testfun/rundemos.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/testfun/rundemos.m	Tue Sep 20 15:38:24 2011 -0400
@@ -35,6 +35,7 @@
     if (is_absolute_filename (directory))
       dirs = {directory};
     else
+      directory = regexprep (directory, ['\',filesep(),'$'], "");
       fullname = find_dir_in_path (directory);
       if (! isempty (fullname))
         dirs = {fullname};
@@ -80,3 +81,5 @@
     retval = findstr (str, "%!demo");
   endif
 endfunction
+
+%!error rundemos ("foo", 1);
--- a/scripts/testfun/runtests.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/testfun/runtests.m	Tue Sep 20 15:38:24 2011 -0400
@@ -35,6 +35,7 @@
     if (is_absolute_filename (directory))
       dirs = {directory};
     else
+      directory = regexprep (directory, ['\',filesep(),'$'], "");
       fullname = find_dir_in_path (directory);
       if (! isempty (fullname))
         dirs = {fullname};
--- a/scripts/testfun/speed.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/testfun/speed.m	Tue Sep 20 15:38:24 2011 -0400
@@ -25,7 +25,8 @@
 ## each @var{n}, an initialization expression (@var{init}) is computed to
 ## create any data needed for the test.  If a second expression (@var{f2}) is
 ## given then the execution times of the two expressions are compared.  When
-## called without output arguments the results are displayed graphically.
+## called without output arguments the results are printed to stdout and
+## displayed graphically.
 ##
 ## @table @code
 ## @item @var{f}
@@ -115,7 +116,7 @@
 ##
 ## @example
 ## @group
-## speed ("v = sum (x)", "", [10000, 100000], ...
+## speed ("sum (x)", "", [10000, 100000], ...
 ##        "v = 0; for i = 1:length (x), v += x(i); end")
 ## @end group
 ## @end example
@@ -127,10 +128,10 @@
 ##
 ## @example
 ## @group
-## speed ("v = xcorr (x, n)", "x = rand (128, 1);", 100,
-##        "v2 = xcorr_orig (x, n)", -100*eps)
-## speed ("v = xcorr (x, 15)", "x = rand (20+n, 1);", 100,
-##        "v2 = xcorr_orig (x, n)", -100*eps)
+## speed ("xcorr (x, n)", "x = rand (128, 1);", 100,
+##        "xcorr_orig (x, n)", -100*eps)
+## speed ("xcorr (x, 15)", "x = rand (20+n, 1);", 100,
+##        "xcorr_orig (x, n)", -100*eps)
 ## @end group
 ## @end example
 ##
@@ -191,7 +192,12 @@
 
   __torig = __tnew = zeros (size (__test_n));
 
-  disp (cstrcat ("testing ", __f1, "\ninit: ", __init));
+  ## Print and plot the data if no output is requested.
+  do_display = (nargout == 0);
+
+  if (do_display)
+    disp (cstrcat ("testing ", __f1, "\ninit: ", __init));
+  endif
 
   ## Make sure the functions are freshly loaded by evaluating them at
   ## test_n(1); first have to initialize the args though.
@@ -208,8 +214,10 @@
     n = __test_n(k);
     eval (cstrcat (__init, ";"));
 
-    printf ("n%i = %i  ",k, n);
-    fflush (stdout);
+    if (do_display)
+      printf ("n%i = %i  ",k, n);
+      fflush (stdout);
+    endif
     eval (cstrcat ("__t = time();", __f1, "; __v1=ans; __t = time()-__t;"));
     if (__t < 0.25)
       eval (cstrcat ("__t2 = time();", __f1, "; __t2 = time()-__t2;"));
@@ -251,14 +259,12 @@
     __order.a = exp (p(2));
   endif
 
-  ## Plot the data if no output is requested.
-  doplot = (nargout == 0);
-
-  if (doplot)
+  if (do_display)
     figure;
   endif
 
-  if (doplot && ! isempty (__f2))
+  if (do_display && ! isempty (__f2))
+
     subplot (1, 2, 1);
     semilogx (__test_n, __torig./__tnew,
               cstrcat ("-*r;", strrep (__f1, ";", "."), "/",
@@ -284,7 +290,7 @@
     printf ("\n\nMean runtime ratio = %.3g for '%s' vs '%s'\n",
             ratio, __f2, __f1);
 
-  elseif (doplot)
+  elseif (do_display)
 
     loglog (__test_n, __tnew*1000, "*-g;execution time;");
     xlabel ("test length");
@@ -293,7 +299,7 @@
 
   endif
 
-  if (doplot)
+  if (do_display)
 
     ## Plot time complexity approximation (using milliseconds).
     order = sprintf ("O(n^%g)", round (10*p(1))/10);
@@ -314,10 +320,12 @@
       time = sprintf ("%g ns", dt*1e9);
     endif
 
-    ## Display nicely formatted complexity.
-    printf ("\nFor %s:\n", __f1);
-    printf ("  asymptotic power: %s\n", order);
-    printf ("  approximate time per operation: %s\n", time);
+    if (do_display)
+      ## Display nicely formatted complexity.
+      printf ("\nFor %s:\n", __f1);
+      printf ("  asymptotic power: %s\n", order);
+      printf ("  approximate time per operation: %s\n", time);
+    endif
 
   endif
 
@@ -378,3 +386,30 @@
 %!  disp("This time, the for loop is done away with entirely.");
 %!  disp("Notice how much bigger the speedup is than in example 1.");
 %! endif
+
+%!error speed ();
+%!error speed (1, 2, 3, 4, 5, 6, 7);
+
+%!test
+%! [order, n, T_f1, T_f2] = speed ("airy (x)", "x = rand (n, 10)", [100, 1000]);
+%! assert (isstruct (order));
+%! assert (size (order), [1, 1]);
+%! assert (fieldnames (order), {"p"; "a"});
+%! assert (isnumeric (n));
+%! assert (size (n), [1, 15]);
+%! assert (isnumeric (T_f1));
+%! assert (size (T_f1), [1, 15]);
+%! assert (isnumeric (T_f1));
+%! assert (size (T_f2), [1, 15]);
+
+%!test
+%! [order, n, T_f1, T_f2] = speed ("sum (x)", "", [100, 1000], "v = 0; for i = 1:length (x), v += x(i); end");
+%! assert (isstruct (order));
+%! assert (size (order), [1, 1]);
+%! assert (fieldnames (order), {"p"; "a"});
+%! assert (isnumeric (n));
+%! assert (size (n), [1, 15]);
+%! assert (isnumeric (T_f1));
+%! assert (size (T_f1), [1, 15]);
+%! assert (isnumeric (T_f1));
+%! assert (size (T_f2), [1, 15]);
--- a/scripts/testfun/test.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/testfun/test.m	Tue Sep 20 15:38:24 2011 -0400
@@ -132,7 +132,7 @@
     __rundemo = 0;
     __verbose = 0;
     __demo_code = "";
-    __demo_idx = 1;
+    __demo_idx = [];
   elseif (strcmp (__flag, "explain"))
     fprintf (__fid, "# %s new test file\n", __signal_file);
     fprintf (__fid, "# %s no tests in file\n", __signal_empty);
@@ -286,7 +286,7 @@
           input ("Press <enter> to continue: ", "s");
         catch
           __success = 0;
-          __msg = sprintf ("%sdemo failed\n%s",  __signal_fail, __error_text__);
+          __msg = sprintf ("%sdemo failed\n%s",  __signal_fail, lasterr ());
         end_try_catch
         clear __test__;
 
@@ -359,7 +359,7 @@
         catch
           __success = 0;
           __msg = sprintf ("%stest failed: syntax error\n%s",
-                           __signal_fail, __error_text__);
+                           __signal_fail, lasterr ());
         end_try_catch
       endif
       __code = "";
@@ -389,7 +389,7 @@
       catch
         __success = 0;
         __msg = sprintf ("%stest failed: syntax error\n%s",
-                         __signal_fail, __error_text__);
+                         __signal_fail, lasterr ());
       end_try_catch
 
       if (__success)
@@ -488,13 +488,13 @@
         eval (sprintf ("%s__test__(%s);", __shared_r, __shared));
       catch
         if (strcmp (__type, "xtest"))
-           __msg = sprintf ("%sknown failure\n%s", __signal_fail, __error_text__);
+           __msg = sprintf ("%sknown failure\n%s", __signal_fail, lasterr ());
            __xfail++;
         else
-           __msg = sprintf ("%stest failed\n%s", __signal_fail, __error_text__);
+           __msg = sprintf ("%stest failed\n%s", __signal_fail, lasterr ());
            __success = 0;
         endif
-        if (isempty (__error_text__))
+        if (isempty (lasterr ()))
           error ("empty error text, probably Ctrl-C --- aborting");
         endif
       end_try_catch
--- a/scripts/time/datenum.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/time/datenum.m	Tue Sep 20 15:38:24 2011 -0400
@@ -50,7 +50,7 @@
 ## Days can be fractional.
 ## @end itemize
 ##
-## @strong{Warning:} this function does not attempt to handle Julian
+## @strong{Caution:} this function does not attempt to handle Julian
 ## calendars so dates before Octave 15, 1582 are wrong by as much
 ## as eleven days.  Also be aware that only Roman Catholic countries
 ## adopted the calendar in 1582.  It took until 1924 for it to be
--- a/scripts/time/datetick.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/time/datetick.m	Tue Sep 20 15:38:24 2011 -0400
@@ -67,6 +67,9 @@
 %! datetick(2,'keepticks')
 %! set(ax,'ytick',12:16)
 
+## Remove from test statistics.  No real tests possible.
+%!assert (1)
+
 function __datetick__ (varargin)
 
   keeplimits = false;
--- a/scripts/time/now.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/scripts/time/now.m	Tue Sep 20 15:38:24 2011 -0400
@@ -37,7 +37,11 @@
 
 function t = now ()
 
-  t = datenum (clock ());
+  if (nargin == 0)
+    t = datenum (clock ());
+  else
+    print_usage ();
+  endif
 
   ## The following doesn't work (e.g., one hour off on 2005-10-04):
   ##
@@ -50,3 +54,8 @@
   ## changing by an hour the offset from CUT for part of the year.
 
 endfunction
+
+%!error now (1);
+%!assert (isnumeric (now ()));
+%!assert (now () > 0);
+%!assert (now () <= now ());
--- a/src/DLD-FUNCTIONS/__contourc__.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/DLD-FUNCTIONS/__contourc__.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -333,3 +333,10 @@
 
   return retval;
 }
+
+/*
+
+## No test needed for internal helper function.
+%!assert (1)
+
+*/
--- a/src/DLD-FUNCTIONS/__delaunayn__.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/DLD-FUNCTIONS/__delaunayn__.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -226,3 +226,10 @@
 
   return retval;
 }
+
+/*
+
+## No test needed for internal helper function.
+%!assert (1)
+
+*/
--- a/src/DLD-FUNCTIONS/__dispatch__.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/DLD-FUNCTIONS/__dispatch__.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -129,3 +129,10 @@
 
   return retval;
 }
+
+/*
+
+## No test needed for internal helper function.
+%!assert (1)
+
+*/
--- a/src/DLD-FUNCTIONS/__dsearchn__.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/DLD-FUNCTIONS/__dsearchn__.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -108,3 +108,10 @@
 
   return retval;
 }
+
+/*
+
+## No test needed for internal helper function.
+%!assert (1)
+
+*/
--- a/src/DLD-FUNCTIONS/__fltk_uigetfile__.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/DLD-FUNCTIONS/__fltk_uigetfile__.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -130,4 +130,11 @@
   return retval;
 }
 
+/*
+
+## No test needed for internal helper function.
+%!assert (1)
+
+*/
+
 #endif
--- a/src/DLD-FUNCTIONS/__glpk__.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/DLD-FUNCTIONS/__glpk__.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -854,3 +854,10 @@
 
   return retval;
 }
+
+/*
+
+## No test needed for internal helper function.
+%!assert (1)
+
+*/
--- a/src/DLD-FUNCTIONS/__init_fltk__.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/DLD-FUNCTIONS/__init_fltk__.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -648,13 +648,13 @@
     begin ();
     {
 
+      canvas = new
+        OpenGL_fltk (0, 0, ww , hh - status_h, number ());
+
       uimenu = new
         fltk_uimenu(0, 0, ww, menu_h);
       uimenu->hide ();
 
-      canvas = new
-        OpenGL_fltk (0, 0, ww , hh - status_h, number ());
-
       bottom = new
         Fl_Box (0,
                 hh - status_h,
@@ -861,8 +861,11 @@
 
   void show_canvas (void)
   {
-    canvas->show ();
-    canvas->make_current ();
+    if (fp.is_visible ())
+      {
+        canvas->show ();
+        canvas->make_current ();
+      }
   }
 
   void hide_canvas (void)
@@ -1837,10 +1840,10 @@
                 case figure::properties::ID_MENUBAR:
                   figure_manager::toggle_menubar_visibility (ov.string_value (), fp.menubar_is("figure"));
                   break;
-                case figure::properties::ID_NAME:
                 case figure::properties::ID_CURRENTAXES:
                   figure_manager::update_canvas (go.get_handle (), fp.get_currentaxes ());
                   break;
+                case figure::properties::ID_NAME:
                 case figure::properties::ID_NUMBERTITLE:
                   figure_manager::set_name (ov.string_value ());
                   break;
--- a/src/DLD-FUNCTIONS/__lin_interpn__.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/DLD-FUNCTIONS/__lin_interpn__.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -355,3 +355,10 @@
 
   return retval;
 }
+
+/*
+
+## No test needed for internal helper function.
+%!assert (1)
+
+*/
--- a/src/DLD-FUNCTIONS/__magick_read__.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/DLD-FUNCTIONS/__magick_read__.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -531,6 +531,13 @@
   return output;
 }
 
+/*
+
+## No test needed for internal helper function.
+%!assert (1)
+
+*/
+
 #ifdef HAVE_MAGICK
 
 static void
@@ -916,6 +923,13 @@
 return retval;
 }
 
+/*
+
+## No test needed for internal helper function.
+%!assert (1)
+
+*/
+
 #ifdef HAVE_MAGICK
 
 template<class T>
@@ -1134,6 +1148,13 @@
   return retval;
 }
 
+/*
+
+## No test needed for internal helper function.
+%!assert (1)
+
+*/
+
 #undef GET_PARAM
 
 // Determine the file formats supported by GraphicsMagick.  This is
@@ -1193,3 +1214,10 @@
 
   return retval;
 }
+
+/*
+
+## No test needed for internal helper function.
+%!assert (1)
+
+*/
--- a/src/DLD-FUNCTIONS/__pchip_deriv__.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/DLD-FUNCTIONS/__pchip_deriv__.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -147,3 +147,10 @@
 
   return retval;
 }
+
+/*
+
+## No test needed for internal helper function.
+%!assert (1)
+
+*/
--- a/src/DLD-FUNCTIONS/__qp__.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/DLD-FUNCTIONS/__qp__.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -528,3 +528,10 @@
 
   return retval;
 }
+
+/*
+
+## No test needed for internal helper function.
+%!assert (1)
+
+*/
--- a/src/DLD-FUNCTIONS/__voronoi__.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/DLD-FUNCTIONS/__voronoi__.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -248,3 +248,10 @@
 
   return retval;
 }
+
+/*
+
+## No test needed for internal helper function.
+%!assert (1)
+
+*/
--- a/src/DLD-FUNCTIONS/bsxfun.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/DLD-FUNCTIONS/bsxfun.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -312,15 +312,18 @@
 DEFUN_DLD (bsxfun, args, ,
   "-*- texinfo -*-\n\
 @deftypefn {Loadable Function} {} bsxfun (@var{f}, @var{A}, @var{B})\n\
-Apply a binary function @var{f} element-by-element to two matrix arguments\n\
-@var{A} and @var{B}.  @var{f} is a function handle, inline function, or\n\
-string containing the name of the function to evaluate.\n\
-The function @var{f} must be capable of accepting two column-vector\n\
-arguments of equal length, or one column vector argument and a scalar.\n\
+The binary singleton expansion function applier does what its name\n\
+suggests: applies a binary function @var{f} element-by-element to two\n\
+array arguments @var{A} and @var{B}, and expands as necessary\n\
+singleton dimensions in either input argument. @var{f} is a function\n\
+handle, inline function, or string containing the name of the function\n\
+to evaluate. The function @var{f} must be capable of accepting two\n\
+column-vector arguments of equal length, or one column vector argument\n\
+and a scalar.\n\
 \n\
-The dimensions of @var{A} and @var{B} must be equal or singleton.  The\n\
-singleton dimensions of the matrices will be expanded to the same\n\
-dimensionality as the other matrix.\n\
+The dimensions of @var{A} and @var{B} must be equal or singleton. The\n\
+singleton dimensions of the arrays will be expanded to the same\n\
+dimensionality as the other array.\n\
 @seealso{arrayfun, cellfun}\n\
 @end deftypefn")
 {
@@ -766,4 +769,45 @@
 %!assert (bsxfun (@max, a, b), max (aa, bb));
 %!assert (bsxfun (@and, a > 0, b > 0), (aa > 0) & (bb > 0));
 %!assert (bsxfun (@or, a > 0, b > 0), (aa > 0) | (bb > 0));
+
+%% Test automatic bsxfun
+%
+%!test
+%! funs = {@plus, @minus, @times, @rdivide, @ldivide, @power, @max, @min, \
+%!         @rem, @mod, @atan2, @hypot, @eq, @ne, @lt, @le, @gt, @ge, \
+%!         @and, @or, @xor };
+%!
+%! float_types = {@single, @double};
+%! int_types = {@int8, @int16, @int32, @int64, \
+%!             @uint8, @uint16, @uint32, @uint64};
+%!
+%! x = rand (3)*10-5;
+%! y = rand (3,1)*10-5;
+%!
+%! for i=1:length (funs)
+%!   for j = 1:length(float_types)
+%!     for k = 1:length(int_types)
+%!
+%!       fun = funs{i};
+%!       f_type = float_types{j};
+%!       i_type = int_types{k};
+%!
+%!         assert (bsxfun (fun, f_type (x), i_type (y)), \
+%!                 fun (f_type(x), i_type (y)));
+%!         assert (bsxfun (fun, f_type (y), i_type (x)), \
+%!                 fun (f_type(y), i_type (x)));
+%!
+%!         assert (bsxfun (fun, i_type (x), i_type (y)), \
+%!                 fun (i_type (x), i_type (y)));
+%!         assert (bsxfun (fun, i_type (y), i_type (x)), \
+%!                 fun (i_type (y), i_type (x)));
+%!
+%!         assert (bsxfun (fun, f_type (x), f_type (y)), \
+%!                 fun (f_type (x), f_type (y)));
+%!         assert (bsxfun (fun, f_type(y), f_type(x)), \
+%!                 fun (f_type (y), f_type (x)));
+%!     endfor
+%!   endfor
+%! endfor
+%!
 */
--- a/src/DLD-FUNCTIONS/cellfun.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/DLD-FUNCTIONS/cellfun.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -58,6 +58,8 @@
 #include "ov-uint32.h"
 #include "ov-uint64.h"
 
+#include "ov-fcn-handle.h"
+
 static octave_value_list
 get_output_list (octave_idx_type count, octave_idx_type nargout,
                  const octave_value_list& inputlist,
@@ -122,8 +124,10 @@
 @item ndims\n\
 Return the number of dimensions of each element.\n\
 \n\
-@item prodofsize\n\
-Return the product of dimensions of each element.\n\
+@item numel\n\
+@itemx prodofsize\n\
+Return the number of elements contained within each cell element.  The\n\
+number is the product of the dimensions of the object at each cell element.\n\
 \n\
 @item size\n\
 Return the size along the @var{k}-th dimension.\n\
@@ -142,7 +146,7 @@
 \n\
 @example\n\
 @group\n\
-cellfun (@@atan2, @{1, 0@}, @{0, 1@})\n\
+cellfun (\"atan2\", @{1, 0@}, @{0, 1@})\n\
      @result{}ans = [1.57080   0.00000]\n\
 @end group\n\
 @end example\n\
@@ -177,7 +181,7 @@
 \n\
 @example\n\
 @group\n\
-cellfun (\"tolower(x)\", @{\"Foo\", \"Bar\", \"FooBar\"@},\n\
+cellfun (\"tolower\", @{\"Foo\", \"Bar\", \"FooBar\"@},\n\
          \"UniformOutput\",false)\n\
 @result{} ans = @{\"foo\", \"bar\", \"foobar\"@}\n\
 @end group\n\
@@ -200,7 +204,7 @@
 @example\n\
 @group\n\
 function y = foo (s, x), y = NaN; endfunction\n\
-cellfun (@@factorial, @{-1,2@},'ErrorHandler',@@foo)\n\
+cellfun (\"factorial\", @{-1,2@}, 'ErrorHandler', @@foo)\n\
 @result{} ans = [NaN 2]\n\
 @end group\n\
 @end example\n\
@@ -220,6 +224,7 @@
     }
 
   octave_value func = args(0);
+  bool symbol_table_lookup = false;
 
   if (! args(1).is_cell ())
     {
@@ -337,6 +342,8 @@
               func = symbol_table::find_function (name);
               if (func.is_undefined ())
                 error ("cellfun: invalid function NAME: %s", name.c_str ());
+
+              symbol_table_lookup = true;
             }
         }
     }
@@ -347,6 +354,30 @@
   if (func.is_function_handle () || func.is_inline_function ()
       || func.is_function ())
     {
+
+      // The following is an optimisation because the symbol table can
+      // give a more specific function class, so this can result in
+      // fewer polymorphic function calls as the function gets called
+      // for each value of the array.
+      if (! symbol_table_lookup )
+        {
+          if (func.is_function_handle ())
+            {
+              octave_fcn_handle* f = func.fcn_handle_value ();
+
+              // Overloaded function handles need to check the type of
+              // the arguments for each element of the array, so they
+              // cannot be optimised this way.
+              if (f -> is_overloaded ())
+                goto nevermind;
+            }
+          octave_value f = symbol_table::find_function (func.function_value ()
+                                                         -> name ());
+          if (f.is_defined ())
+            func = f;
+        }
+      nevermind:
+
       unwind_protect frame;
       frame.protect_var (buffer_error_messages);
 
--- a/src/DLD-FUNCTIONS/chol.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/DLD-FUNCTIONS/chol.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -493,9 +493,6 @@
 %!testif HAVE_CHOLMOD
 %! Ainv3 = cholinv(sparse(A));
 %! assert (norm(Ainv-Ainv3),0,1e-10)
-%!testif HAVE_CHOLMOD
-%! Ainv4 = spcholinv(sparse(A));
-%! assert (norm(Ainv-Ainv4),0,1e-10)
 
 */
 
--- a/src/DLD-FUNCTIONS/config-module.awk	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/DLD-FUNCTIONS/config-module.awk	Tue Sep 20 15:38:24 2011 -0400
@@ -1,4 +1,7 @@
 BEGIN {
+  FS = "|";
+  nfiles = 0;
+
   print "## DO NOT EDIT -- generated from module-files by config-module.awk";
   print ""
   print "EXTRA_DIST += \\"
@@ -6,9 +9,14 @@
   print "  DLD-FUNCTIONS/config-module.awk \\"
   print "  DLD-FUNCTIONS/module-files"
   print ""
-  nfiles = 0;
-} {
-  files[++nfiles] = $1;
+}
+/^#.*/ { next; }
+{
+  nfiles++;
+  files[nfiles] = $1;
+  cppflags[nfiles] = $2;
+  ldflags[nfiles] = $3;
+  libraries[nfiles] = $4;
 } END {
   sep = " \\\n";
   print "DLD_FUNCTIONS_SRC = \\";
@@ -22,9 +30,9 @@
   sep = " \\\n";
   print "DLD_FUNCTIONS_LIBS = $(DLD_FUNCTIONS_SRC:.cc=.la)";
   print "";
-  print "octlib_LTLIBRARIES += $(DLD_FUNCTIONS_LIBS)";
+  print "if AMCOND_ENABLE_DYNAMIC_LINKING";
   print "";
-  print "if AMCOND_ENABLE_DYNAMIC_LINKING";
+  print "octlib_LTLIBRARIES += $(DLD_FUNCTIONS_LIBS)";
   print "";
   print "## Use stamp files to avoid problems with checking timestamps";
   print "## of symbolic links";
@@ -41,18 +49,28 @@
     print "\t  touch $(@F)";
     print "";
   }
+  print "else";
+  print "";
+  print "noinst_LTLIBRARIES = $(DLD_FUNCTIONS_LIBS)";
+  print "";
   print "endif";
-  print "";
 
   for (i = 1; i <= nfiles; i++) {
     basename = files[i];
     sub (/\.cc$/, "", basename);
+    print "";
     printf ("DLD_FUNCTIONS_%s_la_SOURCES = DLD-FUNCTIONS/%s\n",
 	    basename, files[i]);
-    printf ("DLD_FUNCTIONS_%s_la_LDFLAGS = @NO_UNDEFINED_LDFLAG@ -module\n",
-	    basename);
-    printf ("DLD_FUNCTIONS_%s_la_LIBADD = $(OCT_LINK_DEPS)\n", basename);
+    if (cppflags[i])
+      {
+        printf ("DLD-FUNCTIONS/%s.df: CPPFLAGS += %s\n",
+                basename, cppflags[i]);
+        printf ("DLD_FUNCTIONS_%s_la_CPPFLAGS = $(AM_CPPFLAGS) %s\n",
+                basename, cppflags[i]);
+      }
+    printf ("DLD_FUNCTIONS_%s_la_LDFLAGS = -avoid-version -module $(NO_UNDEFINED_LDFLAG) %s $(OCT_LINK_OPTS)\n",
+            basename, ldflags[i]);
+    printf ("DLD_FUNCTIONS_%s_la_LIBADD = liboctinterp.la ../liboctave/liboctave.la ../libcruft/libcruft.la %s $(OCT_LINK_DEPS)\n",
+            basename, libraries[i]);
   }
-  print "";
-
 }
--- a/src/DLD-FUNCTIONS/dot.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/DLD-FUNCTIONS/dot.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -238,6 +238,17 @@
 
 /*
 
+%! assert(dot ([1, 2], [2, 3]), 11);
+
+%!test
+%! x = [2, 1; 2, 1];
+%! y = [-0.5, 2; 0.5, -2];
+%! assert(dot (x, y), [0 0]);
+
+%!test
+%! x = [ 1+i, 3-i; 1-i, 3-i];
+%! assert(dot (x, x), [4, 20]);
+
 */
 
 DEFUN_DLD (blkmm, args, ,
@@ -344,3 +355,14 @@
 
   return retval;
 }
+
+/*
+
+%!test
+%! x(:,:,1) = [1 2; 3 4];
+%! x(:,:,2) = [1 1; 1 1];
+%! z(:,:,1) = [7 10; 15 22];
+%! z(:,:,2) = [2 2; 2 2];
+%! assert(blkmm (x,x),z);
+
+*/
--- a/src/DLD-FUNCTIONS/eigs.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/DLD-FUNCTIONS/eigs.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -323,6 +323,7 @@
   bool a_is_complex = false;
   bool b_is_complex = false;
   bool symmetric = false;
+  bool sym_tested = false;
   bool cholB = false;
   bool a_is_sparse = false;
   ColumnVector permB;
@@ -399,7 +400,8 @@
           else
             acm = (args(0).complex_matrix_value());
           a_is_complex = true;
-          symmetric = false; // ARAPACK doesn't special case complex symmetric
+          symmetric = false; // ARPACK doesn't special case complex symmetric
+          sym_tested = true;
         }
       else
         {
@@ -407,19 +409,17 @@
             {
               asmm = (args(0).sparse_matrix_value());
               a_is_sparse = true;
-              symmetric = asmm.is_symmetric();
             }
           else
             {
               amm = (args(0).matrix_value());
-              symmetric = amm.is_symmetric();
             }
         }
 
     }
 
   // Note hold off reading B till later to avoid issues of double
-  // copies of the matrix if B is full/real while A is complex..
+  // copies of the matrix if B is full/real while A is complex.
   if (!error_state && nargin > 1 + arg_offset &&
       !(args(1 + arg_offset).is_real_scalar ()))
     {
@@ -481,10 +481,13 @@
             {
               octave_value tmp;
 
-              // issym is ignored if A is not a function
+              // issym is ignored for complex matrix inputs
               tmp = map.getfield ("issym");
-              if (tmp.is_defined () && have_a_fun)
-                symmetric = tmp.double_value () != 0.;
+              if (tmp.is_defined () && !sym_tested)
+                {
+                  symmetric = tmp.double_value () != 0.;
+                  sym_tested = true;
+                }
 
               // isreal is ignored if A is not a function
               tmp = map.getfield ("isreal");
@@ -543,6 +546,15 @@
       return retval;
     }
 
+  // Test undeclared (no issym) matrix inputs for symmetry
+  if (!sym_tested && !have_a_fun)
+    {
+      if (a_is_sparse)
+        symmetric = asmm.is_symmetric();
+      else
+        symmetric = amm.is_symmetric();
+    }
+
   if (have_b)
     {
       if (a_is_complex || b_is_complex)
--- a/src/DLD-FUNCTIONS/filter.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/DLD-FUNCTIONS/filter.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -104,16 +104,17 @@
       return y;
     }
 
-  octave_idx_type si_dim = 0;
-  for (octave_idx_type i = 0; i < x_dims.length (); i++)
+  for (octave_idx_type i = 1; i < dim; i++)
     {
-      if (i == dim)
-        continue;
-
-      if (x_dims(i) == 1)
-        continue;
-
-      if (si_dims(++si_dim) != x_dims(i))
+      if (si_dims(i) != x_dims(i-1))
+        {
+          error ("filter: dimensionality of SI and X must agree");
+          return y;
+        }
+    }
+  for (octave_idx_type i = dim+1; i < x_dims.length (); i++)
+    {
+      if (si_dims(i) != x_dims(i))
         {
           error ("filter: dimensionality of SI and X must agree");
           return y;
@@ -456,19 +457,10 @@
                 }
               else
                 {
-                  dim_vector si_dims = args (3).dims ();
-                  bool si_is_vector = true;
-                  for (int i = 0; i < si_dims.length (); i++)
-                    if (si_dims(i) != 1 && si_dims(i) < si_dims.numel ())
-                      {
-                        si_is_vector = false;
-                        break;
-                      }
-
                   si = args(3).float_complex_array_value ();
 
-                  if (si_is_vector)
-                    si = si.reshape (dim_vector (1, si.numel ()));
+                  if (si.is_vector () && x.is_vector ())
+                    si = si.reshape (dim_vector (si.numel (), 1));
                 }
 
               if (! error_state)
@@ -513,19 +505,10 @@
                 }
               else
                 {
-                  dim_vector si_dims = args (3).dims ();
-                  bool si_is_vector = true;
-                  for (int i = 0; i < si_dims.length (); i++)
-                    if (si_dims(i) != 1 && si_dims(i) < si_dims.numel ())
-                      {
-                        si_is_vector = false;
-                        break;
-                      }
-
                   si = args(3).complex_array_value ();
 
-                  if (si_is_vector)
-                    si = si.reshape (dim_vector (1, si.numel ()));
+                  if (si.is_vector () && x.is_vector ())
+                    si = si.reshape (dim_vector (si.numel (), 1));
                 }
 
               if (! error_state)
@@ -573,19 +556,10 @@
                 }
               else
                 {
-                  dim_vector si_dims = args (3).dims ();
-                  bool si_is_vector = true;
-                  for (int i = 0; i < si_dims.length (); i++)
-                    if (si_dims(i) != 1 && si_dims(i) < si_dims.numel ())
-                      {
-                        si_is_vector = false;
-                        break;
-                      }
-
                   si = args(3).float_array_value ();
 
-                  if (si_is_vector)
-                    si = si.reshape (dim_vector (1, si.numel ()));
+                  if (si.is_vector () && x.is_vector ())
+                    si = si.reshape (dim_vector (si.numel (), 1));
                 }
 
               if (! error_state)
@@ -630,19 +604,10 @@
                 }
               else
                 {
-                  dim_vector si_dims = args (3).dims ();
-                  bool si_is_vector = true;
-                  for (int i = 0; i < si_dims.length (); i++)
-                    if (si_dims(i) != 1 && si_dims(i) < si_dims.numel ())
-                      {
-                        si_is_vector = false;
-                        break;
-                      }
-
                   si = args(3).array_value ();
 
-                  if (si_is_vector)
-                    si = si.reshape (dim_vector (1, si.numel ()));
+                  if (si.is_vector () && x.is_vector ())
+                    si = si.reshape (dim_vector (si.numel (), 1));
                 }
 
               if (! error_state)
@@ -749,8 +714,20 @@
 %!
 %!assert(filter (1, ones(10,1)/10, []), []);
 %!assert(filter (1, ones(10,1)/10, zeros(0,10)), zeros(0,10));
+%!assert(filter (1, ones(10,1)/10, single (1:5)), repmat (single (10), 1, 5));
+%% Test using initial conditions
+%!assert(filter([1, 1, 1], [1, 1], [1 2], [1, 1]), [2 2]);
+%!assert(filter([1, 1, 1], [1, 1], [1 2], [1, 1]'), [2 2]);
 %!assert(filter([1, 3], [1], [1 2; 3 4; 5 6], [4, 5]), [5 7; 6 10; 14 18]);
-%!assert(filter (1, ones(10,1)/10, single (1:5)), repmat (single (10), 1, 5));
-%%  Should put some tests of the "DIM" parameter in here.
+%!error (filter([1, 3], [1], [1 2; 3 4; 5 6], [4, 5]'));
+%!assert(filter([1, 3, 2], [1], [1 2; 3 4; 5 6], [1 0 0; 1 0 0], 2), [2 6; 3 13; 5 21]);
+%% Test of DIM parameter
+%!test
+%! x = ones (2, 1, 3, 4);
+%! x(1,1,:,:) = [1 2 3 4; 5 6 7 8; 9 10 11 12];
+%! y0 = [1 1 6 2 15 3 2 1 8 2 18 3 3 1 10 2 21 3 4 1 12 2 24 3];
+%! y0 = reshape (y0, size (x));
+%! y = filter([1 1 1], 1, x, [], 3);
+%! assert (y, y0);
 
 */
--- a/src/DLD-FUNCTIONS/givens.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/DLD-FUNCTIONS/givens.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -203,3 +203,13 @@
 
   return retval;
 }
+
+/*
+
+%!assert (givens (1,1), [1, 1; -1, 1]/sqrt(2), 2*eps);
+%!assert (givens (1,0), eye(2));
+%!assert (givens (0,1), [0, 1; -1 0]);
+%!error givens(1);
+%!error givens()
+
+*/
--- a/src/DLD-FUNCTIONS/kron.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/DLD-FUNCTIONS/kron.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -264,3 +264,15 @@
 
   return retval;
 }
+
+/*
+
+%!test
+%! x = ones(2);
+%! assert( kron (x, x), ones (4));
+
+%!test
+%! z =  [1,  2,  3,  4; 1,  2,  3,  4; 1,  2,  3,  4];
+%! assert( kron (1:4, ones (3, 1)), z)
+
+*/
--- a/src/DLD-FUNCTIONS/luinc.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/DLD-FUNCTIONS/luinc.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -110,7 +110,7 @@
       bool udiag = false;
       Matrix thresh;
       double droptol = -1.;
-      bool vecout;
+      bool vecout = false;
 
       if (args(1).is_string ())
         {
@@ -236,7 +236,7 @@
                             if (vecout)
                               retval(2) = fact.Pr_vec ();
                             else
-                              retval(2) = fact.Pr ();
+                              retval(2) = fact.Pr_mat ();
                             retval(1) = octave_value (fact.U (),
                                                       MatrixType (MatrixType::Upper));
                             retval(0) = octave_value (fact.L (),
@@ -260,8 +260,8 @@
                               }
                             else
                               {
-                                retval(3) = fact.Pc ();
-                                retval(2) = fact.Pr ();
+                                retval(3) = fact.Pc_mat ();
+                                retval(2) = fact.Pr_mat ();
                               }
                             retval(1) = octave_value (fact.U (),
                                                       MatrixType (MatrixType::Upper));
@@ -319,7 +319,7 @@
                             if (vecout)
                               retval(2) = fact.Pr_vec ();
                             else
-                              retval(2) = fact.Pr ();
+                              retval(2) = fact.Pr_mat ();
                             retval(1) = octave_value (fact.U (),
                                                       MatrixType (MatrixType::Upper));
                             retval(0) = octave_value (fact.L (),
@@ -343,8 +343,8 @@
                               }
                             else
                               {
-                                retval(3) = fact.Pc ();
-                                retval(2) = fact.Pr ();
+                                retval(3) = fact.Pc_mat ();
+                                retval(2) = fact.Pr_mat ();
                               }
                             retval(1) = octave_value (fact.U (),
                                                       MatrixType (MatrixType::Upper));
--- a/src/DLD-FUNCTIONS/mgorth.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/DLD-FUNCTIONS/mgorth.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -31,8 +31,8 @@
 #include "gripes.h"
 
 template <class ColumnVector, class Matrix, class RowVector>
-static void 
-do_mgorth (ColumnVector& x, const Matrix& V, RowVector& h) 
+static void
+do_mgorth (ColumnVector& x, const Matrix& V, RowVector& h)
 {
   octave_idx_type Vc = V.columns ();
   h = RowVector (Vc + 1);
@@ -71,7 +71,7 @@
 
   if (nargin != 2 || nargout > 2)
   {
-    print_usage (); 
+    print_usage ();
     return retval;
   }
 
@@ -90,7 +90,7 @@
     {
       error ("mgorth: X and V must be numeric");
     }
- 
+
   bool iscomplex = (arg_x.is_complex_type () || arg_v.is_complex_type ());
   if (arg_x.is_single_type () || arg_v.is_single_type ())
     {
@@ -139,7 +139,7 @@
 }
 
 /*
-  
+
 %!test
 %! for ii=1:100; assert (abs (mgorth (randn (5, 1), eye (5, 4))), [0 0 0 0 1]', eps); endfor
 
--- a/src/DLD-FUNCTIONS/module-files	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/DLD-FUNCTIONS/module-files	Tue Sep 20 15:38:24 2011 -0400
@@ -1,40 +1,41 @@
+# FILE|CPPFLAGS|LDFLAGS|LIBRARIES
 __contourc__.cc
-__delaunayn__.cc
+__delaunayn__.cc|$(QHULL_CPPFLAGS)|$(QHULL_LDFLAGS)|$(QHULL_LIBS)
 __dispatch__.cc
 __dsearchn__.cc
-__fltk_uigetfile__.cc
-__glpk__.cc
-__init_fltk__.cc
+__fltk_uigetfile__.cc|$(GRAPHICS_CFLAGS) $(FT2_CPPFLAGS)|$(GRAPHICS_LDFLAGS) $(FT2_LDFLAGS)|$(GRAPHICS_LIBS) $(FT2_LIBS)
+__glpk__.cc|$(GLPK_CPPFLAGS)|$(GLPK_LDFLAGS)|$(GLPK_LIBS)
+__init_fltk__.cc|$(GRAPHICS_CFLAGS) $(FT2_CPPFLAGS)|$(GRAPHICS_LDFLAGS) $(FT2_LDFLAGS)|$(GRAPHICS_LIBS) $(FT2_LIBS)
 __lin_interpn__.cc
-__magick_read__.cc
+__magick_read__.cc|$(MAGICK_CPPFLAGS)|$(MAGICK_LDFLAGS)|$(MAGICK_LIBS)
 __pchip_deriv__.cc
 __qp__.cc
-__voronoi__.cc
-amd.cc
+__voronoi__.cc|$(QHULL_CPPFLAGS)|$(QHULL_LDFLAGS)|$(QHULL_LIBS)
+amd.cc|$(SPARSE_XCPPFLAGS)|$(SPARSE_XLDFLAGS)|$(SPARSE_XLIBS)
 balance.cc
 besselj.cc
 betainc.cc
 bsxfun.cc
-ccolamd.cc
+ccolamd.cc|$(SPARSE_XCPPFLAGS)|$(SPARSE_XLDFLAGS)|$(SPARSE_XLIBS)
 cellfun.cc
-chol.cc
-colamd.cc
+chol.cc|$(QRUPDATE_CPPFLAGS) $(SPARSE_XCPPFLAGS)|$(QRUPDATE_LDFLAGS) $(SPARSE_XLDFLAGS)|$(QRUPDATE_LIBS) $(SPARSE_XLIBS)
+colamd.cc|$(SPARSE_XCPPFLAGS)|$(SPARSE_XLDFLAGS)|$(SPARSE_XLIBS)
 colloc.cc
 conv2.cc
-convhulln.cc
+convhulln.cc|$(QHULL_CPPFLAGS)|$(QHULL_LDFLAGS)|$(QHULL_LIBS)
 daspk.cc
 dasrt.cc
 dassl.cc
 det.cc
 dlmread.cc
-dmperm.cc
+dmperm.cc|$(SPARSE_XCPPFLAGS)|$(SPARSE_XLDFLAGS)|$(SPARSE_XLIBS)
 dot.cc
 eig.cc
-eigs.cc
-fft.cc
-fft2.cc
-fftn.cc
-fftw.cc
+eigs.cc|$(SPARSE_XCPPFLAGS)|$(SPARSE_XLDFLAGS)|$(SPARSE_XLIBS) $(LAPACK_LIBS) $(BLAS_LIBS)
+fft.cc|$(FFTW_XCPPFLAGS)|$(FFTW_XLDFLAGS)|$(FFTW_XLIBS)
+fft2.cc|$(FFTW_XCPPFLAGS)|$(FFTW_XLDFLAGS)|$(FFTW_XLIBS)
+fftn.cc|$(FFTW_XCPPFLAGS)|$(FFTW_XLDFLAGS)|$(FFTW_XLIBS)
+fftw.cc|$(FFTW_XCPPFLAGS)|$(FFTW_XLDFLAGS)|$(FFTW_XLIBS)
 filter.cc
 find.cc
 gammainc.cc
@@ -58,13 +59,13 @@
 nproc.cc
 onCleanup.cc
 pinv.cc
-qr.cc
+qr.cc|$(QRUPDATE_CPPFLAGS) $(SPARSE_XCPPFLAGS)|$(QRUPDATE_LDFLAGS) $(SPARSE_XLDFLAGS)|$(QRUPDATE_LIBS) $(SPARSE_XLIBS)
 quad.cc
 quadcc.cc
-qz.cc
+qz.cc|||$(LAPACK_LIBS) $(BLAS_LIBS)
 rand.cc
 rcond.cc
-regexp.cc
+regexp.cc|$(REGEX_CPPFLAGS)|$(REGEX_LDFLAGS)|$(REGEX_LIBS)
 schur.cc
 spparms.cc
 sqrtm.cc
@@ -73,10 +74,10 @@
 sub2ind.cc
 svd.cc
 syl.cc
-symbfact.cc
-symrcm.cc
+symbfact.cc|$(SPARSE_XCPPFLAGS)|$(SPARSE_XLDFLAGS)|$(SPARSE_XLIBS)
+symrcm.cc|$(SPARSE_XCPPFLAGS)|$(SPARSE_XLDFLAGS)|$(SPARSE_XLIBS)
 time.cc
 tril.cc
 tsearch.cc
 typecast.cc
-urlwrite.cc
+urlwrite.cc|$(CURL_CPPFLAGS)|$(CURL_LDFLAGS)|$(CURL_LIBS)
--- a/src/DLD-FUNCTIONS/onCleanup.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/DLD-FUNCTIONS/onCleanup.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -274,3 +274,19 @@
 
   return retval;
 }
+
+/*
+
+%!test
+%! old_wstate = warning ("query");
+%! unwind_protect
+%!   trigger = onCleanup (@() warning ("on", "__MY_WARNING__"));
+%!   warning ("off", "__MY_WARNING__");
+%!   assert ((warning ("query", "__MY_WARNING__")).state, "off");
+%!   clear trigger
+%!   assert ((warning ("query", "__MY_WARNING__")).state, "on");
+%! unwind_protect_cleanup
+%!   warning (old_wstate);
+%! end_unwind_protect
+
+*/
--- a/src/DLD-FUNCTIONS/pinv.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/DLD-FUNCTIONS/pinv.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -169,3 +169,23 @@
 
   return retval;
 }
+
+/*
+%!shared a, b, tol, hitol, d, u, x, y
+%! a = reshape (rand*[1:16], 4, 4);   ## Rank 2 matrix
+%! b = pinv (a);
+%! tol = 1e-14;
+%! hitol = 15*sqrt(eps);
+%! d = diag ([rand, rand, hitol, hitol]);
+%! u = rand (4);                      ## Could be singular by freak accident
+%! x = inv (u)*d*u;
+%! y = pinv (x, sqrt(eps));
+%!assert(a*b*a, a, tol);
+%!assert(b*a*b, b, tol);
+%!assert((b*a)', b*a, tol);
+%!assert((a*b)', a*b, tol);
+%!assert(x*y*x, x, -hitol);
+%!assert(y*x*y, y, -hitol);
+%!assert((x*y)', x*y, hitol);
+%!assert((y*x)', y*x, hitol);
+*/
--- a/src/DLD-FUNCTIONS/qr.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/DLD-FUNCTIONS/qr.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -76,6 +76,8 @@
   "-*- texinfo -*-\n\
 @deftypefn  {Loadable Function} {[@var{Q}, @var{R}, @var{P}] =} qr (@var{A})\n\
 @deftypefnx {Loadable Function} {[@var{Q}, @var{R}, @var{P}] =} qr (@var{A}, '0')\n\
+@deftypefnx {Loadable Function} {[@var{C}, @var{R}] =} qr (@var{A}, @var{B})\n\
+@deftypefnx {Loadable Function} {[@var{C}, @var{R}] =} qr (@var{A}, @var{B}, '0')\n\
 @cindex QR factorization\n\
 Compute the QR@tie{}factorization of @var{A}, using standard @sc{lapack}\n\
 subroutines.  For example, given the matrix @code{@var{A} = [1, 2; 3, 4]},\n\
@@ -188,7 +190,7 @@
 \n\
 @example\n\
 @group\n\
-[@var{C},@var{R}] = spqr (@var{A},@var{B})\n\
+[@var{C}, @var{R}] = qr (@var{A}, @var{B})\n\
 x = @var{R} \\ @var{C}\n\
 @end group\n\
 @end example\n\
--- a/src/DLD-FUNCTIONS/quadcc.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/DLD-FUNCTIONS/quadcc.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -50,8 +50,7 @@
   int depth, rdepth, ndiv;
 } cquad_ival;
 
-/* Some constants and matrices that we'll need.
-    */
+/* Some constants and matrices that we'll need.  */
 
 static const double xi[33] = {
   -1., -0.99518472667219688624, -0.98078528040323044912,
@@ -1473,9 +1472,7 @@
 }
 
 
-
-/* The actual integration routine.
-    */
+/* The actual integration routine.  */
 
 DEFUN_DLD (quadcc, args, nargout,
 "-*- texinfo -*-\n\
@@ -1545,6 +1542,7 @@
 @seealso{quad, quadv, quadl, quadgk, trapz, dblquad, triplequad}\n\
 @end deftypefn")
 {
+  octave_value_list retval;
 
   /* Some constants that we will need. */
   static const int n[4] = { 4, 8, 16, 32 };
@@ -1563,11 +1561,11 @@
   double a, b, tol, iivals[cquad_heapsize], *sing;
 
   /* Variables needed for transforming the integrand. */
-  int wrap = 0;
+  bool wrap = false;
   double xw;
 
   /* Stuff we will need to call the integrand. */
-  octave_value_list fargs, retval;
+  octave_value_list fargs, fvals;
 
   /* Actual variables (as opposed to constants above). */
   double m, h, ml, hl, mr, hr, temp;
@@ -1580,48 +1578,49 @@
 
 
   /* Parse the input arguments. */
-  if (nargin < 1)
+  if (nargin < 3)
     {
-      error
-        ("quadcc: first argument (integrand) of type function handle required");
-      return octave_value_list ();
+      print_usage ();
+      return retval;
     }
+
+  if (args(0).is_function_handle () || args(0).is_inline_function ())
+    fcn = args(0).function_value ();
   else
     {
-      if (args (0).is_function_handle () || args (0).is_inline_function ())
-        fcn = args (0).function_value ();
-      else
-        {
-          error ("quadcc: first argument (integrand) must be a function handle or an inline function");
-          return octave_value_list();
-        }
+       std::string fcn_name = unique_symbol_name ("__quadcc_fcn_");
+       std::string fname = "function y = ";
+       fname.append (fcn_name);
+       fname.append ("(x) y = ");
+       fcn = extract_function (args(0), "quadcc", fcn_name, fname,
+                               "; endfunction");
     }
 
-  if (nargin < 2 || !args (1).is_real_scalar ())
+  if (!args(1).is_real_scalar ())
     {
-      error ("quadcc: second argument (left interval edge) must be a single real scalar");
-      return octave_value_list ();
+      error ("quadcc: lower limit of integration (A) must be a single real scalar");
+      return retval;
     }
   else
-    a = args (1).double_value ();
+    a = args(1).double_value ();
 
-  if (nargin < 3 || !args (2).is_real_scalar ())
+  if (!args(2).is_real_scalar ())
     {
-      error ("quadcc: third argument (right interval edge) must be a single real scalar");
-      return octave_value_list ();
+      error ("quadcc: upper limit of integration (B) must be a single real scalar");
+      return retval;
     }
   else
-    b = args (2).double_value ();
+    b = args(2).double_value ();
 
-  if (nargin < 4)
+  if (nargin < 4 || args(3).is_empty ())
     tol = 1.0e-6;
-  else if (!args (3).is_real_scalar ())
+  else if (!args(3).is_real_scalar () || args(3).double_value () <= 0)
     {
-      error ("quadcc: fourth argument (tolerance) must be a single real scalar");
-      return octave_value_list ();
+      error ("quadcc: tolerance (TOL) must be a single real scalar > 0");
+      return retval;
     }
   else
-    tol = args (3).double_value ();
+    tol = args(3).double_value ();
 
   if (nargin < 5)
     {
@@ -1629,20 +1628,21 @@
       iivals[0] = a;
       iivals[1] = b;
     }
-  else if (!(args (4).is_real_scalar () || args (4).is_real_matrix ()))
+  else if (!(args(4).is_real_scalar () || args(4).is_real_matrix ()))
     {
-      error ("quadcc: fifth argument (singularities) must be a vector of real values");
-      return octave_value_list ();
+      error ("quadcc: list of singularities (SING) must be a vector of real values");
+      return retval;
     }
   else
     {
-      nivals = 1 + args (4).length ();
-      if ( nivals > cquad_heapsize ) {
-        error ("quadcc: maximum number of singular points is limited to %i",
-               cquad_heapsize-1);
-        return octave_value_list();
+      nivals = 1 + args(4).length ();
+      if (nivals > cquad_heapsize)
+        {
+          error ("quadcc: maximum number of singular points is limited to %i",
+                 cquad_heapsize-1);
+          return retval;
         }
-      sing = args (4).array_value ().fortran_vec ();
+      sing = args(4).array_value ().fortran_vec ();
       iivals[0] = a;
       for (i = 0; i < nivals - 2; i++)
         iivals[i + 1] = sing[i];
@@ -1652,7 +1652,7 @@
   /* If a or b are +/-Inf, transform the integral. */
   if (xisinf (a) || xisinf (b))
     {
-      wrap = 1;
+      wrap = true;
       for (i = 0; i <= nivals; i++)
         if (xisinf (iivals[i]))
           iivals[i] = copysign (1.0, iivals[i]);
@@ -1688,19 +1688,18 @@
           for (i = 0; i <= n[3]; i++)
             ex (i) = m + xi[i] * h;
         }
-      fargs (0) = ex;
-      retval = feval (fcn, fargs, 1);
-      if (retval.length () != 1 || !retval (0).is_real_matrix ())
+      fargs(0) = ex;
+      fvals = feval (fcn, fargs, 1);
+      if (fvals.length () != 1 || !fvals(0).is_real_matrix ())
         {
-          error
-            ("quadcc: integrand must return a single, real-valued vector");
-          return octave_value_list ();
+          error ("quadcc: integrand F must return a single, real-valued vector");
+          return retval;
         }
-      Matrix effex = retval (0).matrix_value ();
+      Matrix effex = fvals(0).matrix_value ();
       if (effex.length () != ex.length ())
         {
-          error ("quadcc: integrand must return a single, real-valued vector of the same size as the input");
-          return octave_value_list ();
+          error ("quadcc: integrand F must return a single, real-valued vector of the same size as the input");
+          return retval;
         }
       for (i = 0; i <= n[3]; i++)
         {
@@ -1809,18 +1808,18 @@
                 for (i = 0; i < n[d] / 2; i++)
                   ex (i) = m + xi[(2 * i + 1) * skip[d]] * h;
               }
-            fargs (0) = ex;
-            retval = feval (fcn, fargs, 1);
-            if (retval.length () != 1 || !retval (0).is_real_matrix ())
+            fargs(0) = ex;
+            fvals = feval (fcn, fargs, 1);
+            if (fvals.length () != 1 || !fvals(0).is_real_matrix ())
               {
-                error ("quadcc: integrand must return a single, real-valued vector");
-                return octave_value_list ();
+                error ("quadcc: integrand F must return a single, real-valued vector");
+                return retval;
               }
-            Matrix effex = retval (0).matrix_value ();
+            Matrix effex = fvals(0).matrix_value ();
             if (effex.length () != ex.length ())
               {
-                error ("quadcc: integrand must return a single, real-valued vector of the same size as the input");
-                return octave_value_list ();
+                error ("quadcc: integrand F must return a single, real-valued vector of the same size as the input");
+                return retval;
               }
             neval += effex.length ();
             for (i = 0; i < n[d] / 2; i++)
@@ -1957,18 +1956,18 @@
                 for (i = 0; i < n[0] - 1; i++)
                   ex (i) = ml + xi[(i + 1) * skip[0]] * hl;
               }
-            fargs (0) = ex;
-            retval = feval (fcn, fargs, 1);
-            if (retval.length () != 1 || !retval (0).is_real_matrix ())
+            fargs(0) = ex;
+            fvals = feval (fcn, fargs, 1);
+            if (fvals.length () != 1 || !fvals(0).is_real_matrix ())
               {
-                error ("quadcc: integrand must return a single, real-valued vector");
-                return octave_value_list ();
+                error ("quadcc: integrand F must return a single, real-valued vector");
+                return retval;
               }
-            Matrix effex = retval (0).matrix_value ();
+            Matrix effex = fvals(0).matrix_value ();
             if (effex.length () != ex.length ())
               {
-                error ("quadcc: integrand must return a single, real-valued vector of the same size as the input");
-                return octave_value_list ();
+                error ("quadcc: integrand F must return a single, real-valued vector of the same size as the input");
+                return retval;
               }
             neval += effex.length ();
             for (i = 0; i < n[0] - 1; i++)
@@ -2053,18 +2052,18 @@
                 for (i = 0; i < n[0] - 1; i++)
                   ex (i) = mr + xi[(i + 1) * skip[0]] * hr;
               }
-            fargs (0) = ex;
-            retval = feval (fcn, fargs, 1);
-            if (retval.length () != 1 || !retval (0).is_real_matrix ())
+            fargs(0) = ex;
+            fvals = feval (fcn, fargs, 1);
+            if (fvals.length () != 1 || !fvals(0).is_real_matrix ())
               {
-                error ("quadcc: integrand must return a single, real-valued vector");
-                return octave_value_list ();
+                error ("quadcc: integrand F must return a single, real-valued vector");
+                return retval;
               }
-            Matrix effex = retval (0).matrix_value ();
+            Matrix effex = fvals(0).matrix_value ();
             if (effex.length () != ex.length ())
               {
-                error ("quadcc: integrand must return a single, real-valued vector of the same size as the input");
-                return octave_value_list ();
+                error ("quadcc: integrand F must return a single, real-valued vector of the same size as the input");
+                return retval;
               }
             neval += effex.length ();
             for (i = 0; i < n[0] - 1; i++)
@@ -2234,11 +2233,39 @@
     }
 */
   /* Clean up and present the results. */
-  retval (0) = igral;
+  if (nargout > 2)
+    retval(2) = neval;
   if (nargout > 1)
-    retval (1) = err;
-  if (nargout > 2)
-    retval (2) = neval;
+    retval(1) = err;
+  retval(0) = igral;
   /* All is well that ends well. */
   return retval;
 }
+
+
+/*
+
+%!assert (quadcc(@sin,-pi,pi), 0, 1e-6)
+%!assert (quadcc(inline('sin'),-pi,pi), 0, 1e-6)
+%!assert (quadcc('sin',-pi,pi), 0, 1e-6)
+
+%!assert (quadcc(@sin,-pi,0), -2, 1e-6)
+%!assert (quadcc(@sin,0,pi), 2, 1e-6)
+%!assert (quadcc(@(x) 1./sqrt(x), 0, 1), 2, 1e-6)
+%!assert (quadcc(@(x) 1./(sqrt(x).*(x+1)), 0, Inf), pi, 1e-6)
+
+%!assert (quadcc (@(x) exp(-x .^ 2), -Inf, Inf), sqrt(pi), 1e-6)
+%!assert (quadcc (@(x) exp(-x .^ 2), -Inf, 0), sqrt(pi)/2, 1e-6)
+
+%% Test input validation
+%!error (quadcc ())
+%!error (quadcc (@sin))
+%!error (quadcc (@sin, 0))
+%!error (quadcc (@sin, ones(2), pi))
+%!error (quadcc (@sin, -i, pi))
+%!error (quadcc (@sin, 0, ones(2)))
+%!error (quadcc (@sin, 0, i))
+%!error (quadcc (@sin, 0, pi, 0))
+%!error (quadcc (@sin, 0, pi, 1e-6, [ i ]))
+
+*/
--- a/src/DLD-FUNCTIONS/qz.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/DLD-FUNCTIONS/qz.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -287,6 +287,9 @@
     return (fabs (p) >= 1 ? 1 : -1);
 }
 
+
+//FIXME: Matlab does not produce lambda as the first output argument.
+//       Compatibility problem?
 DEFUN_DLD (qz, args, nargout,
   "-*- texinfo -*-\n\
 @deftypefn  {Loadable Function} {@var{lambda} =} qz (@var{A}, @var{B})\n\
@@ -1236,3 +1239,30 @@
 
   return retval;
 }
+
+/*
+%!shared a, b, c
+%!  a = [1 2; 0 3];
+%!  b = [1 0; 0 0];
+%!  c = [0 1; 0 0];
+%!assert(qz (a,b), 1);
+%!assert(isempty (qz (a,c)));
+
+%% Exaple 7.7.3 in Golub & Van Loan
+%!test
+%! a = [ 10  1  2;
+%!        1  2 -1;
+%!        1  1  2];
+%! b = reshape(1:9,3,3);
+%! [aa, bb, q, z, v, w, lambda] = qz (a, b);
+%! sz = length(lambda);
+%! observed =  (b * v * diag ([lambda;0])) (:, 1:sz);
+%! assert ( (a*v) (:, 1:sz), observed, norm (observed) * 1e-14);
+%! observed = (diag ([lambda;0]) * w' * b) (1:sz, :);
+%! assert ( (w'*a) (1:sz, :) , observed, norm (observed) * 1e-13);
+%! assert (q * a * z, aa, norm (aa) * 1e-14);
+%! assert (q * b * z, bb, norm (bb) * 1e-14);
+
+%% FIXME: Still need a test for third form of calling qz
+
+*/
--- a/src/DLD-FUNCTIONS/rand.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/DLD-FUNCTIONS/rand.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -177,20 +177,17 @@
 
                 octave_idx_type base = NINTbig (r.base ());
                 octave_idx_type incr = NINTbig (r.inc ());
-                octave_idx_type lim = NINTbig (r.limit ());
 
-                if (base < 0 || lim < 0)
-                  error ("%s: all dimensions must be positive", fcn);
-                else
+                for (octave_idx_type i = 0; i < n; i++)
                   {
-                    for (octave_idx_type i = 0; i < n; i++)
-                      {
-                        dims(i) = base;
-                        base += incr;
-                      }
+                    //Negative dimensions are treated as zero for Matlab
+                    //compatibility
+                    dims(i) = base >= 0 ? base : 0;
+                    base += incr;
+                  }
 
-                    goto gen_matrix;
-                  }
+                goto gen_matrix;
+
               }
             else
               error ("%s: all elements of range must be integers",
@@ -208,15 +205,10 @@
 
                 for (octave_idx_type i = 0; i < len; i++)
                   {
+                    //Negative dimensions are treated as zero for Matlab
+                    //compatibility
                     octave_idx_type elt = iv(i);
-
-                    if (elt < 0)
-                      {
-                        error ("%s: all dimensions must be positive", fcn);
-                        goto done;
-                      }
-
-                    dims(i) = iv(i);
+                    dims(i) = elt >=0 ? elt : 0;
                   }
 
                 goto gen_matrix;
@@ -278,13 +270,14 @@
 
             for (int i = 0; i < nargin; i++)
               {
-                dims(i) = args(idx+i).int_value ();
-
+                octave_idx_type elt = args(idx+i).int_value ();
                 if (error_state)
                   {
                     error ("%s: expecting integer arguments", fcn);
                     goto done;
                   }
+                //Negative is zero for Matlab compatibility
+                dims(i) = elt >= 0 ? elt : 0;
               }
 
             goto gen_matrix;
--- a/src/DLD-FUNCTIONS/rcond.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/DLD-FUNCTIONS/rcond.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -85,3 +85,12 @@
 
   return retval;
 }
+
+/*
+
+%!assert( rcond (eye (2)), 1)
+%!assert( rcond (ones (2)), 0)
+%!assert( rcond ([1 1; 2 1]), 1/9)
+%!assert( rcond (magic (4)), 0, eps)
+
+*/
--- a/src/DLD-FUNCTIONS/spparms.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/DLD-FUNCTIONS/spparms.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -136,7 +136,7 @@
             {
               double val = octave_sparse_params::get_key (str);
               if (xisnan (val))
-                error ("spparams: KEY not recognized");
+                error ("spparms: KEY not recognized");
               else
                 retval (0) = val;
             }
@@ -148,7 +148,7 @@
           if (error_state)
             error ("spparms: input must be a string or a vector");
           else if (vals.numel () > OCTAVE_SPARSE_CONTROLS_SIZE)
-            error ("spparams: too many elements in vector VALS");
+            error ("spparms: too many elements in vector VALS");
           else
             octave_sparse_params::set_vals (vals);
         }
@@ -176,3 +176,33 @@
 
   return retval;
 }
+
+/*
+
+%!test
+%! old_vals = spparms ();  # save state
+%! spparms ("defaults");
+%! vals = spparms ();
+%! assert (vals, [0 1 1 0 3 3 0.5 1.0 1.0 0.1 0.5 1.0 0.001]');
+%! [keys, vals] = spparms ();
+%! assert (rows (keys), 13);
+%! assert (keys(2,:), "ths_rel");
+%! assert (vals, [0 1 1 0 3 3 0.5 1.0 1.0 0.1 0.5 1.0 0.001]');
+%! spparms ([3 2 1]);
+%! assert (spparms ()(1:3), [3, 2, 1]');
+%! assert (spparms ("ths_rel"), 2);
+%! spparms ("exact_d", 5);
+%! assert (spparms ("exact_d"), 5);
+%! spparms (old_vals);     # restore state
+
+%% Test input validation
+%!error (spparms (1, 2, 3))
+%!error ([x, y, z] = spparms ())
+%!error (spparms ("UNKNOWN_KEY"))
+%!error (spparms ({1, 2, 3}))
+%!error (spparms (ones (14, 1)))
+%!error (spparms (1, 1))
+%!error (spparms ("ths_rel", "hello"))
+%!error (spparms ("UNKNOWN_KEY", 1))
+
+*/
--- a/src/DLD-FUNCTIONS/sqrtm.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/DLD-FUNCTIONS/sqrtm.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -49,22 +49,20 @@
 
   bool singular = false;
 
-  /*
-   * the following code is equivalent to this triple loop:
-   *
-   *  n = rows (T);
-   *  for j = 1:n
-   *    T(j,j) = sqrt (T(j,j));
-   *    for i = j-1:-1:1
-   *      T(i,j) /= (T(i,i) + T(j,j));
-   *      k = 1:i-1;
-   *      T(k,j) -= T(k,i) * T(i,j);
-   *    endfor
-   *  endfor
-   *
-   *  this is an in-place, cache-aligned variant of the code
-   *  given in Higham's paper.
-  */
+  // The following code is equivalent to this triple loop:
+  //
+  //   n = rows (T);
+  //   for j = 1:n
+  //     T(j,j) = sqrt (T(j,j));
+  //     for i = j-1:-1:1
+  //       T(i,j) /= (T(i,i) + T(j,j));
+  //       k = 1:i-1;
+  //       T(k,j) -= T(k,i) * T(i,j);
+  //     endfor
+  //   endfor
+  //
+  // this is an in-place, cache-aligned variant of the code
+  // given in Higham's paper.
 
   const octave_idx_type n = T.rows ();
   element_type *Tp = T.fortran_vec ();
@@ -117,38 +115,32 @@
         {
         case MatrixType::Upper:
         case MatrixType::Diagonal:
-            {
-              if (! x.diag ().any_element_is_negative ())
-                {
-                  // Do it in real arithmetic.
-                  sqrtm_utri_inplace (x);
-                  retval = x;
-                  retval.matrix_type (mt);
-                }
-              else
-                iscomplex = true;
-
-              break;
-            }
-        case MatrixType::Lower:
+          if (! x.diag ().any_element_is_negative ())
             {
-              if (! x.diag ().any_element_is_negative ())
-                {
-                  x = x.transpose ();
-                  sqrtm_utri_inplace (x);
-                  retval = x.transpose ();
-                  retval.matrix_type (mt);
-                }
-              else
-                iscomplex = true;
+              // Do it in real arithmetic.
+              sqrtm_utri_inplace (x);
+              retval = x;
+              retval.matrix_type (mt);
+            }
+          else
+            iscomplex = true;
+          break;
 
-              break;
+        case MatrixType::Lower:
+          if (! x.diag ().any_element_is_negative ())
+            {
+              x = x.transpose ();
+              sqrtm_utri_inplace (x);
+              retval = x.transpose ();
+              retval.matrix_type (mt);
             }
+          else
+            iscomplex = true;
+          break;
+
         default:
-          {
-            iscomplex = true;
-            break;
-          }
+          iscomplex = true;
+          break;
         }
 
       if (iscomplex)
@@ -166,46 +158,41 @@
         {
         case MatrixType::Upper:
         case MatrixType::Diagonal:
-            {
-              sqrtm_utri_inplace (x);
-              retval = x;
-              retval.matrix_type (mt);
+          sqrtm_utri_inplace (x);
+          retval = x;
+          retval.matrix_type (mt);
+          break;
 
-              break;
-            }
         case MatrixType::Lower:
-            {
-              x = x.transpose ();
-              sqrtm_utri_inplace (x);
-              retval = x.transpose ();
-              retval.matrix_type (mt);
+          x = x.transpose ();
+          sqrtm_utri_inplace (x);
+          retval = x.transpose ();
+          retval.matrix_type (mt);
+          break;
 
-              break;
-            }
         default:
-            {
-              ComplexMatrix u;
+          {
+            ComplexMatrix u;
 
-              do
-                {
-                  ComplexSCHUR schur (x, std::string (), true);
-                  x = schur.schur_matrix ();
-                  u = schur.unitary_matrix ();
-                }
-              while (0); // schur no longer needed.
+            do
+              {
+                ComplexSCHUR schur (x, std::string (), true);
+                x = schur.schur_matrix ();
+                u = schur.unitary_matrix ();
+              }
+            while (0); // schur no longer needed.
 
-              sqrtm_utri_inplace (x);
+            sqrtm_utri_inplace (x);
 
-              x = u * x; // original x no longer needed.
-              ComplexMatrix res = xgemm (x, u, blas_no_trans, blas_conj_trans);
+            x = u * x; // original x no longer needed.
+            ComplexMatrix res = xgemm (x, u, blas_no_trans, blas_conj_trans);
 
-              if (cutoff > 0 && xnorm (imag (res), one) <= cutoff)
-                retval = real (res);
-              else
-                retval = res;
-
-              break;
-            }
+            if (cutoff > 0 && xnorm (imag (res), one) <= cutoff)
+              retval = real (res);
+            else
+              retval = res;
+          }
+          break;
         }
     }
 
@@ -246,22 +233,17 @@
     }
 
   if (arg.is_diag_matrix ())
-    {
-      // sqrtm of a diagonal matrix is just sqrt.
-      retval(0) = arg.sqrt ();
-    }
+    // sqrtm of a diagonal matrix is just sqrt.
+    retval(0) = arg.sqrt ();
   else if (arg.is_single_type ())
-    {
-      retval(0) = do_sqrtm<FloatMatrix, FloatComplexMatrix, FloatComplexSCHUR> (arg);
-    }
+    retval(0) = do_sqrtm<FloatMatrix, FloatComplexMatrix, FloatComplexSCHUR> (arg);
   else if (arg.is_numeric_type ())
-    {
-      retval(0) = do_sqrtm<Matrix, ComplexMatrix, ComplexSCHUR> (arg);
-    }
+    retval(0) = do_sqrtm<Matrix, ComplexMatrix, ComplexSCHUR> (arg);
 
   if (nargout > 1 && ! error_state)
     {
       // This corresponds to generic code
+      //
       //   norm (s*s - x, "fro") / norm (x, "fro");
 
       octave_value s = retval(0);
@@ -270,3 +252,22 @@
 
   return retval;
 }
+
+/*
+
+%!assert (sqrtm (2*ones (2)), ones (2), 3*eps)
+
+## The following two tests are from the reference in the docstring above.
+
+%!test
+%! x = [0 1; 0 0];
+%! assert (any (isnan (sqrtm (x))(:) ))
+
+%!test
+%! x = eye (4); x(2,2) = x(3,3) = 2^-26; x(1,4) = 1;
+%! z = eye (4); z(2,2) = z(3,3) = 2^-13; z(1,4) = 0.5;
+%! [y, err] = sqrtm(x);
+%! assert (y, z)
+%! assert (err, 0)   ## Yes, this one has to hold exactly
+
+*/
--- a/src/DLD-FUNCTIONS/str2double.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/DLD-FUNCTIONS/str2double.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -271,7 +271,7 @@
     }
   else if (args(0).is_cell ())
     {
-      const Cell cell = args(0).cell_value (); 
+      const Cell cell = args(0).cell_value ();
 
       if (! error_state)
       {
@@ -286,7 +286,7 @@
     }
   else
     retval = NDArray (args(0).dims (), octave_NaN);
-  
+
 
   return retval;
 }
--- a/src/DLD-FUNCTIONS/urlwrite.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/DLD-FUNCTIONS/urlwrite.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -112,11 +112,11 @@
           {
             BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
 
-            CURLcode res = curl_easy_perform (curl);
-            if (res != CURLE_OK)
+            errnum = curl_easy_perform (curl);
+            if (errnum != CURLE_OK)
               {
                 if (curlerror)
-                  error ("%s", curl_easy_strerror (res));
+                  error ("%s", curl_easy_strerror (errnum));
               }
             else
               retval = true;
@@ -145,6 +145,7 @@
     std::string host;
     bool valid;
     bool ascii;
+    mutable CURLcode errnum;
 
   private:
     CURL *curl;
@@ -250,11 +251,7 @@
 
   std::string lasterror (void) const
     {
-      CURLcode errnum;
-
-      curl_easy_getinfo (rep->handle(), CURLINFO_OS_ERRNO, &errnum);
-
-      return std::string (curl_easy_strerror (errnum));
+      return std::string (curl_easy_strerror (rep->errnum));
     }
 
   void set_ostream (std::ostream& os) const
--- a/src/Makefile.am	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/Makefile.am	Tue Sep 20 15:38:24 2011 -0400
@@ -3,17 +3,17 @@
 # Copyright (C) 1993-2011 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 3 of the License, 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, see
 # <http://www.gnu.org/licenses/>.
@@ -24,7 +24,7 @@
   @CPPFLAGS@ -I../libgnu -I$(top_srcdir)/libgnu \
   -I$(top_srcdir)/libcruft/misc \
   -I../liboctave -I$(top_srcdir)/liboctave \
-  -I. -I$(srcdir) 
+  -I. -I$(srcdir)
 
 AUTOMAKE_OPTIONS = subdir-objects
 
@@ -56,7 +56,7 @@
   octave-config
 endif
 
-## Order matters here.  Leave builtins.cc last, because it depends on 
+## Order matters here.  Leave builtins.cc last, because it depends on
 ## $(DEF_FILES), and building those requires all the sources
 ## (except builtins.cc) to be available.
 BUILT_SOURCES = \
@@ -310,6 +310,7 @@
   defaults.h \
   graphics.h \
   oct-conf.h \
+  profiler.h \
   mxarray.h \
   version.h
 
@@ -446,6 +447,7 @@
   pager.cc \
   pr-output.cc \
   procstream.cc \
+  profiler.cc \
   sighandlers.cc \
   siglist.c \
   sparse.cc \
@@ -478,20 +480,15 @@
 include TEMPLATE-INST/module.mk
 
 if AMCOND_ENABLE_DYNAMIC_LINKING
-  DLD_DYNAMIC_SRC = $(DLD_FUNCTIONS_SRC)
-  DLD_STATIC_SRC =
   OCT_FILES = $(DLD_FUNCTIONS_LIBS:.la=.oct)
   OCT_STAMP_FILES = $(subst DLD-FUNCTIONS/,DLD-FUNCTIONS/$(am__leading_dot),$(DLD_FUNCTIONS_LIBS:.la=.oct-stamp))
 else
-  DLD_DYNAMIC_SRC =
-  DLD_STATIC_SRC = $(DLD_FUNCTIONS_SRC)
   OCT_FILES =
   OCT_STAMP_FILES =
 endif
 
 liboctinterp_la_SOURCES = \
   $(DIST_SRC) \
-  $(DLD_STATIC_SRC) \
   $(OPERATORS_SRC) \
   $(TEMPLATE_INST_SRC)
 
@@ -506,87 +503,14 @@
   version.h \
   $(OPT_INC)
 
+liboctinterp_la_CPPFLAGS = @OCTINTERP_DLL_DEFS@ $(AM_CPPFLAGS)
 
-if AMCOND_ENABLE_DYNAMIC_LINKING
-  OCTAVE_LIBS = \
-    ./liboctinterp.la \
-    ../liboctave/liboctave.la \
-    ../libcruft/libcruft.la \
-    ../libcruft/libranlib.la \
-    ../libgnu/libgnu.la \
-    $(SPARSE_XLDFLAGS) $(SPARSE_XLIBS) \
-    $(QRUPDATE_LDFLAGS) $(QRUPDATE_LIBS) \
-    $(FFTW_XLDFLAGS) $(FFTW_XLIBS) \
-    $(LAPACK_LIBS) $(BLAS_LIBS) \
-    $(GRAPHICS_LDFLAGS) $(GRAPHICS_LIBS) \
-    $(FT2_LDFLAGS) $(FT2_LIBS) \
-    $(HDF5_LDFLAGS) $(HDF5_LIBS) $(Z_LDFLAGS) $(Z_LIBS) \
-    $(OPENGL_LIBS) $(X11_LIBS) $(CARBON_LIBS) \
-    $(READLINE_LIBS) $(TERM_LIBS) \
-    $(LIBGLOB) \
-    $(REGEX_LDFLAGS) $(REGEX_LIBS) \
-    $(LAPACK_LIBS) $(BLAS_LIBS) \
-    $(DL_LIBS) $(PTHREAD_LIBS) \
-    $(LIBS) \
-    $(FLIBS)
-else
-  ## FIXME -- this list is probably not complete now.  It may not even
-  ## be possible to build a statically linked copy of Octave that is
-  ## fully functional.
-  OCTAVE_LIBS = \
-    ./liboctinterp.la \
-    ../liboctave/liboctave.la \
-    ../libcruft/libcruft.la \
-    ../libcruft/libranlib.la \
-    ../libgnu/libgnu.la \
-    $(FFTW_XLDFLAGS) $(FFTW_XLIBS) \
-    $(QHULL_LDFLAGS) $(QHULL_LIBS) \
-    $(QRUPDATE_LDFLAGS) $(QRUPDATE_LIBS) \
-    $(SPARSE_XLDFLAGS) $(SPARSE_XLIBS) \
-    $(REGEX_LDFLAGS) $(REGEX_LIBS) \
-    $(CURL_LDFLAGS) $(CURL_LIBS) \
-    $(GLPK_LDFLAGS) $(GLPK_LIBS) \
-    $(MAGICK_LDFLAGS) $(MAGICK_LIBS) \
-    $(GRAPHICS_LDFLAGS) $(GRAPHICS_LIBS) \
-    $(FT2_LDFLAGS) $(FT2_LIBS) \
-    $(HDF5_LDFLAGS) $(HDF5_LIBS) $(Z_LDFLAGS) $(Z_LIBS) \
-    $(OPENGL_LIBS) $(X11_LIBS) $(CARBON_LIBS) \
-    $(READLINE_LIBS) $(TERM_LIBS) \
-    $(LIBGLOB) \
-    $(LAPACK_LIBS) $(BLAS_LIBS) \
-    $(DL_LIBS) $(PTHREAD_LIBS) \
-    $(LIBS) \
-    $(FLIBS)
-endif
+include link-deps.mk
 
-OCTINTERP_LINK_DEPS = \
-  $(RLD_FLAG) \
+liboctinterp_la_LIBADD = \
   ../liboctave/liboctave.la \
   ../libcruft/libcruft.la \
-  ../libcruft/libranlib.la \
-  ../libgnu/libgnu.la \
-  $(FFTW_XLDFLAGS) $(FFTW_XLIBS) \
-  $(FT2_LDFLAGS) $(FT2_LIBS) \
-  $(HDF5_LDFLAGS) $(HDF5_LIBS) $(Z_LDFLAGS) $(Z_LIBS) \
-  $(OPENGL_LIBS) $(X11_LIBS) $(CARBON_LIBS) \
-  $(READLINE_LIBS) $(TERM_LIBS) \
-  $(LIBGLOB) \
-  $(LAPACK_LIBS) $(BLAS_LIBS) \
-  $(LIBS) \
-  $(FLIBS)
-
-liboctinterp_la_LIBADD = $(OCTINTERP_LINK_DEPS)
-
-## Additional library dependencies used by module.mk files
-OCT_LINK_DEPS = \
-  $(RLD_FLAG) $(LDFLAGS) \
-  ./liboctinterp.la \
-  ../liboctave/liboctave.la \
-  ../libcruft/libcruft.la \
-  ../libcruft/libranlib.la \
-  ../libgnu/libgnu.la
-
-liboctinterp_la_CPPFLAGS = @OCTINTERP_DLL_DEFS@ $(AM_CPPFLAGS)
+  $(LIBOCTINTERP_LINK_DEPS)
 
 # Increment these as needed and according to the rules in the libtool manual:
 liboctinterp_current = 0
@@ -598,120 +522,39 @@
 liboctinterp_la_LDFLAGS = \
   -version-info $(liboctinterp_version_info) \
   $(NO_UNDEFINED_LDFLAG) \
-  -bindir $(bindir)
+  -bindir $(bindir) \
+  $(LIBOCTINTERP_LINK_OPTS)
 
 display.df display.lo: CPPFLAGS += $(X11_FLAGS)
 
-DLD-FUNCTIONS/__magick_read__.df: CPPFLAGS += $(MAGICK_CPPFLAGS)
-DLD_FUNCTIONS___magick_read___la_CPPFLAGS = $(AM_CPPFLAGS) $(MAGICK_CPPFLAGS)
-DLD_FUNCTIONS___magick_read___la_LIBADD += $(MAGICK_LDFLAGS) $(MAGICK_LIBS)
-
-DLD-FUNCTIONS/convhulln.df: CPPFLAGS += $(QHULL_CPPFLAGS)
-DLD_FUNCTIONS_convhulln_la_CPPFLAGS = $(AM_CPPFLAGS) $(QHULL_CPPFLAGS)
-DLD_FUNCTIONS_convhulln_la_LIBADD += $(QHULL_LDFLAGS) $(QHULL_LIBS)
-
-DLD-FUNCTIONS/__delaunayn__.df: CPPFLAGS += $(QHULL_CPPFLAGS)
-DLD_FUNCTIONS___delaunayn___la_CPPFLAGS = $(AM_CPPFLAGS) $(QHULL_CPPFLAGS)
-DLD_FUNCTIONS___delaunayn___la_LIBADD += $(QHULL_LDFLAGS) $(QHULL_LIBS)
-
-DLD-FUNCTIONS/__voronoi__.df: CPPFLAGS += $(QHULL_CPPFLAGS)
-DLD_FUNCTIONS___voronoi___la_CPPFLAGS = $(AM_CPPFLAGS) $(QHULL_CPPFLAGS)
-DLD_FUNCTIONS___voronoi___la_LIBADD += $(QHULL_LDFLAGS) $(QHULL_LIBS)
-
-DLD-FUNCTIONS/eigs.df: CPPFLAGS += $(SPARSE_XCPPFLAGS)
-DLD_FUNCTIONS_eigs_la_CPPFLAGS = $(AM_CPPFLAGS) $(SPARSE_XCPPFLAGS)
-DLD_FUNCTIONS_eigs_la_LIBADD += $(SPARSE_XLDFLAGS) $(SPARSE_XLIBS) $(LAPACK_LIBS) $(BLAS_LIBS)
-
-#DLD-FUNCTIONS/qz.df DLD-FUNCTIONS/qz.lo:
-DLD_FUNCTIONS_qz_la_LIBADD += $(LAPACK_LIBS) $(BLAS_LIBS)
-
-DLD-FUNCTIONS/qr.df: CPPFLAGS += $(QRUPDATE_CPPFLAGS) $(SPARSE_XCPPFLAGS)
-DLD_FUNCTIONS_qr_la_CPPFLAGS = $(AM_CPPFLAGS) $(QRUPDATE_CPPFLAGS) $(SPARSE_XCPPFLAGS)
-DLD_FUNCTIONS_qr_la_LIBADD += $(QRUPDATE_LDFLAGS) $(QRUPDATE_LIBS) $(SPARSE_XLDFLAGS) $(SPARSE_XLIBS)
-
-DLD-FUNCTIONS/chol.df: CPPFLAGS += $(QRUPDATE_CPPFLAGS) $(SPARSE_XCPPFLAGS)
-DLD_FUNCTIONS_chol_la_CPPFLAGS = $(AM_CPPFLAGS) $(QRUPDATE_CPPFLAGS) $(SPARSE_XCPPFLAGS)
-DLD_FUNCTIONS_chol_la_LIBADD += $(QRUPDATE_LDFLAGS) $(QRUPDATE_LIBS) $(SPARSE_XLDFLAGS) $(SPARSE_XLIBS)
-
-DLD-FUNCTIONS/regexp.df: CPPFLAGS += $(REGEX_CPPFLAGS)
-DLD_FUNCTIONS_regexp_la_CPPFLAGS = $(AM_CPPFLAGS) $(REGEX_CPPFLAGS)
-DLD_FUNCTIONS_regexp_la_LIBADD += $(REGEX_LDFLAGS) $(REGEX_LIBS)
-
-DLD-FUNCTIONS/urlwrite.df: CPPFLAGS += $(CURL_CPPFLAGS)
-DLD_FUNCTIONS_urlwrite_la_CPPFLAGS = $(AM_CPPFLAGS) $(CURL_CPPFLAGS)
-DLD_FUNCTIONS_urlwrite_la_LIBADD += $(CURL_LDFLAGS) $(CURL_LIBS)
-
-DLD-FUNCTIONS/__fltk_uigetfile__.df: CPPFLAGS += $(GRAPHICS_CFLAGS) $(FT2_CPPFLAGS)
-DLD_FUNCTIONS___fltk_uigetfile___la_CPPFLAGS = $(AM_CPPFLAGS) $(GRAPHICS_CFLAGS) $(FT2_CPPFLAGS)
-DLD_FUNCTIONS___fltk_uigetfile___la_LIBADD += $(GRAPHICS_LDFLAGS) $(GRAPHICS_LIBS) $(FT2_LDFLAGS) $(FT2_LIBS)
-
-DLD-FUNCTIONS/__glpk__.df: CPPFLAGS += $(GLPK_CPPFLAGS)
-DLD_FUNCTIONS___glpk___la_CPPFLAGS = $(AM_CPPFLAGS) $(GLPK_CPPFLAGS)
-DLD_FUNCTIONS___glpk___la_LIBADD += $(GLPK_LDFLAGS) $(GLPK_LIBS)
-
-DLD-FUNCTIONS/__init_fltk__.df: CPPFLAGS += $(GRAPHICS_CFLAGS) $(FT2_CPPFLAGS)
-DLD_FUNCTIONS___init_fltk___la_CPPFLAGS = $(AM_CPPFLAGS) $(GRAPHICS_CFLAGS) $(FT2_CPPFLAGS)
-DLD_FUNCTIONS___init_fltk___la_LIBADD += $(GRAPHICS_LDFLAGS) $(GRAPHICS_LIBS) $(FT2_LDFLAGS) $(FT2_LIBS)
-
-DLD-FUNCTIONS/amd.df: CPPFLAGS += $(SPARSE_XCPPFLAGS)
-DLD_FUNCTIONS_amd_la_CPPFLAGS = $(AM_CPPFLAGS) $(SPARSE_XCPPFLAGS)
-DLD_FUNCTIONS_amd_la_LIBADD += $(SPARSE_XLDFLAGS) $(SPARSE_XLIBS)
-
-DLD-FUNCTIONS/colamd.df: CPPFLAGS += $(SPARSE_XCPPFLAGS)
-DLD_FUNCTIONS_colamd_la_CPPFLAGS = $(AM_CPPFLAGS) $(SPARSE_XCPPFLAGS)
-DLD_FUNCTIONS_colamd_la_LIBADD += $(SPARSE_XLDFLAGS) $(SPARSE_XLIBS)
-
-DLD-FUNCTIONS/ccolamd.df: CPPFLAGS += $(SPARSE_XCPPFLAGS)
-DLD_FUNCTIONS_ccolamd_la_CPPFLAGS = $(AM_CPPFLAGS) $(SPARSE_XCPPFLAGS)
-DLD_FUNCTIONS_ccolamd_la_LIBADD += $(SPARSE_XLDFLAGS) $(SPARSE_XLIBS)
-
-DLD-FUNCTIONS/symbfact.df: CPPFLAGS += $(SPARSE_XCPPFLAGS)
-DLD_FUNCTIONS_symbfact_la_CPPFLAGS = $(AM_CPPFLAGS) $(SPARSE_XCPPFLAGS)
-DLD_FUNCTIONS_symbfact_la_LIBADD += $(SPARSE_XLDFLAGS) $(SPARSE_XLIBS)
-
-DLD-FUNCTIONS/dmperm.df: CPPFLAGS += $(SPARSE_XCPPFLAGS)
-DLD_FUNCTIONS_dmperm_la_CPPFLAGS = $(AM_CPPFLAGS) $(SPARSE_XCPPFLAGS)
-DLD_FUNCTIONS_dmperm_la_LIBADD += $(SPARSE_XLDFLAGS) $(SPARSE_XLIBS)
-
-DLD-FUNCTIONS/symrcm.df: CPPFLAGS += $(SPARSE_XCPPFLAGS)
-DLD_FUNCTIONS_symrcm_la_CPPFLAGS = $(AM_CPPFLAGS) $(SPARSE_XCPPFLAGS)
-DLD_FUNCTIONS_symrcm_la_LIBADD += $(SPARSE_XLDFLAGS) $(SPARSE_XLIBS)
-
-DLD-FUNCTIONS/fft.df: CPPFLAGS += $(FFTW_XCPPFLAGS)
-DLD_FUNCTIONS_fft_la_CPPFLAGS = $(AM_CPPFLAGS) $(FFTW_XCPPFLAGS)
-DLD_FUNCTIONS_fft_la_LIBADD += $(FFTW_XLDFLAGS) $(FFTW_XLIBS)
-
-DLD-FUNCTIONS/fft2.df: CPPFLAGS += $(FFTW_XCPPFLAGS)
-DLD_FUNCTIONS_fft2_la_CPPFLAGS = $(AM_CPPFLAGS) $(FFTW_XCPPFLAGS)
-DLD_FUNCTIONS_fft2_la_LIBADD += $(FFTW_XLDFLAGS) $(FFTW_XLIBS)
-
-DLD-FUNCTIONS/fftn.df: CPPFLAGS += $(FFTW_XCPPFLAGS)
-DLD_FUNCTIONS_fftn_la_CPPFLAGS = $(AM_CPPFLAGS) $(FFTW_XCPPFLAGS)
-DLD_FUNCTIONS_fftn_la_LIBADD += $(FFTW_XLDFLAGS) $(FFTW_XLIBS)
-
-DLD-FUNCTIONS/fftw.df: CPPFLAGS += $(FFTW_XCPPFLAGS)
-DLD_FUNCTIONS_fftw_la_CPPFLAGS = $(AM_CPPFLAGS) $(FFTW_XCPPFLAGS)
-DLD_FUNCTIONS_fftw_la_LIBADD += $(FFTW_XLDFLAGS) $(FFTW_XLIBS)
-
-
 octave_SOURCES = main.c
 
-octave_LDADD = $(OCTAVE_LIBS)
+octave_LDADD = \
+  liboctinterp.la \
+  ../liboctave/liboctave.la \
+  ../libcruft/libcruft.la \
+  $(OCTAVE_LINK_DEPS)
 
+octave_LDFLAGS = \
+  $(NO_UNDEFINED_LDFLAG) \
+  $(OCTAVE_LINK_OPTS)
 
 ## Section for defining and creating DEF_FILES
 SRC_DEF_FILES := $(shell $(srcdir)/find-defun-files.sh "$(srcdir)" $(DIST_SRC))
 
-DLD_STATIC_DEF_FILES  = $(DLD_STATIC_SRC:.cc=.df)
-DLD_DYNAMIC_DEF_FILES = $(DLD_DYNAMIC_SRC:.cc=.df)
+DLD_FUNCTIONS_DEF_FILES = $(DLD_FUNCTIONS_SRC:.cc=.df)
 
 ## builtins.cc depends on $(DEF_FILES), so DEF_FILES should only include
 ## .df files that correspond to sources included in liboctave.
-DEF_FILES = $(SRC_DEF_FILES) $(DLD_STATIC_DEF_FILES)
+if AMCOND_ENABLE_DYNAMIC_LINKING
+  DEF_FILES = $(SRC_DEF_FILES)
+else
+  DEF_FILES = $(SRC_DEF_FILES) $(DLD_FUNCTIONS_DEF_FILES)
+endif
 
-ALL_DEF_FILES = $(DEF_FILES) $(DLD_DYNAMIC_DEF_FILES)
+ALL_DEF_FILES = $(SRC_DEF_FILES) $(DLD_FUNCTIONS_DEF_FILES)
 
-$(DEF_FILES) $(DYNAMIC_DLD_DEF_FILES): mkdefs Makefile
+$(SRC_DEF_FILES): mkdefs Makefile
 
 $(DEF_FILES): $(OPT_HANDLERS) $(OPT_INC)
 
@@ -725,7 +568,7 @@
 	  -DMAKE_BUILTINS $< | $(srcdir)/mkdefs $(srcdir) $< > $@-t
 	mv $@-t $@
 
-## Special rules:  
+## Special rules:
 ## Mostly for sources which must be built before rest of compilation.
 
 ## defaults.h and oct-conf.h must depend on Makefile.  Calling configure
@@ -794,9 +637,13 @@
 $(OPT_INC) : %.h : %.in
 	$(MAKE) -C $(@D) $(@F)
 
-DLD-FUNCTIONS/PKG_ADD: $(DLD_DYNAMIC_DEF_FILES) mk-pkg-add
-	$(srcdir)/mk-pkg-add $(DLD_DYNAMIC_DEF_FILES) > $@-t
+if AMCOND_ENABLE_DYNAMIC_LINKING
+DLD_FUNCTIONS_PKG_ADD_FILE = DLD-FUNCTIONS/PKG_ADD
+
+DLD-FUNCTIONS/PKG_ADD: $(DLD_FUNCTIONS_DEF_FILES) mk-pkg-add
+	$(srcdir)/mk-pkg-add $(DLD_FUNCTIONS_DEF_FILES) > $@-t
 	mv $@-t $@
+endif
 
 lex.lo lex.o oct-parse.lo oct-parse.o: \
   AM_CXXFLAGS := $(filter-out -Wold-style-cast, $(AM_CXXFLAGS))
@@ -828,8 +675,7 @@
 gendoc$(BUILD_EXEEXT): gendoc.cc
 	$(BUILD_CXX) $(BUILD_CXXFLAGS) -o $@ $^ $(BUILD_LDFLAGS)
 
-
-all-local: $(OCT_STAMP_FILES) DLD-FUNCTIONS/PKG_ADD .DOCSTRINGS
+all-local: $(OCT_STAMP_FILES) $(DLD_FUNCTIONS_PKG_ADD_FILE) .DOCSTRINGS
 
 if AMCOND_BUILD_COMPILED_AUX_PROGRAMS
 octave-config.cc: octave-config.cc.in Makefile
@@ -882,8 +728,8 @@
 if AMCOND_ENABLE_DYNAMIC_LINKING
 install-oct:
 	$(top_srcdir)/build-aux/mkinstalldirs $(DESTDIR)$(octfiledir)
-	if [ -n "`cat DLD-FUNCTIONS/PKG_ADD`" ]; then \
-	  $(INSTALL_DATA) DLD-FUNCTIONS/PKG_ADD $(DESTDIR)$(octfiledir)/PKG_ADD; \
+	if [ -n "`cat $(DLD_FUNCTIONS_PKG_ADD_FILE)`" ]; then \
+	  $(INSTALL_DATA) $(DLD_FUNCTIONS_PKG_ADD_FILE) $(DESTDIR)$(octfiledir)/PKG_ADD; \
 	fi
 	cd $(DESTDIR)$(octlibdir) && \
 	for ltlib in $(DLD_FUNCTIONS_LIBS); do \
@@ -911,7 +757,7 @@
 
 CLEANFILES = \
   $(bin_SCRIPTS) \
-  DLD-FUNCTIONS/PKG_ADD \
+  $(DLD_FUNCTIONS_PKG_ADD_FILE) \
   doc-files \
   gendoc.cc \
   gendoc$(BUILD_EXEEXT) \
--- a/src/OPERATORS/op-cell.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/OPERATORS/op-cell.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -51,36 +51,6 @@
 
 DEFCATOP_FN (c_c, cell, cell, concat)
 
-static octave_value
-oct_catop_cell_matrix (octave_base_value& a1, const octave_base_value& a2,
-                         const Array<octave_idx_type>&)
-{
-  octave_value retval;
-  CAST_BINOP_ARGS (const octave_cell&, const octave_matrix&);
-  NDArray tmp = v2.array_value ();
-  dim_vector dv = tmp.dims ();
-  if (dv.all_zero ())
-    retval = octave_value (v1.cell_value ());
-  else
-    error ("invalid concatenation of cell array with matrix");
-  return retval;
-}
-
-static octave_value
-oct_catop_matrix_cell (octave_base_value& a1, const octave_base_value& a2,
-                         const Array<octave_idx_type>&)
-{
-  octave_value retval;
-  CAST_BINOP_ARGS (const octave_matrix&, const octave_cell&);
-  NDArray tmp = v1.array_value ();
-  dim_vector dv = tmp.dims ();
-  if (dv.all_zero ())
-    retval = octave_value (v2.cell_value ());
-  else
-    error ("invalid concatenation of cell array with matrix");
-  return retval;
-}
-
 DEFASSIGNANYOP_FN (assign, cell, assign);
 
 DEFNULLASSIGNOP_FN (null_assign, cell, delete_elements)
@@ -93,9 +63,6 @@
 
   INSTALL_CATOP (octave_cell, octave_cell, c_c);
 
-  INSTALL_CATOP (octave_cell, octave_matrix, cell_matrix);
-  INSTALL_CATOP (octave_matrix, octave_cell, matrix_cell);
-
   INSTALL_ASSIGNANYOP (op_asn_eq, octave_cell, assign);
 
   INSTALL_ASSIGNOP (op_asn_eq, octave_cell, octave_null_matrix, null_assign);
--- a/src/OPERATORS/op-int.h	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/OPERATORS/op-int.h	Tue Sep 20 15:38:24 2011 -0400
@@ -21,6 +21,7 @@
 */
 
 #include "quit.h"
+#include "bsxfun.h"
 
 #define DEFINTBINOP_OP(name, t1, t2, op, t3) \
   BINOPDECL (name, a1, a2) \
@@ -703,8 +704,15 @@
     dim_vector b_dims = b.dims (); \
     if (a_dims != b_dims) \
       { \
-        gripe_nonconformant ("operator .^", a_dims, b_dims); \
-        return octave_value (); \
+        if (is_valid_bsxfun (a_dims, b_dims)) \
+          { \
+            return bsxfun_pow (a, b); \
+          } \
+        else \
+          { \
+            gripe_nonconformant ("operator .^", a_dims, b_dims);  \
+            return octave_value (); \
+          } \
       } \
     T1 ## NDArray result (a_dims); \
     for (int i = 0; i < a.length (); i++) \
@@ -722,8 +730,15 @@
     dim_vector b_dims = b.dims (); \
     if (a_dims != b_dims) \
       { \
-        gripe_nonconformant ("operator .^", a_dims, b_dims); \
-        return octave_value (); \
+        if (is_valid_bsxfun (a_dims, b_dims)) \
+          { \
+            return bsxfun_pow (a, b); \
+          } \
+        else \
+          { \
+            gripe_nonconformant ("operator .^", a_dims, b_dims);  \
+            return octave_value (); \
+          } \
       } \
     T1 ## NDArray result (a_dims); \
     for (int i = 0; i < a.length (); i++) \
@@ -741,8 +756,15 @@
     dim_vector b_dims = b.dims (); \
     if (a_dims != b_dims) \
       { \
-        gripe_nonconformant ("operator .^", a_dims, b_dims); \
-        return octave_value (); \
+        if (is_valid_bsxfun (a_dims, b_dims)) \
+          { \
+            return bsxfun_pow (a, b); \
+          } \
+        else \
+          { \
+            gripe_nonconformant ("operator .^", a_dims, b_dims);  \
+            return octave_value (); \
+          } \
       } \
     T2 ## NDArray result (a_dims); \
     for (int i = 0; i < a.length (); i++) \
@@ -760,8 +782,15 @@
     dim_vector b_dims = b.dims (); \
     if (a_dims != b_dims) \
       { \
-        gripe_nonconformant ("operator .^", a_dims, b_dims); \
-        return octave_value (); \
+        if (is_valid_bsxfun (a_dims, b_dims)) \
+          { \
+            return bsxfun_pow (a, b); \
+          } \
+        else \
+          { \
+            gripe_nonconformant ("operator .^", a_dims, b_dims);  \
+            return octave_value (); \
+          } \
       } \
     T1 ## NDArray result (a_dims); \
     for (int i = 0; i < a.length (); i++) \
@@ -779,8 +808,15 @@
     dim_vector b_dims = b.dims (); \
     if (a_dims != b_dims) \
       { \
-        gripe_nonconformant ("operator .^", a_dims, b_dims); \
-        return octave_value (); \
+        if (is_valid_bsxfun (a_dims, b_dims)) \
+          { \
+            return bsxfun_pow (a, b); \
+          } \
+        else \
+          { \
+            gripe_nonconformant ("operator .^", a_dims, b_dims);  \
+            return octave_value (); \
+          } \
       } \
     T2 ## NDArray result (a_dims); \
     for (int i = 0; i < a.length (); i++) \
--- a/src/OPERATORS/op-pm-sm.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/OPERATORS/op-pm-sm.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -32,6 +32,49 @@
 
 #include "ov-perm.h"
 #include "ov-re-sparse.h"
+#include "ov-bool-sparse.h"
+
+// Unary permutation ops, some cast to sparse
+
+//Avoid casting to a full matrix
+DEFUNOP_OP (uplus, perm_matrix, /* no-op */)
+
+// Not calling standard CAST_UNOP_ARG for these next two because a
+// dynamic_cast would fail.
+DEFUNOP (not, perm_matrix)
+{
+  // Obviously negation of a permutation matrix destroys sparsity
+  return octave_value ( ! a.bool_array_value ());
+}
+
+DEFUNOP (uminus, perm_matrix)
+{
+  return octave_value ( - a.sparse_matrix_value ());
+}
+
+// Most other logical operations cast to SparseBoolMatrix
+DEFBINOP (eq_pm, perm_matrix, perm_matrix)
+{
+  CAST_BINOP_ARGS (const octave_perm_matrix&, const octave_perm_matrix&);
+  return v1.sparse_bool_matrix_value () == v2.sparse_bool_matrix_value ();
+}
+DEFBINOP (ne_pm, perm_matrix, perm_matrix)
+{
+  CAST_BINOP_ARGS (const octave_perm_matrix&, const octave_perm_matrix&);
+  return v1.sparse_bool_matrix_value () != v2.sparse_bool_matrix_value ();
+}
+DEFBINOP (el_and_pm, perm_matrix, perm_matrix)
+{
+  CAST_BINOP_ARGS (const octave_perm_matrix&, const octave_perm_matrix&);
+  return mx_el_and(v1.sparse_bool_matrix_value (),
+                   v2.sparse_bool_matrix_value ());
+}
+DEFBINOP (el_or_pm,  perm_matrix, perm_matrix)
+{
+  CAST_BINOP_ARGS (const octave_perm_matrix&, const octave_perm_matrix&);
+  return mx_el_or(v1.sparse_bool_matrix_value (),
+                  v2.sparse_bool_matrix_value ());
+}
 
 // permutation matrix by sparse matrix ops
 
@@ -86,6 +129,11 @@
 void
 install_pm_sm_ops (void)
 {
+  INSTALL_UNOP (op_not, octave_perm_matrix, not);
+  INSTALL_UNOP (op_uplus, octave_perm_matrix, uplus);
+  INSTALL_UNOP (op_uminus, octave_perm_matrix, uminus);
+
+
   INSTALL_BINOP (op_mul, octave_perm_matrix, octave_sparse_matrix,
                  mul_pm_sm);
   INSTALL_BINOP (op_ldiv, octave_perm_matrix, octave_sparse_matrix,
@@ -94,4 +142,9 @@
                  mul_sm_pm);
   INSTALL_BINOP (op_div, octave_sparse_matrix, octave_perm_matrix,
                  div_sm_pm);
+
+  INSTALL_BINOP (op_eq, octave_perm_matrix, octave_perm_matrix, eq_pm);
+  INSTALL_BINOP (op_ne, octave_perm_matrix, octave_perm_matrix, ne_pm);
+  INSTALL_BINOP (op_el_and, octave_perm_matrix, octave_perm_matrix, el_and_pm);
+  INSTALL_BINOP (op_el_or,  octave_perm_matrix, octave_perm_matrix, el_or_pm);
 }
--- a/src/data.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/data.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -1943,6 +1943,9 @@
 %!error <dimension mismatch> cat (3, cat (3, [], []), [1,2;3,4]);
 %!error <dimension mismatch> cat (3, zeros (0, 0, 2), [1,2;3,4]);
 
+%!assert ([zeros(3,2,2); ones(1,2,2)], repmat([0;0;0;1],[1,2,2]) );
+%!assert ([zeros(3,2,2); ones(1,2,2)], vertcat(zeros(3,2,2), ones(1,2,2)) );
+
 */
 
 static octave_value
@@ -4194,8 +4197,8 @@
 @end example\n\
 \n\
 Calling @code{eye} with no arguments is equivalent to calling it\n\
-with an argument of 1.  This odd definition is for compatibility\n\
-with @sc{matlab}.\n\
+with an argument of 1.  Any negative dimensions are treated as zero. \n\
+These odd definitions are for compatibility with @sc{matlab}.\n\
 @seealso{speye}\n\
 @end deftypefn")
 {
--- a/src/defaults.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/defaults.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -419,6 +419,17 @@
   return SET_NONEMPTY_INTERNAL_STRING_VARIABLE (EDITOR);
 }
 
+/*
+%!error (EDITOR (1, 2));
+%!test
+%! orig_val = EDITOR ();
+%! old_val = EDITOR ("X");
+%! assert (orig_val, old_val);
+%! assert (EDITOR (), "X");
+%! EDITOR (orig_val);
+%! assert (EDITOR (), orig_val);
+*/
+
 DEFUN (EXEC_PATH, args, nargout,
   "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {@var{val} =} EXEC_PATH ()\n\
@@ -438,6 +449,17 @@
   return retval;
 }
 
+/*
+%!error (EXEC_PATH (1, 2));
+%!test
+%! orig_val = EXEC_PATH ();
+%! old_val = EXEC_PATH ("X");
+%! assert (orig_val, old_val);
+%! assert (EXEC_PATH (), "X");
+%! EXEC_PATH (orig_val);
+%! assert (EXEC_PATH (), orig_val);
+*/
+
 DEFUN (IMAGE_PATH, args, nargout,
   "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {@var{val} =} IMAGE_PATH ()\n\
@@ -449,6 +471,17 @@
   return SET_NONEMPTY_INTERNAL_STRING_VARIABLE (IMAGE_PATH);
 }
 
+/*
+%!error (IMAGE_PATH (1, 2));
+%!test
+%! orig_val = IMAGE_PATH ();
+%! old_val = IMAGE_PATH ("X");
+%! assert (orig_val, old_val);
+%! assert (IMAGE_PATH (), "X");
+%! IMAGE_PATH (orig_val);
+%! assert (IMAGE_PATH (), orig_val);
+*/
+
 DEFUN (OCTAVE_HOME, args, ,
   "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} OCTAVE_HOME ()\n\
@@ -465,6 +498,11 @@
   return retval;
 }
 
+/*
+%!error OCTAVE_HOME (1);
+%!assert (ischar (OCTAVE_HOME ()));
+*/
+
 DEFUNX ("OCTAVE_VERSION", FOCTAVE_VERSION, args, ,
   "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} OCTAVE_VERSION ()\n\
@@ -482,3 +520,8 @@
 
   return retval;
 }
+
+/*
+%!error OCTAVE_VERSION (1);
+%!assert (ischar (OCTAVE_VERSION ()));
+*/
--- a/src/error.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/error.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -1066,6 +1066,10 @@
 
           octave_scalar_map m = args(0).scalar_map_value ();
 
+          // empty struct is not an error.  return and resume calling function.
+          if (m.nfields () == 0)
+            return retval;
+
           if (m.contains ("message"))
             {
               octave_value c = m.getfield ("message");
@@ -1684,10 +1688,6 @@
   return retval;
 }
 
-// For backward compatibility.
-DEFALIAS (error_text, lasterr);
-DEFALIAS (__error_text__, lasterr);
-
 DEFUN (lastwarn, args, nargout,
   "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {[@var{msg}, @var{msgid}] =} lastwarn (@var{msg}, @var{msgid})\n\
--- a/src/genprops.awk	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/genprops.awk	Tue Sep 20 15:38:24 2011 -0400
@@ -300,8 +300,9 @@
         emit_get_accessor(i, "graphics_handle", "handle_value");
       else if (type[i] == "string_property")
         emit_get_accessor(i, "std::string", "string_value");
-      else if (type[i] == "string_array_property")
-          emit_get_accessor(i, "octave_value", "get");
+      else if (type[i] == "string_array_property" \
+               || type[i] == "text_label_property")
+        emit_get_accessor(i, "octave_value", "get");
       else if (type[i] == "double_property")
         emit_get_accessor(i, "double", "double_value");
       else if (type[i] == "double_radio_property")
--- a/src/gl-render.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/gl-render.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -665,7 +665,7 @@
                                    double p1, double p1N,
                                    double p2, double p2N,
                                    double dx, double dy, double dz,
-                                   int xyz, bool doubleside)
+                                   int xyz, bool mirror)
 {
   glBegin (GL_LINES);
 
@@ -679,7 +679,7 @@
             {
               glVertex3d (val, p1, p2);
               glVertex3d (val, p1+dy, p2+dz);
-              if (doubleside)
+              if (mirror)
                 {
                   glVertex3d (val, p1N, p2N);
                   glVertex3d (val, p1N-dy, p2N-dz);
@@ -689,7 +689,7 @@
             {
               glVertex3d (p1, val, p2);
               glVertex3d (p1+dx, val, p2+dz);
-              if (doubleside)
+              if (mirror)
                 {
                   glVertex3d (p1N, val, p2N);
                   glVertex3d (p1N-dx, val, p2N-dz);
@@ -699,7 +699,7 @@
             {
               glVertex3d (p1, p2, val);
               glVertex3d (p1+dx, p2+dy, val);
-              if (doubleside)
+              if (mirror)
                 {
                   glVertex3d (p1N, p2N, val);
                   glVertex3d (p1N-dx, p2N-dy, val);
@@ -966,7 +966,7 @@
       string_vector xticklabels = props.get_xticklabel ().all_strings ();
       int wmax = 0, hmax = 0;
       bool tick_along_z = nearhoriz || xisinf (fy);
-      bool box = props.is_box ();
+      bool mirror = props.is_box () && xstate != AXE_ANY_DIR;
 
       set_color (props.get_xcolor_rgb ());
 
@@ -982,14 +982,14 @@
           render_tickmarks (xticks, x_min, x_max, ypTick, ypTick,
                             zpTick, zpTickN, 0., 0.,
                             signum(zpTick-zpTickN)*fz*xticklen,
-                            0, (box && xstate != AXE_ANY_DIR));
+                            0, mirror);
         }
       else
         {
           render_tickmarks (xticks, x_min, x_max, ypTick, ypTickN,
                             zpTick, zpTick, 0.,
                             signum(ypTick-ypTickN)*fy*xticklen,
-                            0., 0, (box && xstate != AXE_ANY_DIR));
+                            0., 0, mirror);
         }
 
       // tick texts
@@ -1021,12 +1021,12 @@
             render_tickmarks (xmticks, x_min, x_max, ypTick, ypTick,
                               zpTick, zpTickN, 0., 0.,
                               signum(zpTick-zpTickN)*fz*xticklen/2,
-                              0, (box && xstate != AXE_ANY_DIR));
+                              0, mirror);
           else
             render_tickmarks (xmticks, x_min, x_max, ypTick, ypTickN,
                               zpTick, zpTick, 0.,
                               signum(ypTick-ypTickN)*fy*xticklen/2,
-                              0., 0, (box && xstate != AXE_ANY_DIR));
+                              0., 0, mirror);
         }
 
       gh_manager::get_object (props.get_xlabel ()).set ("visible", "on");
@@ -1073,7 +1073,8 @@
       string_vector yticklabels = props.get_yticklabel ().all_strings ();
       int wmax = 0, hmax = 0;
       bool tick_along_z = nearhoriz || xisinf (fx);
-      bool box = props.is_box ();
+      bool mirror = props.is_box () && ystate != AXE_ANY_DIR
+                    && (props.get_tag () != "plotyy");
 
       set_color (props.get_ycolor_rgb ());
 
@@ -1088,12 +1089,12 @@
         render_tickmarks (yticks, y_min, y_max, xpTick, xpTick,
                           zpTick, zpTickN, 0., 0.,
                           signum(zpTick-zpTickN)*fz*yticklen,
-                          1, (box && ystate != AXE_ANY_DIR));
+                          1, mirror);
       else
         render_tickmarks (yticks, y_min, y_max, xpTick, xpTickN,
                           zpTick, zpTick,
                           signum(xPlaneN-xPlane)*fx*yticklen,
-                          0., 0., 1, (box && ystate != AXE_ANY_DIR));
+                          0., 0., 1, mirror);
 
       // tick texts
       if (yticklabels.numel () > 0)
@@ -1125,12 +1126,12 @@
             render_tickmarks (ymticks, y_min, y_max, xpTick, xpTick,
                               zpTick, zpTickN, 0., 0.,
                               signum(zpTick-zpTickN)*fz*yticklen/2,
-                              1, (box && ystate != AXE_ANY_DIR));
+                              1, mirror);
           else
             render_tickmarks (ymticks, y_min, y_max, xpTick, xpTickN,
                               zpTick, zpTick,
                               signum(xpTick-xpTickN)*fx*yticklen/2,
-                              0., 0., 1, (box && ystate != AXE_ANY_DIR));
+                              0., 0., 1, mirror);
         }
 
       gh_manager::get_object (props.get_ylabel ()).set ("visible", "on");
@@ -1169,7 +1170,7 @@
       Matrix zmticks = xform.zscale (props.get_zmtick ().matrix_value ());
       string_vector zticklabels = props.get_zticklabel ().all_strings ();
       int wmax = 0, hmax = 0;
-      bool box = props.is_box ();
+      bool mirror = props.is_box () && zstate != AXE_ANY_DIR;
 
       set_color (props.get_zcolor_rgb ());
 
@@ -1185,7 +1186,7 @@
             render_tickmarks (zticks, z_min, z_max, xPlaneN, xPlane,
                               yPlane, yPlane,
                               signum(xPlaneN-xPlane)*fx*zticklen,
-                              0., 0., 2, (box && zstate != AXE_ANY_DIR));
+                              0., 0., 2, mirror);
           else
             render_tickmarks (zticks, z_min, z_max, xPlaneN, xPlaneN,
                               yPlane, yPlane, 0.,
@@ -1198,7 +1199,7 @@
             render_tickmarks (zticks, z_min, z_max, xPlaneN, xPlane,
                               yPlaneN, yPlane, 0.,
                               signum(yPlaneN-yPlane)*fy*zticklen,
-                              0., 2, (box && zstate != AXE_ANY_DIR));
+                              0., 2, mirror);
           else
             render_tickmarks (zticks, z_min, z_max, xPlane, xPlane,
                               yPlaneN, yPlane,
@@ -1250,7 +1251,7 @@
                 render_tickmarks (zmticks, z_min, z_max, xPlaneN, xPlane,
                                   yPlane, yPlane,
                                   signum(xPlaneN-xPlane)*fx*zticklen/2,
-                                  0., 0., 2, (box && zstate != AXE_ANY_DIR));
+                                  0., 0., 2, mirror);
               else
                 render_tickmarks (zmticks, z_min, z_max, xPlaneN, xPlaneN,
                                   yPlane, yPlane, 0.,
@@ -1263,13 +1264,13 @@
                 render_tickmarks (zmticks, z_min, z_max, xPlane, xPlane,
                                   yPlaneN, yPlane, 0.,
                                   signum(yPlaneN-yPlane)*fy*zticklen/2,
-                                  0., 2, (box && zstate != AXE_ANY_DIR));
+                                  0., 2, mirror);
               else
                 render_tickmarks (zmticks, z_min, z_max, xPlane, xPlane,
                                   yPlaneN, yPlaneN,
                                   signum(xPlane-xPlaneN)*fx*zticklen/2,
                                   0., 0., 2, false);
-            }            
+            }
         }
 
       gh_manager::get_object (props.get_zlabel ()).set ("visible", "on");
@@ -2373,7 +2374,7 @@
             {
               if (c.numel () == 0)
                 c = props.get_color_data ().matrix_value ();
-              has_markerfacecolor = ((c.numel () > 0) 
+              has_markerfacecolor = ((c.numel () > 0)
                                     && (c.rows () == f.rows ()));
             }
         }
@@ -2421,7 +2422,7 @@
 void
 opengl_renderer::draw_text (const text::properties& props)
 {
-  if (props.get_string ().empty ())
+  if (props.get_string ().is_empty ())
     return;
 
   const Matrix pos = xform.scale (props.get_data_position ());
--- a/src/gl2ps-renderer.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/gl2ps-renderer.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -199,7 +199,7 @@
 void
 glps_renderer::draw_text (const text::properties& props)
 {
-  if (props.get_string ().empty ())
+  if (props.get_string ().is_empty ())
     return;
 
   set_font (props);
@@ -223,9 +223,15 @@
   // FIXME: handle margin and surrounding box
 
   glRasterPos3d (pos(0), pos(1), pos(2));
-  gl2psTextOpt (props.get_string ().c_str (), fontname.c_str (), fontsize,
+
+  octave_value string_prop = props.get_string ();
+
+  string_vector sv = string_prop.all_strings ();
+
+  std::string s = sv.join ("\n");
+
+  gl2psTextOpt (s.c_str (), fontname.c_str (), fontsize,
                 alignment_to_mode (halign, valign), props.get_rotation ());
-
 }
 
 #endif
--- a/src/gl2ps.c	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/gl2ps.c	Tue Sep 20 15:38:24 2011 -0400
@@ -1,6 +1,6 @@
 /*
  * GL2PS, an OpenGL to PostScript Printing Library
- * Copyright (C) 1999-2009 C. Geuzaine
+ * Copyright (C) 1999-2011 C. Geuzaine
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of either:
@@ -305,10 +305,12 @@
 
 static void *gl2psRealloc(void *ptr, size_t size)
 {
+  void *orig = ptr;
   if(!size) return NULL;
-  ptr = realloc(ptr, size);
+  ptr = realloc(orig, size);
   if(!ptr){
     gl2psMsg(GL2PS_ERROR, "Couldn't reallocate requested memory");
+    free(orig);
     return NULL;
   }
   return ptr;
@@ -320,12 +322,12 @@
   free(ptr);
 }
 
-static size_t gl2psWriteBigEndian(unsigned long data, size_t bytes)
-{
-  size_t i;
-  size_t size = sizeof(unsigned long);
+static int gl2psWriteBigEndian(unsigned long data, int bytes)
+{
+  int i;
+  int size = sizeof(unsigned long);
   for(i = 1; i <= bytes; ++i){
-    fputc(0xff & (data >> (size-i) * 8), gl2ps->stream);
+    fputc(0xff & (data >> (size - i) * 8), gl2ps->stream);
   }
   return bytes;
 }
@@ -392,10 +394,10 @@
   return gl2ps->compress->start;
 }
 
-static size_t gl2psWriteBigEndianCompress(unsigned long data, size_t bytes)
-{
-  size_t i;
-  size_t size = sizeof(unsigned long);
+static int gl2psWriteBigEndianCompress(unsigned long data, int bytes)
+{
+  int i;
+  int size = sizeof(unsigned long);
   for(i = 1; i <= bytes; ++i){
     *gl2ps->compress->src = (Bytef)(0xff & (data >> (size-i) * 8));
     ++gl2ps->compress->src;
@@ -441,7 +443,7 @@
   return ret;
 }
 
-static void gl2psPrintGzipHeader()
+static void gl2psPrintGzipHeader(void)
 {
 #if defined(GL2PS_HAVE_ZLIB)
   char tmp[10] = {'\x1f', '\x8b', /* magic numbers: 0x1f, 0x8b */
@@ -459,7 +461,7 @@
 #endif
 }
 
-static void gl2psPrintGzipFooter()
+static void gl2psPrintGzipFooter(void)
 {
 #if defined(GL2PS_HAVE_ZLIB)
   int n;
@@ -789,6 +791,7 @@
 
 static void gl2psUserFlushPNG(png_structp png_ptr)
 {
+  (void) png_ptr;  /* not used */
 }
 
 static void gl2psConvertPixmapToPNG(GL2PSimage *pixmap, GL2PSlist *png)
@@ -1358,17 +1361,17 @@
   (*t2)->verts[0] = quad->verts[0];
   (*t2)->verts[1] = quad->verts[2];
   (*t2)->verts[2] = quad->verts[3];
-  (*t2)->boundary = ((quad->boundary & 4) ? 2 : 0) | ((quad->boundary & 4) ? 2 : 0);
+  (*t2)->boundary = ((quad->boundary & 4) ? 2 : 0) | ((quad->boundary & 8) ? 4 : 0);
 }
 
 static int gl2psCompareDepth(const void *a, const void *b)
 {
-  GL2PSprimitive *q, *w;
+  const GL2PSprimitive *q, *w;
   GLfloat dq = 0.0F, dw = 0.0F, diff;
   int i;
 
-  q = *(GL2PSprimitive**)a;
-  w = *(GL2PSprimitive**)b;
+  q = *(const GL2PSprimitive* const*)a;
+  w = *(const GL2PSprimitive* const*)b;
 
   for(i = 0; i < q->numverts; i++){
     dq += q->verts[i].xyz[2];
@@ -1394,10 +1397,10 @@
 
 static int gl2psTrianglesFirst(const void *a, const void *b)
 {
-  GL2PSprimitive *q, *w;
-
-  q = *(GL2PSprimitive**)a;
-  w = *(GL2PSprimitive**)b;
+  const GL2PSprimitive *q, *w;
+
+  q = *(const GL2PSprimitive* const*)a;
+  w = *(const GL2PSprimitive* const*)b;
   return (q->type < w->type ? 1 : -1);
 }
 
@@ -1614,7 +1617,7 @@
   }
 }
 
-static void gl2psRescaleAndOffset()
+static void gl2psRescaleAndOffset(void)
 {
   GL2PSprimitive *prim;
   GLfloat minZ, maxZ, rangeZ, scaleZ;
@@ -3201,7 +3204,7 @@
   int i;
 
   if(gl2ps->filename && strlen(gl2ps->filename) < 256){
-    for(i = strlen(gl2ps->filename)-1; i >= 0; i--){
+    for(i = (int)strlen(gl2ps->filename) - 1; i >= 0; i--){
       if(gl2ps->filename[i] == '.'){
         strncpy(name, gl2ps->filename, i);
         name[i] = '\0';
@@ -3306,6 +3309,7 @@
 
 static void gl2psPrintTeXBeginViewport(GLint viewport[4])
 {
+  (void) viewport;  /* not used */
   glRenderMode(GL_FEEDBACK);
 
   if(gl2ps->header){
@@ -3409,7 +3413,7 @@
        cnt, text->fontsize, x, y, text->str);
   }
   else{
-    rad = (GLfloat)M_PI * text->angle / 180.0F;
+    rad = (GLfloat)(M_PI * text->angle / 180.0F);
     srad = (GLfloat)sin(rad);
     crad = (GLfloat)cos(rad);
     gl2ps->streamlength += gl2psPrintf
@@ -4170,8 +4174,7 @@
 /* Put vertex' edge flag (8bit) and coordinates (32bit) in shader stream */
 
 static int gl2psPrintPDFShaderStreamDataCoord(GL2PSvertex *vertex,
-                                              size_t (*action)(unsigned long data,
-                                                               size_t size),
+                                              int (*action)(unsigned long data, int size),
                                               GLfloat dx, GLfloat dy,
                                               GLfloat xmin, GLfloat ymin)
 {
@@ -4217,8 +4220,7 @@
 /* Put vertex' rgb value (8bit for every component) in shader stream */
 
 static int gl2psPrintPDFShaderStreamDataRGB(GL2PSvertex *vertex,
-                                            size_t (*action)(unsigned long data,
-                                                             size_t size))
+                                            int (*action)(unsigned long data, int size))
 {
   int offs = 0;
   unsigned long imap;
@@ -4242,8 +4244,7 @@
 /* Put vertex' alpha (8/16bit) in shader stream */
 
 static int gl2psPrintPDFShaderStreamDataAlpha(GL2PSvertex *vertex,
-                                              size_t (*action)(unsigned long data,
-                                                               size_t size),
+                                              int (*action)(unsigned long data, int size),
                                               int sigbyte)
 {
   int offs = 0;
@@ -4270,8 +4271,7 @@
 static int gl2psPrintPDFShaderStreamData(GL2PStriangle *triangle,
                                          GLfloat dx, GLfloat dy,
                                          GLfloat xmin, GLfloat ymin,
-                                         size_t (*action)(unsigned long data,
-                                                          size_t size),
+                                         int (*action)(unsigned long data, int size),
                                          int gray)
 {
   int i, offs = 0;
@@ -4489,8 +4489,7 @@
 /* Similar groups of functions for pixmaps and text */
 
 static int gl2psPrintPDFPixmapStreamData(GL2PSimage *im,
-                                         size_t (*action)(unsigned long data,
-                                                          size_t size),
+                                         int (*action)(unsigned long data, int size),
                                          int gray)
 {
   int x, y, shift;
@@ -5031,6 +5030,7 @@
   gl2psPrintf("\"/>\n");
   gl2psListDelete(png);
 #else
+  (void) x; (void) y; (void) pixmap;  /* not used */
   gl2psMsg(GL2PS_WARNING, "GL2PS must be compiled with PNG support in "
            "order to embed images in SVG streams");
 #endif
@@ -5842,7 +5842,8 @@
                                    const void *pixels)
 {
   int size, i;
-  GLfloat pos[4], *piv, zoom_x, zoom_y;
+  const GLfloat *piv;
+  GLfloat pos[4], zoom_x, zoom_y;
   GL2PSprimitive *prim;
   GLboolean valid;
 
@@ -5894,7 +5895,7 @@
       prim->data.image->format = GL_RGB;
       size = height * width * 3;
       prim->data.image->pixels = (GLfloat*)gl2psMalloc(size * sizeof(GLfloat));
-      piv = (GLfloat*)pixels;
+      piv = (const GLfloat*)pixels;
       for(i = 0; i < size; ++i, ++piv){
         prim->data.image->pixels[i] = *piv;
         if(!((i + 1) % 3))
@@ -5939,7 +5940,7 @@
   glPassThrough((GLfloat)width);
   glPassThrough((GLfloat)height);
   for(i = 0; i < size; i += sizeoffloat){
-    float *value = (float*)imagemap;
+    const float *value = (const float*)imagemap;
     glPassThrough(*value);
     imagemap += sizeoffloat;
   }
--- a/src/gl2ps.h	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/gl2ps.h	Tue Sep 20 15:38:24 2011 -0400
@@ -1,6 +1,6 @@
 /*
  * GL2PS, an OpenGL to PostScript Printing Library
- * Copyright (C) 1999-2009 C. Geuzaine
+ * Copyright (C) 1999-2011 C. Geuzaine
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of either:
@@ -80,14 +80,14 @@
 
 #define GL2PS_MAJOR_VERSION 1
 #define GL2PS_MINOR_VERSION 3
-#define GL2PS_PATCH_VERSION 5
+#define GL2PS_PATCH_VERSION 6
 #define GL2PS_EXTRA_VERSION ""
 
 #define GL2PS_VERSION (GL2PS_MAJOR_VERSION + \
                        0.01 * GL2PS_MINOR_VERSION + \
                        0.0001 * GL2PS_PATCH_VERSION)
 
-#define GL2PS_COPYRIGHT "(C) 1999-2009 C. Geuzaine"
+#define GL2PS_COPYRIGHT "(C) 1999-2011 C. Geuzaine"
 
 /* Output file formats (the values and the ordering are important!) */
 
--- a/src/graphics.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/graphics.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -657,7 +657,7 @@
 template<class T>
 static void
 get_array_limits (const Array<T>& m, double& emin, double& emax,
-                  double& eminp)
+                  double& eminp, double& emaxp)
 {
   const T *data = m.data ();
   octave_idx_type n = m.numel ();
@@ -677,6 +677,9 @@
 
           if (e > 0 && e < eminp)
             eminp = e;
+
+          if (e < 0 && e > emaxp)
+            emaxp = e;
         }
     }
 }
@@ -1130,31 +1133,31 @@
 array_property::get_data_limits (void)
 {
   xmin = xminp = octave_Inf;
-  xmax = -octave_Inf;
+  xmax = xmaxp = -octave_Inf;
 
   if (! data.is_empty ())
     {
       if (data.is_integer_type ())
         {
           if (data.is_int8_type ())
-            get_array_limits (data.int8_array_value (), xmin, xmax, xminp);
+            get_array_limits (data.int8_array_value (), xmin, xmax, xminp, xmaxp);
           else if (data.is_uint8_type ())
-            get_array_limits (data.uint8_array_value (), xmin, xmax, xminp);
+            get_array_limits (data.uint8_array_value (), xmin, xmax, xminp, xmaxp);
           else if (data.is_int16_type ())
-            get_array_limits (data.int16_array_value (), xmin, xmax, xminp);
+            get_array_limits (data.int16_array_value (), xmin, xmax, xminp, xmaxp);
           else if (data.is_uint16_type ())
-            get_array_limits (data.uint16_array_value (), xmin, xmax, xminp);
+            get_array_limits (data.uint16_array_value (), xmin, xmax, xminp, xmaxp);
           else if (data.is_int32_type ())
-            get_array_limits (data.int32_array_value (), xmin, xmax, xminp);
+            get_array_limits (data.int32_array_value (), xmin, xmax, xminp, xmaxp);
           else if (data.is_uint32_type ())
-            get_array_limits (data.uint32_array_value (), xmin, xmax, xminp);
+            get_array_limits (data.uint32_array_value (), xmin, xmax, xminp, xmaxp);
           else if (data.is_int64_type ())
-            get_array_limits (data.int64_array_value (), xmin, xmax, xminp);
+            get_array_limits (data.int64_array_value (), xmin, xmax, xminp, xmaxp);
           else if (data.is_uint64_type ())
-            get_array_limits (data.uint64_array_value (), xmin, xmax, xminp);
+            get_array_limits (data.uint64_array_value (), xmin, xmax, xminp, xmaxp);
         }
       else
-        get_array_limits (data.array_value (), xmin, xmax, xminp);
+        get_array_limits (data.array_value (), xmin, xmax, xminp, xmaxp);
     }
 }
 
@@ -3172,6 +3175,7 @@
   ticklength.add_constraint (dim_vector (1, 2));
   tightinset.add_constraint (dim_vector (1, 4));
   looseinset.add_constraint (dim_vector (1, 4));
+  update_font ();
 
   x_zlim.resize (1, 2);
 
@@ -3263,13 +3267,119 @@
 void
 axes::properties::sync_positions (void)
 {
+  Matrix ref_linset = looseinset.get ().matrix_value ();
+  if (autopos_tag_is ("subplot"))
+    {
+      graphics_object parent_obj = gh_manager::get_object (get_parent ());
+      if (parent_obj.isa ("figure"))
+        {
+           // FIXME: temporarily changed units should be protected
+           //        from interrupts
+           std::string fig_units = parent_obj.get ("units").string_value ();
+           parent_obj.set ("units", "pixels");
+
+           Matrix ref_outbox = outerposition.get ().matrix_value ();
+           ref_outbox(2) += ref_outbox(0);
+           ref_outbox(3) += ref_outbox(1);
+
+           // Find those subplots that are left, right, bottom and top aligned
+           // with the current subplot
+           Matrix kids = parent_obj.get_properties ().get_children ();
+           std::vector<octave_value> aligned;
+           std::vector<bool> l_aligned, b_aligned, r_aligned, t_aligned;
+           for (octave_idx_type i = 0; i < kids.numel (); i++)
+             {
+               graphics_object go = gh_manager::get_object (kids(i));
+               if (go.isa ("axes"))
+                 {
+                   axes::properties& props =
+                     dynamic_cast<axes::properties&> (go.get_properties ());
+                   if (props.autopos_tag_is("subplot"))
+                     {
+                       Matrix outpos = go.get ("outerposition").matrix_value ();
+                       bool l_align=(std::abs (outpos(0)-ref_outbox(0)) < 1e-15);
+                       bool b_align=(std::abs (outpos(1)-ref_outbox(1)) < 1e-15);
+                       bool r_align=(std::abs (outpos(0)+outpos(2)-ref_outbox(2)) < 1e-15);
+                       bool t_align=(std::abs (outpos(1)+outpos(3)-ref_outbox(3)) < 1e-15);
+                       if (l_align || b_align || r_align || t_align)
+                         {
+                           aligned.push_back(kids(i));
+                           l_aligned.push_back(l_align);
+                           b_aligned.push_back(b_align);
+                           r_aligned.push_back(r_align);
+                           t_aligned.push_back(t_align);
+                           // FIXME: the temporarily deleted tags should be
+                           //        protected from interrupts
+                           props.set_autopos_tag ("none");
+                         }
+                     }
+                 }
+             }
+           // Determine a minimum box which aligns the subplots
+           Matrix ref_box(1, 4, 0.);
+           ref_box(2) = 1.;
+           ref_box(3) = 1.;
+           for (size_t i = 0; i < aligned.size (); i++)
+             {
+               graphics_object go = gh_manager::get_object (aligned[i]);
+               axes::properties& props =
+                 dynamic_cast<axes::properties&> (go.get_properties ());
+               Matrix linset = props.get_looseinset ().matrix_value ();
+               if (l_aligned[i])
+                 linset(0) = std::min (0., linset(0)-0.01);
+               if (b_aligned[i])
+                 linset(1) = std::min (0., linset(1)-0.01);
+               if (r_aligned[i])
+                 linset(2) = std::min (0., linset(2)-0.01);
+               if (t_aligned[i])
+                 linset(3) = std::min (0., linset(3)-0.01);
+               props.set_looseinset (linset);
+               Matrix pos = props.get_position ().matrix_value ();
+               if (l_aligned[i])
+                 ref_box(0) = std::max (ref_box(0), pos(0));
+               if (b_aligned[i])
+                 ref_box(1) = std::max (ref_box(1), pos(1));
+               if (r_aligned[i])
+                 ref_box(2) = std::min (ref_box(2), pos(0)+pos(2));
+               if (t_aligned[i])
+                 ref_box(3) = std::min (ref_box(3), pos(1)+pos(3));
+             }
+           // Set common looseinset values for all aligned subplots and
+           // revert their tag values
+           for (size_t i = 0; i < aligned.size (); i++)
+             {
+               graphics_object go = gh_manager::get_object (aligned[i]);
+               axes::properties& props =
+                 dynamic_cast<axes::properties&> (go.get_properties ());
+               Matrix outpos = props.get_outerposition ().matrix_value ();
+               Matrix linset = props.get_looseinset ().matrix_value ();
+               if (l_aligned[i])
+                 linset(0) = (ref_box(0)-outpos(0))/outpos(2);
+               if (b_aligned[i])
+                 linset(1) = (ref_box(1)-outpos(1))/outpos(3);
+               if (r_aligned[i])
+                 linset(2) = (outpos(0)+outpos(2)-ref_box(2))/outpos(2);
+               if (t_aligned[i])
+                 linset(3) = (outpos(1)+outpos(3)-ref_box(3))/outpos(3);
+               props.set_looseinset (linset);
+               props.set_autopos_tag ("subplot");
+             }
+           parent_obj.set ("units", fig_units);
+        }
+    }
+  else
+    sync_positions (ref_linset);
+}
+
+void
+axes::properties::sync_positions (const Matrix& linset)
+{
   Matrix pos = position.get ().matrix_value ();
   Matrix outpos = outerposition.get ().matrix_value ();
-  Matrix lins = looseinset.get ().matrix_value ();
-  double lratio = lins(0);
-  double bratio = lins(1);
-  double wratio = 1-lins(0)-lins(2);
-  double hratio = 1-lins(1)-lins(3);
+  double lratio = linset(0);
+  double bratio = linset(1);
+  double wratio = 1-linset(0)-linset(2);
+  double hratio = 1-linset(1)-linset(3);
   if (activepositionproperty.is ("outerposition"))
     {
       pos = outpos;
@@ -3286,7 +3396,7 @@
       double thrshldy = 0.005*outpos(3);
       double minsizex = 0.2*outpos(2);
       double minsizey = 0.2*outpos(3);
-      bool updatex = true, updatey = true; 
+      bool updatex = true, updatey = true;
       for (int i = 0; i < 10; i++)
         {
           double dt;
@@ -3359,7 +3469,7 @@
   inset(1) = pos(1)-outpos(1);
   inset(2) = outpos(0)+outpos(2)-pos(0)-pos(2);
   inset(3) = outpos(1)+outpos(3)-pos(1)-pos(3);
-  
+
   tightinset = inset;
 }
 
@@ -4223,15 +4333,22 @@
   update_title_position ();
 }
 
+static bool updating_xlabel_position = false;
+
 void
 axes::properties::update_xlabel_position (void)
 {
+  if (updating_xlabel_position)
+    return;
+
   text::properties& xlabel_props = reinterpret_cast<text::properties&>
     (gh_manager::get_object (get_xlabel ()).get_properties ());
 
-  bool is_empty = xlabel_props.get_string ().empty ();
-
-  xlabel_props.set_autopos_tag ("none");
+  bool is_empty = xlabel_props.get_string ().is_empty ();
+
+  unwind_protect frame;
+  frame.protect_var (updating_xlabel_position);
+  updating_xlabel_position = true;
 
   if (! is_empty)
     {
@@ -4305,19 +4422,24 @@
           xlabel_props.set_rotationmode ("auto");
         }
     }
-
-  xlabel_props.set_autopos_tag ("xlabel");
-}
+}
+
+static bool updating_ylabel_position = false;
 
 void
 axes::properties::update_ylabel_position (void)
 {
+  if (updating_ylabel_position)
+    return;
+
   text::properties& ylabel_props = reinterpret_cast<text::properties&>
     (gh_manager::get_object (get_ylabel ()).get_properties ());
 
-  bool is_empty = ylabel_props.get_string ().empty ();
-
-  ylabel_props.set_autopos_tag ("none");
+  bool is_empty = ylabel_props.get_string ().is_empty ();
+
+  unwind_protect frame;
+  frame.protect_var (updating_ylabel_position);
+  updating_ylabel_position = true;
 
   if (! is_empty)
     {
@@ -4391,20 +4513,25 @@
           ylabel_props.set_rotationmode ("auto");
         }
     }
-
-  ylabel_props.set_autopos_tag ("ylabel");
-}
+}
+
+static bool updating_zlabel_position = false;
 
 void
 axes::properties::update_zlabel_position (void)
 {
+  if (updating_zlabel_position)
+    return;
+
   text::properties& zlabel_props = reinterpret_cast<text::properties&>
     (gh_manager::get_object (get_zlabel ()).get_properties ());
 
   bool camAuto = cameraupvectormode_is ("auto");
-  bool is_empty = zlabel_props.get_string ().empty ();
-
-  zlabel_props.set_autopos_tag ("none");
+  bool is_empty = zlabel_props.get_string ().is_empty ();
+
+  unwind_protect frame;
+  frame.protect_var (updating_zlabel_position);
+  updating_zlabel_position = true;
 
   if (! is_empty)
     {
@@ -4499,17 +4626,22 @@
           zlabel_props.set_rotationmode ("auto");
         }
     }
-
-  zlabel_props.set_autopos_tag ("zlabel");
-}
+}
+
+static bool updating_title_position = false;
 
 void
 axes::properties::update_title_position (void)
 {
+  if (updating_title_position)
+    return;
+
   text::properties& title_props = reinterpret_cast<text::properties&>
     (gh_manager::get_object (get_title ()).get_properties ());
 
-  title_props.set_autopos_tag ("none");
+  unwind_protect frame;
+  frame.protect_var (updating_title_position);
+  updating_title_position = true;
 
   if (title_props.positionmode_is ("auto"))
     {
@@ -4523,8 +4655,6 @@
       title_props.set_position (p.extract_n(0, 3).transpose ());
       title_props.set_positionmode ("auto");
     }
-
-  title_props.set_autopos_tag ("title");
 }
 
 void
@@ -4566,7 +4696,8 @@
       double minval = octave_Inf;
       double maxval = -octave_Inf;
       double min_pos = octave_Inf;
-      get_children_limits (minval, maxval, min_pos, kids, limit_type);
+      double max_neg = -octave_Inf;
+      get_children_limits (minval, maxval, min_pos, max_neg, kids, limit_type);
       if (!xisinf (minval) && !xisnan (minval)
           && !xisinf (maxval) && !xisnan (maxval))
         {
@@ -4693,6 +4824,19 @@
     }
 }
 
+void
+axes::properties::update_font (void)
+{
+#ifdef HAVE_FREETYPE
+#ifdef HAVE_FONTCONFIG
+  text_renderer.set_font (get ("fontname").string_value (),
+                          get ("fontweight").string_value (),
+                          get ("fontangle").string_value (),
+                          get ("fontsize").double_value ());
+#endif
+#endif
+}
+
 // The INTERNAL flag defines whether position or outerposition is used.
 
 Matrix
@@ -4756,7 +4900,7 @@
 
           Matrix text_pos = text_props.get_position ().matrix_value ();
           text_pos = xform.transform (text_pos(0), text_pos(1), text_pos(2));
-          if (text_props.get_string ().empty ())
+          if (text_props.get_string ().is_empty ())
             {
               ext(0) = std::min (ext(0), text_pos(0));
               ext(1) = std::min (ext(1), text_pos(1));
@@ -4795,7 +4939,7 @@
 
   ext(2) = ext(2)-ext(0);
   ext(3) = ext(3)-ext(1);
-  
+
   return ext;
 }
 
@@ -4929,7 +5073,8 @@
 // FIXME -- maybe this should go into array_property class?
 /*
 static void
-check_limit_vals (double& min_val, double& max_val, double& min_pos,
+check_limit_vals (double& min_val, double& max_val,
+                  double& min_pos, double& max_neg,
                   const array_property& data)
 {
   double val = data.min_val ();
@@ -4941,18 +5086,22 @@
   val = data.min_pos ();
   if (! (xisinf (val) || xisnan (val)) && val > 0 && val < min_pos)
     min_pos = val;
+  val = data.max_neg ();
+  if (! (xisinf (val) || xisnan (val)) && val < 0 && val > max_neg)
+    max_neg = val;
 }
 */
 
 static void
-check_limit_vals (double& min_val, double& max_val, double& min_pos,
+check_limit_vals (double& min_val, double& max_val,
+                  double& min_pos, double& max_neg,
                   const octave_value& data)
 {
   if (data.is_matrix_type ())
     {
       Matrix m = data.matrix_value ();
 
-      if (! error_state && m.numel () == 3)
+      if (! error_state && m.numel () == 4)
         {
           double val;
 
@@ -4967,6 +5116,10 @@
           val = m(2);
           if (! (xisinf (val) || xisnan (val)) && val > 0 && val < min_pos)
             min_pos = val;
+
+          val = m(3);
+          if (! (xisinf (val) || xisnan (val)) && val < 0 && val > max_neg)
+            max_neg = val;
         }
     }
 }
@@ -4984,8 +5137,8 @@
     }
   else
     {
-      b = static_cast<int> (gnulib::floor (std::log10 (std::abs (x)))); 
-      a = x / std::pow (10.0, b); 
+      b = static_cast<int> (gnulib::floor (std::log10 (std::abs (x))));
+      a = x / std::pow (10.0, b);
     }
 }
 
@@ -5031,7 +5184,8 @@
 
 Matrix
 axes::properties::get_axis_limits (double xmin, double xmax,
-                                   double min_pos, bool logscale)
+                                   double min_pos, double max_neg,
+                                   bool logscale)
 {
   Matrix retval;
 
@@ -5042,13 +5196,17 @@
     {
       if (logscale)
         {
-          if (xisinf (min_pos))
+          if (xisinf (min_pos) && xisinf (max_neg))
             {
-              // warning ("axis: logscale with no positive values to plot");
+              // TODO -- max_neg is needed for "loglog ([0 -Inf])"
+              //         This is the only place where max_neg is needed.
+              //         Is there another way?
+              retval = default_lim ();
+              retval(0) = pow (10., retval(0));
+              retval(1) = pow (10., retval(1));
               return retval;
             }
-
-          if (min_val <= 0)
+          if ((min_val <= 0 && max_val >= 0))
             {
               warning ("axis: omitting nonpositive data in log plot");
               min_val = min_pos;
@@ -5059,8 +5217,18 @@
               min_val *= 0.9;
               max_val *= 1.1;
             }
-          min_val = pow (10, gnulib::floor (log10 (min_val)));
-          max_val = pow (10, std::ceil (log10 (max_val)));
+          if (min_val > 0)
+            {
+              // Log plots with all positive data
+              min_val = pow (10, gnulib::floor (log10 (min_val)));
+              max_val = pow (10, std::ceil (log10 (max_val)));
+            }
+          else
+            {
+              // Log plots with all negative data
+              min_val = -pow (10, gnulib::floor (log10 (-min_val)));
+              max_val = -pow (10, std::ceil (log10 (-max_val)));
+            }
         }
       else
         {
@@ -5106,19 +5274,29 @@
 
   double lo = (lims.get ().matrix_value ()) (0);
   double hi = (lims.get ().matrix_value ()) (1);
+  bool is_negative = lo < 0 && hi < 0;
+  double tmp;
   // FIXME should this be checked for somewhere else? (i.e. set{x,y,z}lim)
   if (hi < lo)
     {
-      double tmp = hi;
+      tmp = hi;
       hi = lo;
       lo = tmp;
     }
 
   if (is_logscale)
     {
-      // FIXME we should check for negtives here
-      hi = std::log10 (hi);
-      lo = std::log10 (lo);
+      if (is_negative)
+        {
+          tmp = hi;
+          hi = std::log10 (-lo);
+          lo = std::log10 (-tmp);
+        }
+      else
+        {
+          hi = std::log10 (hi);
+          lo = std::log10 (lo);
+        }
     }
 
   double tick_sep = calc_tick_sep (lo , hi);
@@ -5147,6 +5325,12 @@
           tmp_lims(1) = std::pow (10.,tmp_lims(1));
           if (tmp_lims(0) <= 0)
             tmp_lims(0) = std::pow (10., lo);
+          if (is_negative)
+            {
+              tmp = tmp_lims(0);
+              tmp_lims(0) = -tmp_lims(1);
+              tmp_lims(1) = -tmp;
+            }
         }
       lims = tmp_lims;
     }
@@ -5164,6 +5348,13 @@
       if (is_logscale)
         tmp_ticks (i) = std::pow (10., tmp_ticks (i));
     }
+  if (is_logscale && is_negative)
+    {
+      Matrix rev_ticks (1, i2-i1+1);
+      rev_ticks = -tmp_ticks;
+      for (int i = 0; i <= i2-i1; i++)
+        tmp_ticks (i) = rev_ticks (i2-i1-i);
+    }
 
   ticks = tmp_ticks;
 
@@ -5204,14 +5395,7 @@
                                          const string_vector& ticklabels,
                                          const Matrix& limits)
 {
-#ifdef HAVE_FREETYPE
-  //FIXME: text_renderer could be cached
-  ft_render text_renderer;
-  text_renderer.set_font (get ("fontname").string_value (),
-                          get ("fontweight").string_value (),
-                          get ("fontangle").string_value (),
-                          get ("fontsize").double_value ());
-#else
+#ifndef HAVE_FREETYPE
   double fontsize = get ("fontsize").double_value ();
 #endif
 
@@ -5242,7 +5426,8 @@
 }
 
 void
-get_children_limits (double& min_val, double& max_val, double& min_pos,
+get_children_limits (double& min_val, double& max_val,
+                     double& min_pos, double& max_neg,
                      const Matrix& kids, char limit_type)
 {
   octave_idx_type n = kids.numel ();
@@ -5258,7 +5443,7 @@
             {
               octave_value lim = obj.get_xlim ();
 
-              check_limit_vals (min_val, max_val, min_pos, lim);
+              check_limit_vals (min_val, max_val, min_pos, max_neg, lim);
             }
         }
       break;
@@ -5272,7 +5457,7 @@
             {
               octave_value lim = obj.get_ylim ();
 
-              check_limit_vals (min_val, max_val, min_pos, lim);
+              check_limit_vals (min_val, max_val, min_pos, max_neg, lim);
             }
         }
       break;
@@ -5286,7 +5471,7 @@
             {
               octave_value lim = obj.get_zlim ();
 
-              check_limit_vals (min_val, max_val, min_pos, lim);
+              check_limit_vals (min_val, max_val, min_pos, max_neg, lim);
             }
         }
       break;
@@ -5300,7 +5485,7 @@
             {
               octave_value lim = obj.get_clim ();
 
-              check_limit_vals (min_val, max_val, min_pos, lim);
+              check_limit_vals (min_val, max_val, min_pos, max_neg, lim);
             }
         }
       break;
@@ -5314,7 +5499,7 @@
             {
               octave_value lim = obj.get_alim ();
 
-              check_limit_vals (min_val, max_val, min_pos, lim);
+              check_limit_vals (min_val, max_val, min_pos, max_neg, lim);
             }
         }
       break;
@@ -5338,6 +5523,7 @@
   double min_val = octave_Inf;
   double max_val = -octave_Inf;
   double min_pos = octave_Inf;
+  double max_neg = -octave_Inf;
 
   char update_type = 0;
 
@@ -5345,7 +5531,7 @@
   double val;
 
 #define FIX_LIMITS \
-  if (limits.numel() == 3) \
+  if (limits.numel() == 4) \
     { \
       val = limits(0); \
       if (! (xisinf (val) || xisnan (val))) \
@@ -5356,13 +5542,17 @@
       val = limits(2); \
       if (! (xisinf (val) || xisnan (val))) \
         min_pos = val; \
+      val = limits(3); \
+      if (! (xisinf (val) || xisnan (val))) \
+        max_neg = val; \
     } \
   else \
     { \
-      limits.resize(3, 1); \
+      limits.resize(4, 1); \
       limits(0) = min_val; \
       limits(1) = max_val; \
       limits(2) = min_pos; \
+      limits(3) = max_neg; \
     }
 
   if (axis_type == "xdata" || axis_type == "xscale"
@@ -5374,9 +5564,10 @@
           limits = xproperties.get_xlim ().matrix_value ();
           FIX_LIMITS ;
 
-          get_children_limits (min_val, max_val, min_pos, kids, 'x');
-
-          limits = xproperties.get_axis_limits (min_val, max_val, min_pos,
+          get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'x');
+
+          limits = xproperties.get_axis_limits (min_val, max_val,
+                                                min_pos, max_neg,
                                                 xproperties.xscale_is ("log"));
 
           update_type = 'x';
@@ -5391,9 +5582,10 @@
           limits = xproperties.get_ylim ().matrix_value ();
           FIX_LIMITS ;
 
-          get_children_limits (min_val, max_val, min_pos, kids, 'y');
-
-          limits = xproperties.get_axis_limits (min_val, max_val, min_pos,
+          get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'y');
+
+          limits = xproperties.get_axis_limits (min_val, max_val,
+                                                min_pos, max_neg,
                                                 xproperties.yscale_is ("log"));
 
           update_type = 'y';
@@ -5408,9 +5600,10 @@
           limits = xproperties.get_zlim ().matrix_value ();
           FIX_LIMITS ;
 
-          get_children_limits (min_val, max_val, min_pos, kids, 'z');
-
-          limits = xproperties.get_axis_limits (min_val, max_val, min_pos,
+          get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'z');
+
+          limits = xproperties.get_axis_limits (min_val, max_val,
+                                                min_pos, max_neg,
                                                 xproperties.zscale_is ("log"));
 
           update_type = 'z';
@@ -5425,7 +5618,7 @@
           limits = xproperties.get_clim ().matrix_value ();
           FIX_LIMITS ;
 
-          get_children_limits (min_val, max_val, min_pos, kids, 'c');
+          get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'c');
 
           if (min_val > max_val)
             {
@@ -5453,7 +5646,7 @@
           limits = xproperties.get_alim ().matrix_value ();
           FIX_LIMITS ;
 
-          get_children_limits (min_val, max_val, min_pos, kids, 'a');
+          get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'a');
 
           if (min_val > max_val)
             {
@@ -5529,6 +5722,7 @@
   double min_val = octave_Inf;
   double max_val = -octave_Inf;
   double min_pos = octave_Inf;
+  double max_neg = -octave_Inf;
 
   char update_type = 0;
 
@@ -5540,9 +5734,10 @@
     {
       if (xproperties.xlimmode_is ("auto"))
         {
-          get_children_limits (min_val, max_val, min_pos, kids, 'x');
-
-          limits = xproperties.get_axis_limits (min_val, max_val, min_pos,
+          get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'x');
+
+          limits = xproperties.get_axis_limits (min_val, max_val,
+                                                min_pos, max_neg,
                                                 xproperties.xscale_is ("log"));
 
           update_type = 'x';
@@ -5554,9 +5749,10 @@
     {
       if (xproperties.ylimmode_is ("auto"))
         {
-          get_children_limits (min_val, max_val, min_pos, kids, 'y');
-
-          limits = xproperties.get_axis_limits (min_val, max_val, min_pos,
+          get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'y');
+
+          limits = xproperties.get_axis_limits (min_val, max_val,
+                                                min_pos, max_neg,
                                                 xproperties.yscale_is ("log"));
 
           update_type = 'y';
@@ -5568,9 +5764,10 @@
     {
       if (xproperties.zlimmode_is ("auto"))
         {
-          get_children_limits (min_val, max_val, min_pos, kids, 'z');
-
-          limits = xproperties.get_axis_limits (min_val, max_val, min_pos,
+          get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'z');
+
+          limits = xproperties.get_axis_limits (min_val, max_val,
+                                                min_pos, max_neg,
                                                 xproperties.zscale_is ("log"));
 
           update_type = 'z';
@@ -5582,7 +5779,7 @@
     {
       if (xproperties.climmode_is ("auto"))
         {
-          get_children_limits (min_val, max_val, min_pos, kids, 'c');
+          get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'c');
 
           if (min_val > max_val)
             {
@@ -5607,7 +5804,7 @@
     {
       if (xproperties.alimmode_is ("auto"))
         {
-          get_children_limits (min_val, max_val, min_pos, kids, 'a');
+          get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'a');
 
           if (min_val > max_val)
             {
@@ -5693,12 +5890,14 @@
   double minx = octave_Inf;
   double maxx = -octave_Inf;
   double min_pos_x = octave_Inf;
-  get_children_limits (minx, maxx, min_pos_x, kids, 'x');
+  double max_neg_x = -octave_Inf;
+  get_children_limits (minx, maxx, min_pos_x, max_neg_x, kids, 'x');
 
   double miny = octave_Inf;
   double maxy = -octave_Inf;
   double min_pos_y = octave_Inf;
-  get_children_limits (miny, maxy, min_pos_y, kids, 'y');
+  double max_neg_y = -octave_Inf;
+  get_children_limits (miny, maxy, min_pos_y, max_neg_y, kids, 'y');
 
   // Perform the zooming
   xlims (0) = x + factor * (xlims (0) - x);
@@ -5742,12 +5941,14 @@
   double minx = octave_Inf;
   double maxx = -octave_Inf;
   double min_pos_x = octave_Inf;
-  get_children_limits (minx, maxx, min_pos_x, kids, 'x');
+  double max_neg_x = -octave_Inf;
+  get_children_limits (minx, maxx, min_pos_x, max_neg_x, kids, 'x');
 
   double miny = octave_Inf;
   double maxy = -octave_Inf;
   double min_pos_y = octave_Inf;
-  get_children_limits (miny, maxy, min_pos_y, kids, 'y');
+  double max_neg_y = -octave_Inf;
+  get_children_limits (miny, maxy, min_pos_y, max_neg_y, kids, 'y');
 
   xlims (0) += delta_x;
   xlims (1) += delta_x;
@@ -5815,11 +6016,12 @@
 Matrix
 line::properties::compute_xlim (void) const
 {
-  Matrix m (1, 3);
+  Matrix m (1, 4);
 
   m(0) = xdata.min_val ();
   m(1) = xdata.max_val ();
   m(2) = xdata.min_pos ();
+  m(3) = xdata.max_neg ();
 
   return m;
 }
@@ -5827,11 +6029,12 @@
 Matrix
 line::properties::compute_ylim (void) const
 {
-  Matrix m (1, 3);
+  Matrix m (1, 4);
 
   m(0) = ydata.min_val ();
   m(1) = ydata.max_val ();
   m(2) = ydata.min_pos ();
+  m(3) = ydata.max_neg ();
 
   return m;
 }
@@ -5864,11 +6067,9 @@
 }
 
 void
-text::properties::update_text_extent (void)
+text::properties::update_font (void)
 {
 #ifdef HAVE_FREETYPE
-
-  // FIXME: font and color should be set only when modified, for efficiency
 #ifdef HAVE_FONTCONFIG
   renderer.set_font (get ("fontname").string_value (),
                      get ("fontweight").string_value (),
@@ -5876,6 +6077,13 @@
                      get ("fontsize").double_value ());
 #endif
   renderer.set_color (get_color_rgb ());
+#endif
+}
+
+void
+text::properties::update_text_extent (void)
+{
+#ifdef HAVE_FREETYPE
 
   int halign = 0, valign = 0;
 
@@ -5892,11 +6100,17 @@
     valign = 1;
 
   Matrix bbox;
+
   // FIXME: string should be parsed only when modified, for efficiency
-  renderer.text_to_pixels (get_string (), pixels, bbox,
+
+  octave_value string_prop = get_string ();
+
+  string_vector sv = string_prop.all_strings ();
+
+  renderer.text_to_pixels (sv.join ("\n"), pixels, bbox,
                            halign, valign, get_rotation ());
-
   set_extent (bbox);
+
 #endif
 
   if (autopos_tag_is ("xlabel") || autopos_tag_is ("ylabel") ||
@@ -6102,6 +6316,7 @@
   double min_val = octave_Inf;
   double max_val = -octave_Inf;
   double min_pos = octave_Inf;
+  double max_neg = -octave_Inf;
 
   Matrix limits;
   double val;
@@ -6134,7 +6349,7 @@
       update_type = 'a';
     }
 
-  if (limits.numel() == 3)
+  if (limits.numel() == 4)
     {
       val = limits(0);
       if (! (xisinf (val) || xisnan (val)))
@@ -6145,27 +6360,33 @@
       val = limits(2);
       if (! (xisinf (val) || xisnan (val)))
         min_pos = val;
+      val = limits(3);
+      if (! (xisinf (val) || xisnan (val)))
+        max_neg = val;
     }
   else
     {
-      limits.resize(3,1);
+      limits.resize(4,1);
       limits(0) = min_val;
       limits(1) = max_val;
       limits(2) = min_pos;
-    }
-
-  get_children_limits (min_val, max_val, min_pos, kids, update_type);
+      limits(3) = max_neg;
+    }
+
+  get_children_limits (min_val, max_val, min_pos, max_neg, kids, update_type);
 
   unwind_protect frame;
   frame.protect_var (updating_hggroup_limits);
 
   updating_hggroup_limits = true;
 
-  if (limits(0) != min_val || limits(1) != max_val || limits(2) != min_pos)
+  if (limits(0) != min_val || limits(1) != max_val
+      || limits(2) != min_pos || limits(3) != max_neg)
     {
       limits(0) = min_val;
       limits(1) = max_val;
       limits(2) = min_pos;
+      limits(3) = max_neg;
 
       switch (update_type)
         {
@@ -6208,36 +6429,37 @@
   double min_val = octave_Inf;
   double max_val = -octave_Inf;
   double min_pos = octave_Inf;
+  double max_neg = -octave_Inf;
 
   char update_type = 0;
 
   if (axis_type == "xlim" || axis_type == "xliminclude")
     {
-      get_children_limits (min_val, max_val, min_pos, kids, 'x');
+      get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'x');
 
       update_type = 'x';
     }
   else if (axis_type == "ylim" || axis_type == "yliminclude")
     {
-      get_children_limits (min_val, max_val, min_pos, kids, 'y');
+      get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'y');
 
       update_type = 'y';
     }
   else if (axis_type == "zlim" || axis_type == "zliminclude")
     {
-      get_children_limits (min_val, max_val, min_pos, kids, 'z');
+      get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'z');
 
       update_type = 'z';
     }
   else if (axis_type == "clim" || axis_type == "climinclude")
     {
-      get_children_limits (min_val, max_val, min_pos, kids, 'c');
+      get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'c');
 
       update_type = 'c';
     }
   else if (axis_type == "alim" || axis_type == "aliminclude")
     {
-      get_children_limits (min_val, max_val, min_pos, kids, 'a');
+      get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'a');
 
       update_type = 'a';
     }
@@ -6247,11 +6469,12 @@
 
   updating_hggroup_limits = true;
 
-  Matrix limits (1, 3, 0.0);
+  Matrix limits (1, 4, 0.0);
 
   limits(0) = min_val;
   limits(1) = max_val;
   limits(2) = min_pos;
+  limits(3) = max_neg;
 
   switch (update_type)
     {
@@ -6917,6 +7140,12 @@
 
   if (nargin == 1 || nargin == 2)
     {
+      if (args(0).is_empty())
+        {
+          retval = Matrix ();
+          return retval;
+        }
+
       ColumnVector hcv (args(0).vector_value ());
 
       if (! error_state)
--- a/src/graphics.h.in	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/graphics.h.in	Tue Sep 20 15:38:24 2011 -0400
@@ -33,6 +33,7 @@
 #include <list>
 #include <map>
 #include <set>
+#include <sstream>
 #include <string>
 
 #include "caseless-str.h"
@@ -692,6 +693,178 @@
 
 // ---------------------------------------------------------------------
 
+class text_label_property : public base_property
+{
+public:
+  enum type { char_t, cellstr_t };
+
+  text_label_property (const std::string& s, const graphics_handle& h,
+                       const std::string& val = "")
+    : base_property (s, h), value (val), stored_type (char_t)
+  { }
+
+  text_label_property (const std::string& s, const graphics_handle& h,
+                       const NDArray& nda)
+    : base_property (s, h), stored_type (char_t)
+  {
+    octave_idx_type nel = nda.numel ();
+
+    value.resize (nel);
+
+    for (octave_idx_type i = 0; i < nel; i++)
+      {
+        std::ostringstream buf;
+        buf << nda(i);
+        value[i] = buf.str ();
+      }
+  }
+
+  text_label_property (const std::string& s, const graphics_handle& h,
+                       const Cell& c)
+    : base_property (s, h), stored_type (cellstr_t)
+  {
+    octave_idx_type nel = c.numel ();
+
+    value.resize (nel);
+
+    for (octave_idx_type i = 0; i < nel; i++)
+      {
+        octave_value tmp = c(i);
+
+        if (tmp.is_string ())
+          value[i] = c(i).string_value ();
+        else
+          {
+            double d = c(i).double_value ();
+
+            if (! error_state)
+              {
+                std::ostringstream buf;
+                buf << d;
+                value[i] = buf.str ();
+              }
+            else
+              break;
+          }
+      }
+  }
+
+  text_label_property (const text_label_property& p)
+    : base_property (p), value (p.value), stored_type (p.stored_type)
+  { }
+
+  bool empty (void) const
+  {
+    octave_value tmp = get ();
+    return tmp.is_empty ();
+  }
+
+  octave_value get (void) const
+  {
+    if (stored_type == char_t)
+      return octave_value (char_value ());
+    else
+      return octave_value (cell_value ());
+  }
+
+  std::string string_value (void) const
+  {
+    return value.empty () ? std::string () : value[0];
+  }
+
+  string_vector string_vector_value (void) const { return value; }
+
+  charMatrix char_value (void) const { return charMatrix (value, ' '); }
+
+  Cell cell_value (void) const {return Cell (value); }
+
+  text_label_property& operator = (const octave_value& val)
+  {
+    set (val);
+    return *this;
+  }
+
+  base_property* clone (void) const { return new text_label_property (*this); }
+
+protected:
+
+  bool do_set (const octave_value& val)
+  {
+    if (val.is_string ())
+      {
+        value = val.all_strings ();
+
+        stored_type = char_t;
+      }
+    else if (val.is_cell ())
+      {
+        Cell c = val.cell_value ();
+
+        octave_idx_type nel = c.numel ();
+
+        value.resize (nel);
+
+        for (octave_idx_type i = 0; i < nel; i++)
+          {
+            octave_value tmp = c(i);
+
+            if (tmp.is_string ())
+              value[i] = c(i).string_value ();
+            else
+              {
+                double d = c(i).double_value ();
+
+                if (! error_state)
+                  {
+                    std::ostringstream buf;
+                    buf << d;
+                    value[i] = buf.str ();
+                  }
+                else
+                  return false;
+              }
+          }
+
+        stored_type = cellstr_t;
+      }
+    else
+      {
+        NDArray nda = val.array_value ();
+
+        if (! error_state)
+          {
+            octave_idx_type nel = nda.numel ();
+
+            value.resize (nel);
+
+            for (octave_idx_type i = 0; i < nel; i++)
+              {
+                std::ostringstream buf;
+                buf << nda(i);
+                value[i] = buf.str ();
+              }
+
+            stored_type = char_t;
+          }
+        else
+          {
+            error ("set: invalid string property value for \"%s\"",
+                   get_name ().c_str ());
+
+            return false;
+          }
+      }
+
+    return true;
+  }
+
+private:
+  string_vector value;
+  type stored_type;
+};
+
+// ---------------------------------------------------------------------
+
 class radio_values
 {
 public:
@@ -1115,7 +1288,8 @@
 public:
   array_property (void)
     : base_property ("", graphics_handle ()), data (Matrix ()),
-      xmin (), xmax (), xminp (), type_constraints (), size_constraints ()
+      xmin (), xmax (), xminp (), xmaxp (),
+      type_constraints (), size_constraints ()
     {
       get_data_limits ();
     }
@@ -1123,7 +1297,8 @@
   array_property (const std::string& nm, const graphics_handle& h,
                   const octave_value& m)
     : base_property (nm, h), data (m),
-      xmin (), xmax (), xminp (), type_constraints (), size_constraints ()
+      xmin (), xmax (), xminp (), xmaxp (),
+      type_constraints (), size_constraints ()
     {
       get_data_limits ();
     }
@@ -1133,7 +1308,7 @@
   // copy constraints.
   array_property (const array_property& p)
     : base_property (p), data (p.data),
-      xmin (p.xmin), xmax (p.xmax), xminp (p.xminp),
+      xmin (p.xmin), xmax (p.xmax), xminp (p.xminp), xmaxp (p.xmaxp),
       type_constraints (), size_constraints ()
     { }
 
@@ -1148,14 +1323,16 @@
   double min_val (void) const { return xmin; }
   double max_val (void) const { return xmax; }
   double min_pos (void) const { return xminp; }
+  double max_neg (void) const { return xmaxp; }
 
   Matrix get_limits (void) const
     {
-      Matrix m (1, 3);
+      Matrix m (1, 4);
 
       m(0) = min_val ();
       m(1) = max_val ();
       m(2) = min_pos ();
+      m(3) = max_neg ();
 
       return m;
     }
@@ -1210,6 +1387,7 @@
   double xmin;
   double xmax;
   double xminp;
+  double xmaxp;
   std::list<std::string> type_constraints;
   std::list<dim_vector> size_constraints;
 };
@@ -3206,6 +3384,11 @@
     bool x2Dtop, y2Dright, layer2Dtop;
     bool xySym, xyzSym, zSign, nearhoriz;
 
+#if HAVE_FREETYPE
+    // freetype renderer, used for calculation of text (tick labels) size
+    ft_render text_renderer;
+#endif
+
     void set_text_child (handle_property& h, const std::string& who,
                          const octave_value& v);
 
@@ -3288,11 +3471,11 @@
       radio_property cameraviewanglemode , "{auto}|manual"
       array_property currentpoint , Matrix (2, 3, 0.0)
       radio_property drawmode , "{normal}|fast"
-      radio_property fontangle , "{normal}|italic|oblique"
-      string_property fontname , OCTAVE_DEFAULT_FONTNAME
-      double_property fontsize , 10
+      radio_property fontangle u , "{normal}|italic|oblique"
+      string_property fontname u , OCTAVE_DEFAULT_FONTNAME
+      double_property fontsize u , 10
       radio_property fontunits SU , "{points}|normalized|inches|centimeters|pixels"
-      radio_property fontweight , "{normal}|light|demi|bold"
+      radio_property fontweight u , "{normal}|light|demi|bold"
       radio_property gridlinestyle , "-|--|{:}|-.|none"
       string_array_property linestyleorder , "-"
       double_property linewidth , 0.5
@@ -3318,6 +3501,8 @@
       row_vector_property zmtick h , Matrix ()
       // hidden properties for inset
       array_property looseinset hu , Matrix (1, 4, 0.0)
+      // hidden properties for alignment of subplots
+      radio_property autopos_tag h , "{none}|subplot"
    END_PROPERTIES
 
   protected:
@@ -3411,7 +3596,15 @@
           calc_ticklabels (ztick, zticklabel, zscale.is ("log"));
       }
 
+    void update_font (void);
+    void update_fontname (void) { update_font (); }
+    void update_fontsize (void) { update_font (); }
+    void update_fontangle (void) { update_font (); }
+    void update_fontweight (void) { update_font (); }
+
+    void sync_positions (const Matrix& linset);
     void sync_positions (void);
+
     void update_outerposition (void)
     {
       set_activepositionproperty ("outerposition");
@@ -3457,7 +3650,9 @@
     Matrix calc_tightbox (const Matrix& init_pos);
 
   public:
-    Matrix get_axis_limits (double xmin, double xmax, double min_pos, bool logscale);
+    Matrix get_axis_limits (double xmin, double xmax,
+                            double min_pos, double max_neg,
+                            bool logscale);
 
     void update_xlim (bool do_clr_zoom = true)
     {
@@ -3671,7 +3866,7 @@
     // properties declarations.
 
     BEGIN_PROPERTIES (text)
-      string_property string u , ""
+      text_label_property string u , ""
       radio_property units u , "{data}|pixels|normalized|inches|centimeters|points"
       array_property position mu , Matrix (1, 3, 0.0)
       double_property rotation mu , 0
@@ -3712,7 +3907,7 @@
     Matrix get_extent_matrix (void) const;
     const uint8NDArray& get_pixels (void) const { return pixels; }
 #if HAVE_FREETYPE
-    // freetype render, used for text rendering
+    // freetype renderer, used for calculation of text size
     ft_render renderer;
 #endif
 
@@ -3722,6 +3917,7 @@
         position.add_constraint (dim_vector (1, 2));
         position.add_constraint (dim_vector (1, 3));
         cached_units = get_units ();
+        update_font ();
       }
 
   private:
@@ -3757,13 +3953,14 @@
     void update_horizontalalignmentmode (void) { request_autopos (); }
     void update_verticalalignmentmode (void) { request_autopos (); }
 
+    void update_font (void);
     void update_string (void) { request_autopos (); update_text_extent (); }
     void update_rotation (void) { update_text_extent (); }
-    void update_color (void) { update_text_extent (); }
-    void update_fontname (void) { update_text_extent (); }
-    void update_fontsize (void) { update_text_extent (); }
-    void update_fontangle (void) { update_text_extent (); }
-    void update_fontweight (void) { update_text_extent (); }
+    void update_color (void) { update_font (); }
+    void update_fontname (void) { update_font (); update_text_extent (); }
+    void update_fontsize (void) { update_font (); update_text_extent (); }
+    void update_fontangle (void) { update_font (); update_text_extent (); }
+    void update_fontweight (void) { update_font (); update_text_extent (); }
     void update_interpreter (void) { update_text_extent (); }
     void update_horizontalalignment (void) { update_text_extent (); }
     void update_verticalalignment (void) { update_text_extent (); }
@@ -4717,7 +4914,8 @@
   void do_post_event (const graphics_event& e);
 };
 
-void get_children_limits (double& min_val, double& max_val, double& min_pos,
+void get_children_limits (double& min_val, double& max_val,
+                          double& min_pos, double& max_neg,
                           const Matrix& kids, char limit_type);
 
 OCTINTERP_API int calc_dimensions (const graphics_object& gh);
--- a/src/help.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/help.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -749,6 +749,9 @@
   const string_vector bif = symbol_table::built_in_function_names ();
   const int bif_len = bif.length ();
 
+  const string_vector cfl = symbol_table::cmdline_function_names ();
+  const int cfl_len = cfl.length ();
+
   const string_vector lcl = symbol_table::variable_names ();
   const int lcl_len = lcl.length ();
 
@@ -758,7 +761,8 @@
   const string_vector afl = autoloaded_functions ();
   const int afl_len = afl.length ();
 
-  const int total_len = key_len + bif_len + lcl_len + ffl_len + afl_len;
+  const int total_len
+    = key_len + bif_len + cfl_len + lcl_len + ffl_len + afl_len;
 
   string_vector list (total_len);
 
@@ -772,6 +776,9 @@
   for (i = 0; i < bif_len; i++)
     list[j++] = bif[i];
 
+  for (i = 0; i < cfl_len; i++)
+    list[j++] = cfl[i];
+
   for (i = 0; i < lcl_len; i++)
     list[j++] = lcl[i];
 
--- a/src/input.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/input.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -686,93 +686,88 @@
   frame.protect_var (VPS1);
   VPS1 = prompt;
 
-  if (stdin_is_tty)
+  if (! (interactive || forced_interactive)
+      || (reading_fcn_file
+          || reading_classdef_file
+          || reading_script_file
+          || get_input_from_eval_string
+          || input_from_startup_file
+          || input_from_command_line_file))
     {
-      if (! (interactive || forced_interactive)
-          || (reading_fcn_file
-              || reading_classdef_file
-              || reading_script_file
-              || get_input_from_eval_string
-              || input_from_startup_file
-              || input_from_command_line_file))
-        {
-          frame.protect_var (forced_interactive);
-          forced_interactive = true;
+      frame.protect_var (forced_interactive);
+      forced_interactive = true;
+
+      frame.protect_var (reading_fcn_file);
+      reading_fcn_file = false;
+
+      frame.protect_var (reading_classdef_file);
+      reading_classdef_file = false;
+
+      frame.protect_var (reading_script_file);
+      reading_script_file = false;
 
-          frame.protect_var (reading_fcn_file);
-          reading_fcn_file = false;
+      frame.protect_var (input_from_startup_file);
+      input_from_startup_file = false;
+
+      frame.protect_var (input_from_command_line_file);
+      input_from_command_line_file = false;
 
-          frame.protect_var (reading_classdef_file);
-          reading_classdef_file = false;
+      frame.protect_var (get_input_from_eval_string);
+      get_input_from_eval_string = false;
+
+      YY_BUFFER_STATE old_buf = current_buffer ();
+      YY_BUFFER_STATE new_buf = create_buffer (get_input_from_stdin ());
+
+      // FIXME: are these safe?
+      frame.add_fcn (switch_to_buffer, old_buf);
+      frame.add_fcn (delete_buffer, new_buf);
 
-          frame.protect_var (reading_script_file);
-          reading_script_file = false;
+      switch_to_buffer (new_buf);
+    }
+
+  while (Vdebugging)
+    {
+      reset_error_handler ();
+
+      reset_parser ();
 
-          frame.protect_var (input_from_startup_file);
-          input_from_startup_file = false;
+      // Save current value of global_command.
+      frame.protect_var (global_command);
+
+      global_command = 0;
 
-          frame.protect_var (input_from_command_line_file);
-          input_from_command_line_file = false;
+      // Do this with an unwind-protect cleanup function so that the
+      // forced variables will be unmarked in the event of an interrupt.
+      symbol_table::scope_id scope = symbol_table::top_scope ();
+      frame.add_fcn (symbol_table::unmark_forced_variables, scope);
 
-          frame.protect_var (get_input_from_eval_string);
-          get_input_from_eval_string = false;
+      // This is the same as yyparse in parse.y.
+      int retval = octave_parse ();
 
-          YY_BUFFER_STATE old_buf = current_buffer ();
-          YY_BUFFER_STATE new_buf = create_buffer (get_input_from_stdin ());
+      if (retval == 0 && global_command)
+        {
+          global_command->accept (*current_evaluator);
 
-          // FIXME: are these safe?
-          frame.add_fcn (switch_to_buffer, old_buf);
-          frame.add_fcn (delete_buffer, new_buf);
+          // FIXME -- To avoid a memory leak, global_command should be
+          // deleted, I think.  But doing that here causes trouble if
+          // an error occurs while executing a debugging command
+          // (dbstep, for example). It's not clear to me why that
+          // happens.
+          //
+          // delete global_command;
+          //
+          // global_command = 0;
 
-          switch_to_buffer (new_buf);
+          if (octave_completion_matches_called)
+            octave_completion_matches_called = false;
         }
 
-      while (Vdebugging)
-        {
-          reset_error_handler ();
-
-          reset_parser ();
-
-          // Save current value of global_command.
-          frame.protect_var (global_command);
-
-          global_command = 0;
-
-          // Do this with an unwind-protect cleanup function so that the
-          // forced variables will be unmarked in the event of an interrupt.
-          symbol_table::scope_id scope = symbol_table::top_scope ();
-          frame.add_fcn (symbol_table::unmark_forced_variables, scope);
-
-          // This is the same as yyparse in parse.y.
-          int retval = octave_parse ();
-
-          if (retval == 0 && global_command)
-            {
-              global_command->accept (*current_evaluator);
+      // Unmark forced variables.
+      // Restore previous value of global_command.
+      frame.run_top (2);
 
-              // FIXME -- To avoid a memory leak, global_command should be
-              // deleted, I think.  But doing that here causes trouble if
-              // an error occurs while executing a debugging command
-              // (dbstep, for example). It's not clear to me why that
-              // happens.
-              //
-              // delete global_command;
-              //
-              // global_command = 0;
-
-              if (octave_completion_matches_called)
-                octave_completion_matches_called = false;
-            }
-
-          // Unmark forced variables.
-          // Restore previous value of global_command.
-          frame.run_top (2);
-
-          octave_quit ();
-        }
+      octave_quit ();
     }
-  else
-    warning ("invalid attempt to debug script read from stdin");
 }
 
 // If the user simply hits return, this will produce an empty matrix.
@@ -956,14 +951,11 @@
 
   unwind_protect frame;
 
-  // FIXME -- we shouldn't need both the
-  // command_history object and the
-  // Vsaving_history variable...
+  frame.add_fcn (command_history::ignore_entries,
+                 command_history::ignoring_entries ());
+
   command_history::ignore_entries (false);
 
-  frame.add_fcn (command_history::ignore_entries, ! Vsaving_history);
-
-  frame.protect_var (Vsaving_history);
   frame.protect_var (Vdebugging);
 
   frame.add_fcn (octave_call_stack::restore_frame,
@@ -975,7 +967,6 @@
   // tree_print_code tpc (octave_stdout);
   // stmt.accept (tpc);
 
-  Vsaving_history = true;
   Vdebugging = true;
 
   std::string prompt = "debug> ";
--- a/src/lex.ll	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/lex.ll	Tue Sep 20 15:38:24 2011 -0400
@@ -164,13 +164,13 @@
     } \
   while (0)
 
-#define BIN_OP_RETURN(tok, convert, bos) \
+#define BIN_OP_RETURN_INTERNAL(tok, convert, bos, qit) \
   do \
     { \
       yylval.tok_val = new token (input_line_number, current_input_column); \
       token_stack.push (yylval.tok_val); \
       current_input_column += yyleng; \
-      lexer_flags.quote_is_transpose = false; \
+      lexer_flags.quote_is_transpose = qit; \
       lexer_flags.convert_spaces_to_comma = convert; \
       lexer_flags.looking_for_object_index = false; \
       lexer_flags.at_beginning_of_statement = bos; \
@@ -178,6 +178,21 @@
     } \
   while (0)
 
+#define XBIN_OP_RETURN_INTERNAL(tok, convert, bos, qit) \
+  do \
+    { \
+      gripe_matlab_incompatible_operator (yytext); \
+      BIN_OP_RETURN_INTERNAL (tok, convert, bos, qit); \
+    } \
+  while (0)
+
+#define BIN_OP_RETURN(tok, convert, bos) \
+  do \
+    { \
+      BIN_OP_RETURN_INTERNAL (tok, convert, bos, false); \
+    } \
+  while (0)
+
 #define XBIN_OP_RETURN(tok, convert, bos) \
   do \
     { \
@@ -896,8 +911,8 @@
 ".^"    { LEXER_DEBUG (".^"); BIN_OP_RETURN (EPOW, false, false); }
 ".**"   { LEXER_DEBUG (".**"); XBIN_OP_RETURN (EPOW, false, false); }
 ".'"    { LEXER_DEBUG (".'"); do_comma_insert_check (); BIN_OP_RETURN (TRANSPOSE, true, false); }
-"++"    { LEXER_DEBUG ("++"); do_comma_insert_check (); XBIN_OP_RETURN (PLUS_PLUS, true, false); }
-"--"    { LEXER_DEBUG ("--"); do_comma_insert_check (); XBIN_OP_RETURN (MINUS_MINUS, true, false); }
+"++"    { LEXER_DEBUG ("++"); do_comma_insert_check (); XBIN_OP_RETURN_INTERNAL (PLUS_PLUS, true, false, true); }
+"--"    { LEXER_DEBUG ("--"); do_comma_insert_check (); XBIN_OP_RETURN_INTERNAL (MINUS_MINUS, true, false, true); }
 "<="    { LEXER_DEBUG ("<="); BIN_OP_RETURN (EXPR_LE, false, false); }
 "=="    { LEXER_DEBUG ("=="); BIN_OP_RETURN (EXPR_EQ, false, false); }
 "~="    { LEXER_DEBUG ("~="); BIN_OP_RETURN (EXPR_NE, false, false); }
@@ -3435,6 +3450,14 @@
   return retval;
 }
 
+/*
+
+%!assert (iskeyword ("for"))
+%!assert (iskeyword ("fort"), false)
+%!assert (iskeyword ("fft"), false)
+
+*/
+
 void
 prep_lexer_for_script_file (void)
 {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/link-deps.mk	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,38 @@
+include ../liboctave/link-deps.mk
+
+if AMCOND_ENABLE_DYNAMIC_LINKING
+  LIBOCTINTERP_LINK_DEPS =
+else
+  LIBOCTINTERP_LINK_DEPS = $(DLD_FUNCTIONS_LIBS)
+endif
+
+LIBOCTINTERP_LINK_DEPS += \
+  $(GRAPHICS_LIBS) \
+  $(FT2_LIBS) \
+  $(HDF5_LIBS) \
+  $(Z_LIBS) \
+  $(OPENGL_LIBS) \
+  $(X11_LIBS) \
+  $(CARBON_LIBS)
+
+LIBOCTINTERP_LINK_OPTS = \
+  $(GRAPHICS_LDFLAGS) \
+  $(FT2_LDFLAGS) \
+  $(HDF5_LDFLAGS) \
+  $(Z_LDFLAGS) \
+  $(REGEX_LDFLAGS)
+
+OCT_LINK_DEPS =
+
+OCT_LINK_OPTS = $(LDFLAGS)
+
+if AMCOND_LINK_ALL_DEPS
+  LIBOCTINTERP_LINK_DEPS += $(LIBOCTAVE_LINK_DEPS)
+  LIBOCTINTERP_LINK_OPTS += $(LIBOCTAVE_LINK_OPTS)
+
+  OCTAVE_LINK_DEPS = $(LIBOCTINTERP_LINK_DEPS)
+  OCTAVE_LINK_OPTS = $(LIBOCTINTERP_LINK_OPTS)
+
+  OCT_LINK_DEPS += $(LIBOCTINTERP_LINK_DEPS)
+  OCT_LINK_OPTS += $(LIBOCTINTERP_LINK_OPTS)
+endif
--- a/src/load-save.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/load-save.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -545,6 +545,9 @@
 @deftypefnx {Command} {} load options file\n\
 @deftypefnx {Command} {} load options file v1 v2 @dots{}\n\
 @deftypefnx {Command} {S =} load (\"options\", \"file\", \"v1\", \"v2\", @dots{})\n\
+@deftypefnx {Command} {} load file options\n\
+@deftypefnx {Command} {} load file options v1 v2 @dots{}\n\
+@deftypefnx {Command} {S =} load (\"file\", \"options\", \"v1\", \"v2\", @dots{})\n\
 Load the named variables @var{v1}, @var{v2}, @dots{}, from the file\n\
 @var{file}.  If no variables are specified then all variables found in the\n\
 file will be loaded.  As with @code{save}, the list of variables to extract\n\
@@ -642,6 +645,16 @@
   if (error_state)
     return retval;
 
+  int i = 1;
+  std::string orig_fname = "";
+
+  // Function called with Matlab-style ["filename", options] syntax
+  if (argv[1].at(0) != '-')
+    {
+      orig_fname = argv[1];
+      i++;
+    }
+
   // It isn't necessary to have the default load format stored in a
   // user preference variable since we can determine the type of file
   // as we are reading.
@@ -651,8 +664,8 @@
   bool list_only = false;
   bool verbose = false;
 
-  int i;
-  for (i = 1; i < argc; i++)
+  //for (i; i < argc; i++)
+  for (; i < argc; i++)
     {
       if (argv[i] == "-force" || argv[i] == "-f")
         {
@@ -710,19 +723,24 @@
         break;
     }
 
-  if (i == argc)
+  if (orig_fname == "")
     {
-      print_usage ();
-      return retval;
+      if (i == argc)
+        {
+          print_usage ();
+          return retval;
+        }
+      else
+        orig_fname = argv[i];
     }
-
-  std::string orig_fname = argv[i];
+  else
+    i--;
 
   oct_mach_info::float_format flt_fmt = oct_mach_info::flt_fmt_unknown;
 
   bool swap = false;
 
-  if (argv[i] == "-")
+  if (orig_fname == "-")
     {
       i++;
 
@@ -747,7 +765,7 @@
     }
   else
     {
-      std::string fname = file_ops::tilde_expand (argv[i]);
+      std::string fname = file_ops::tilde_expand (orig_fname);
 
       fname = find_file_to_load (fname, orig_fname);
 
--- a/src/ls-mat5.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/ls-mat5.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -1225,21 +1225,29 @@
             else
               {
                 octave_class* cls = new octave_class (m, classname);
-                cls->reconstruct_exemplar ();
-
-                if (! cls->reconstruct_parents ())
-                  warning ("load: unable to reconstruct object inheritance");
-
-                tc = cls;
-                if (load_path::find_method (classname, "loadobj") !=
-                    std::string())
+
+                if (cls->reconstruct_exemplar ())
                   {
-                    octave_value_list tmp = feval ("loadobj", tc, 1);
-
-                    if (! error_state)
-                      tc = tmp(0);
-                    else
-                      goto data_read_error;
+
+                    if (! cls->reconstruct_parents ())
+                      warning ("load: unable to reconstruct object inheritance");
+
+                    tc = cls;
+                    if (load_path::find_method (classname, "loadobj") !=
+                        std::string())
+                      {
+                        octave_value_list tmp = feval ("loadobj", tc, 1);
+
+                        if (! error_state)
+                          tc = tmp(0);
+                        else
+                          goto data_read_error;
+                      }
+                  }
+                else
+                  {
+                    tc = m;
+                    warning ("load: element has been converted to a structure");
                   }
               }
           }
--- a/src/mappers.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/mappers.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -67,7 +67,6 @@
 }
 
 /*
-
 %!assert(abs (1), 1);
 %!assert(abs (-3.5), 3.5);
 %!assert(abs (3+4i), 5);
@@ -82,8 +81,7 @@
 
 %!error abs ();
 %!error abs (1, 2);
-
- */
+*/
 
 DEFUN (acos, args, ,
     "-*- texinfo -*-\n\
@@ -102,7 +100,6 @@
 }
 
 /*
-
 %!test
 %! rt2 = sqrt (2);
 %! rt3 = sqrt (3);
@@ -119,7 +116,6 @@
 
 %!error acos ();
 %!error acos (1, 2);
-
 */
 
 DEFUN (acosh, args, ,
@@ -139,7 +135,6 @@
 }
 
 /*
-
 %!test
 %! v = [0, pi/2*i, pi*i, pi/2*i];
 %! x = [1, 0, -1, 0];
@@ -152,7 +147,6 @@
 
 %!error acosh ();
 %!error acosh (1, 2);
-
 */
 
 DEFUN (angle, args, ,
@@ -203,7 +197,6 @@
 }
 
 /*
-
 %!assert(arg (1), 0);
 %!assert(arg (i), pi/2);
 %!assert(arg (-1), pi);
@@ -212,13 +205,18 @@
 
 %!assert(arg (single(1)), single(0));
 %!assert(arg (single(i)), single(pi/2));
-%!assert(arg (single(-1)), single(pi));
+%!test
+%! if (ismac ())
+%!   ## Avoid failing for a MacOS feature
+%!   assert(arg (single(-1)), single(pi), 2*eps(single(1)));
+%! else
+%!   assert(arg (single(-1)), single(pi));
+%! endif
 %!assert(arg (single(-i)), single(-pi/2));
 %!assert(arg (single([1, i; -1, -i])), single([0, pi/2; pi, -pi/2]), 2e1*eps('single'));
 
 %!error arg ();
 %!error arg (1, 2);
-
 */
 
 DEFUN (asin, args, ,
@@ -265,7 +263,6 @@
 }
 
 /*
-
 %!test
 %! v = [0, pi/2*i, 0, -pi/2*i];
 %! x = [0, i, 0, -i];
@@ -278,7 +275,6 @@
 
 %!error asinh ();
 %!error asinh (1, 2);
-
 */
 
 DEFUN (atan, args, ,
@@ -298,7 +294,6 @@
 }
 
 /*
-
 %!test
 %! rt2 = sqrt (2);
 %! rt3 = sqrt (3);
@@ -315,8 +310,7 @@
 
 %!error atan ();
 %!error atan (1, 2);
-
- */
+*/
 
 DEFUN (atanh, args, ,
     "-*- texinfo -*-\n\
@@ -335,7 +329,6 @@
 }
 
 /*
-
 %!test
 %! v = [0, 0];
 %! x = [0, 0];
@@ -348,7 +341,6 @@
 
 %!error atanh ();
 %!error atanh (1, 2);
-
 */
 
 DEFUN (cbrt, args, ,
@@ -370,7 +362,6 @@
 }
 
 /*
-
 %!assert (cbrt (64), 4)
 %!assert (cbrt (-125), -5)
 %!assert (cbrt (0), 0)
@@ -379,7 +370,6 @@
 %!assert (cbrt (NaN), NaN)
 %!assert (cbrt (2^300), 2^100)
 %!assert (cbrt (125*2^300), 5*2^100)
-
 */
 
 DEFUN (ceil, args, ,
@@ -408,7 +398,6 @@
 }
 
 /*
-
 %% double precision
 %!assert(ceil ([2, 1.1, -1.1, -1]), [2, 2, -1, -1]);
 
@@ -423,7 +412,6 @@
 
 %!error ceil ();
 %!error ceil (1, 2);
-
 */
 
 DEFUN (conj, args, ,
@@ -449,7 +437,6 @@
 }
 
 /*
-
 %!assert(conj (1), 1);
 %!assert(conj (i), -i)
 %!assert(conj (1+i), 1-i)
@@ -464,7 +451,6 @@
 
 %!error conj ();
 %!error conj (1, 2);
-
 */
 
 DEFUN (cos, args, ,
@@ -484,7 +470,6 @@
 }
 
 /*
-
 %!test
 %! rt2 = sqrt (2);
 %! rt3 = sqrt (3);
@@ -501,8 +486,7 @@
 
 %!error cos ();
 %!error cos (1, 2);
-
- */
+*/
 
 DEFUN (cosh, args, ,
     "-*- texinfo -*-\n\
@@ -521,7 +505,6 @@
 }
 
 /*
-
 %!test
 %! x = [0, pi/2*i, pi*i, 3*pi/2*i];
 %! v = [1, 0, -1, 0];
@@ -534,7 +517,6 @@
 
 %!error cosh ();
 %!error cosh (1, 2);
-
 */
 
 DEFUN (erf, args, ,
@@ -573,7 +555,6 @@
 }
 
 /*
-
 %!test
 %! a = -1i*sqrt(-1/(6.4187*6.4187));
 %! assert (erf(a), erf(real(a)));
@@ -597,9 +578,6 @@
 
 %% test/octave.test/arith/erf-3.m
 %!error erf(1,2);
-
-
-
 */
 
 DEFUN (erfinv, args, ,
@@ -660,11 +638,9 @@
 }
 
 /*
-
 %!test
 %! a = -1i*sqrt(-1/(6.4187*6.4187));
 %! assert (erfc(a), erfc(real(a)));
-
 */
 
 DEFUN (erfcx, args, ,
@@ -695,10 +671,6 @@
   return retval;
 }
 
-/*
-
-*/
-
 DEFUN (exp, args, ,
     "-*- texinfo -*-\n\
 @deftypefn {Mapping Function} {} exp (@var{x})\n\
@@ -724,7 +696,6 @@
 }
 
 /*
-
 %!assert(exp ([0, 1, -1, -1000]), [1, e, 1/e, 0], sqrt (eps));
 %!assert(exp (1+i), e * (cos (1) + sin (1) * i), sqrt (eps));
 %!assert(exp (single([0, 1, -1, -1000])), single([1, e, 1/e, 0]), sqrt (eps('single')));
@@ -735,7 +706,6 @@
 
 %!assert(exp (Inf) == Inf && exp (-Inf) == 0 && isnan (exp (NaN)));
 %!assert(exp (Inf ('single')) == Inf('single') && exp (-Inf('single')) == 0 && isnan (exp (NaN('single'))));
-
 */
 
 DEFUN (expm1, args, ,
@@ -788,7 +758,6 @@
 }
 
 /*
-
 %!assert(!(finite (Inf)));
 %!assert(!(finite (NaN)));
 %!assert(finite (rand(1,10)));
@@ -796,8 +765,7 @@
 %!assert(!(finite (single(Inf))));
 %!assert(!(finite (single(NaN))));
 %!assert(finite (single(rand(1,10))));
-
- */
+*/
 
 DEFUN (fix, args, ,
     "-*- texinfo -*-\n\
@@ -825,7 +793,6 @@
 }
 
 /*
-
 %!assert(fix ([1.1, 1, -1.1, -1]), [1, 1, -1, -1]);
 %!assert(fix ([1.1+1.1i, 1+i, -1.1-1.1i, -1-i]), [1+i, 1+i, -1-i, -1-i]);
 %!assert(fix (single([1.1, 1, -1.1, -1])), single([1, 1, -1, -1]));
@@ -833,7 +800,6 @@
 
 %!error fix ();
 %!error fix (1, 2);
-
 */
 
 DEFUN (floor, args, ,
@@ -862,7 +828,6 @@
 }
 
 /*
-
 %!assert(floor ([2, 1.1, -1.1, -1]), [2, 1, -2, -1]);
 %!assert(floor ([2+2i, 1.1+1.1i, -1.1-1.1i, -1-i]), [2+2i, 1+i, -2-2i, -1-i]);
 %!assert(floor (single ([2, 1.1, -1.1, -1])), single ([2, 1, -2, -1]));
@@ -870,7 +835,6 @@
 
 %!error floor ();
 %!error floor (1, 2);
-
 */
 
 DEFUN (gamma, args, ,
@@ -909,7 +873,6 @@
 }
 
 /*
-
 %!test
 %! a = -1i*sqrt(-1/(6.4187*6.4187));
 %! assert (gamma(a), gamma(real(a)));
@@ -936,7 +899,6 @@
 
 %!error gamma();
 %!error gamma(1,2);
-
 */
 
 DEFUN (imag, args, ,
@@ -956,7 +918,6 @@
 }
 
 /*
-
 %!assert(imag (1), 0);
 %!assert(imag (i), 1);
 %!assert(imag (1+i), 1);
@@ -969,8 +930,7 @@
 
 %!error imag ();
 %!error imag (1, 2);
-
- */
+*/
 
 DEFUNX ("isalnum", Fisalnum, args, ,
     "-*- texinfo -*-\n\
@@ -990,6 +950,19 @@
   return retval;
 }
 
+/*
+%!test
+%! charset = setstr (0:127);
+%! result = zeros (1, 128);
+%! result ((toascii("A"):toascii("Z"))+1) = 1;
+%! result ((toascii("0"):toascii("9"))+1) = 1;
+%! result ((toascii("a"):toascii("z"))+1) = 1;
+%! assert(all (isalnum (charset) == result));
+
+%!error isalnum (1, 2);
+%!error isalnum ();
+*/
+
 DEFUNX ("isalpha", Fisalpha, args, ,
     "-*- texinfo -*-\n\
 @deftypefn {Mapping Function} {} isalpha (@var{s})\n\
@@ -1008,6 +981,18 @@
   return retval;
 }
 
+/*
+%!test
+%! charset = setstr (0:127);
+%! result = zeros (1, 128);
+%! result ((toascii("A"):toascii("Z"))+1) = 1;
+%! result ((toascii("a"):toascii("z"))+1) = 1;
+%! assert(all (isalpha (charset) == result));
+
+%!error isalpha (1, 2);
+%!error isalpha ();
+*/
+
 DEFUNX ("isascii", Fisascii, args, ,
     "-*- texinfo -*-\n\
 @deftypefn {Mapping Function} {} isascii (@var{s})\n\
@@ -1025,6 +1010,16 @@
   return retval;
 }
 
+/*
+%!test
+%! charset = setstr (0:127);
+%! result = ones (1, 128);
+%! assert(all (isascii (charset) == result));
+
+%!error isascii (1, 2);
+%!error isascii ();
+*/
+
 DEFUNX ("iscntrl", Fiscntrl, args, ,
     "-*- texinfo -*-\n\
 @deftypefn {Mapping Function} {} iscntrl (@var{s})\n\
@@ -1042,6 +1037,19 @@
   return retval;
 }
 
+/*
+%% test/octave.test/string/iscntrl-1.m
+%!test
+%! charset = setstr (0:127);
+%! result = zeros (1, 128);
+%! result (1:32) = 1;
+%! result (128) = 1;
+%! assert(all (iscntrl (charset) == result));
+
+%!error iscntrl (1, 2);
+%!error iscntrl ();
+*/
+
 DEFUNX ("isdigit", Fisdigit, args, ,
     "-*- texinfo -*-\n\
 @deftypefn {Mapping Function} {} isdigit (@var{s})\n\
@@ -1059,6 +1067,17 @@
   return retval;
 }
 
+/*
+%!test
+%! charset = setstr (0:127);
+%! result = zeros (1, 128);
+%! result ((toascii("0"):toascii("9"))+1) = 1;
+%! assert(all (isdigit (charset) == result));
+
+%!error isdigit (1, 2);
+%!error isdigit ();
+*/
+
 DEFUN (isinf, args, ,
     "-*- texinfo -*-\n\
 @deftypefn {Mapping Function} {} isinf (@var{x})\n\
@@ -1085,7 +1104,6 @@
 }
 
 /*
-
 %!assert(isinf (Inf));
 %!assert(!isinf (NaN));
 %!assert(!(isinf (NA)));
@@ -1097,8 +1115,7 @@
 %!assert(!(isinf (single(NA))));
 %!assert(isinf (single(rand(1,10))), false(1,10));
 %!assert(isinf(single([NaN -Inf -1 0 1 Inf NA])), [false, true, false, false, false, true, false]);
-
- */
+*/
 
 DEFUNX ("isgraph", Fisgraph, args, ,
     "-*- texinfo -*-\n\
@@ -1118,6 +1135,17 @@
   return retval;
 }
 
+/*
+%!test
+%! charset = setstr (0:127);
+%! result = zeros (1, 128);
+%! result (34:127) = 1;
+%! assert(all (isgraph (charset) == result));
+
+%!error isgraph (1, 2);
+%!error isgraph ();
+*/
+
 DEFUNX ("islower", Fislower, args, ,
     "-*- texinfo -*-\n\
 @deftypefn {Mapping Function} {} islower (@var{s})\n\
@@ -1135,6 +1163,17 @@
   return retval;
 }
 
+/*
+%!test
+%! charset = setstr (0:127);
+%! result = zeros (1, 128);
+%! result ((toascii("a"):toascii("z"))+1) = 1;
+%! assert(all (islower (charset) == result));
+
+%!error islower (1, 2);
+%!error islower ();
+*/
+
 DEFUN (isna, args, ,
     "-*- texinfo -*-\n\
 @deftypefn {Mapping Function} {} isna (@var{x})\n\
@@ -1161,7 +1200,6 @@
 }
 
 /*
-
 %!assert(!(isna (Inf)));
 %!assert(!isna (NaN));
 %!assert(isna (NA));
@@ -1173,8 +1211,7 @@
 %!assert(isna (single(NA)));
 %!assert(isna (single(rand(1,10))), false(1,10));
 %!assert(isna(single([NaN -Inf -1 0 1 Inf NA])), [false, false, false, false, false, false, true]);
-
- */
+*/
 
 DEFUN (isnan, args, ,
     "-*- texinfo -*-\n\
@@ -1202,7 +1239,6 @@
 }
 
 /*
-
 %!assert(!(isnan (Inf)));
 %!assert(isnan (NaN));
 %!assert(isnan (NA));
@@ -1214,8 +1250,7 @@
 %!assert(isnan (single(NA)));
 %!assert(isnan (single(rand(1,10))), false(1,10));
 %!assert(isnan(single([NaN -Inf -1 0 1 Inf NA])), [true, false, false, false, false, false, true]);
-
- */
+*/
 
 DEFUNX ("isprint", Fisprint, args, ,
     "-*- texinfo -*-\n\
@@ -1235,6 +1270,20 @@
   return retval;
 }
 
+/*
+%!test
+%! charset = setstr (0:127);
+%! result = zeros (1, 128);
+%! result (33:127) = 1;
+%! if (ispc () && ! isunix ())
+%!   result(10) = 1;
+%! endif
+%! assert(all (isprint (charset) == result));
+
+%!error isprint (1, 2);
+%!error isprint ();
+*/
+
 DEFUNX ("ispunct", Fispunct, args, ,
     "-*- texinfo -*-\n\
 @deftypefn {Mapping Function} {} ispunct (@var{s})\n\
@@ -1252,6 +1301,20 @@
   return retval;
 }
 
+/*
+%!test
+%! charset = setstr (0:127);
+%! result = zeros (1, 128);
+%! result (34:48) = 1;
+%! result (59:65) = 1;
+%! result (92:97) = 1;
+%! result (124:127) = 1;
+%! assert(all (ispunct (charset) == result));
+
+%!error ispunct (1, 2);
+%!error ispunct ();
+*/
+
 DEFUNX ("isspace", Fisspace, args, ,
     "-*- texinfo -*-\n\
 @deftypefn {Mapping Function} {} isspace (@var{s})\n\
@@ -1270,6 +1333,17 @@
   return retval;
 }
 
+/*
+%!test
+%! charset = setstr (0:127);
+%! result = zeros (1, 128);
+%! result (toascii (" \f\n\r\t\v")+1) = 1;
+%! assert(all (isspace (charset) == result));
+
+%!error isspace (1, 2);
+%!error isspace ();
+*/
+
 DEFUNX ("isupper", Fisupper, args, ,
     "-*- texinfo -*-\n\
 @deftypefn {Mapping Function} {} isupper (@var{s})\n\
@@ -1287,6 +1361,17 @@
   return retval;
 }
 
+/*
+%!test
+%! charset = setstr (0:127);
+%! result = zeros (1, 128);
+%! result ((toascii("A"):toascii("Z"))+1) = 1;
+%! assert(all (isupper (charset) == result));
+
+%!error isupper (1, 2);
+%!error isupper ();
+*/
+
 DEFUNX ("isxdigit", Fisxdigit, args, ,
     "-*- texinfo -*-\n\
 @deftypefn {Mapping Function} {} isxdigit (@var{s})\n\
@@ -1304,6 +1389,19 @@
   return retval;
 }
 
+/*
+%!test
+%! charset = setstr (0:127);
+%! result = zeros (1, 128);
+%! result ((toascii("A"):toascii("F"))+1) = 1;
+%! result ((toascii("0"):toascii("9"))+1) = 1;
+%! result ((toascii("a"):toascii("f"))+1) = 1;
+%! assert(all (isxdigit (charset) == result));
+
+%!error isxdigit (1, 2);
+%!error isxdigit ();
+*/
+
 DEFUN (lgamma, args, ,
     "-*- texinfo -*-\n\
 @deftypefn  {Mapping Function} {} lgamma (@var{x})\n\
@@ -1322,7 +1420,6 @@
 }
 
 /*
-
 %!test
 %! a = -1i*sqrt(-1/(6.4187*6.4187));
 %! assert (lgamma(a), lgamma(real(a)));
@@ -1349,7 +1446,6 @@
 
 %!error lgamma();
 %!error lgamma(1,2);
-
 */
 
 DEFUN (log, args, ,
@@ -1377,7 +1473,6 @@
 }
 
 /*
-
 %!assert(log ([1, e, e^2]), [0, 1, 2], sqrt (eps));
 %!assert(log ([-0.5, -1.5, -2.5]), log([0.5, 1.5, 2.5]) + pi*1i, sqrt (eps));
 
@@ -1386,8 +1481,7 @@
 
 %!error log ();
 %!error log (1, 2);
-
- */
+*/
 
 DEFUN (log10, args, ,
     "-*- texinfo -*-\n\
@@ -1406,13 +1500,11 @@
 }
 
 /*
-
 %!assert(log10 ([0.01, 0.1, 1, 10, 100]), [-2, -1, 0, 1, 2], sqrt (eps));
 %!assert(log10 (single([0.01, 0.1, 1, 10, 100])), single([-2, -1, 0, 1, 2]), sqrt (eps ('single')));
 
 %!error log10 ();
 %!error log10 (1, 2);
-
 */
 
 DEFUN (log1p, args, ,
@@ -1455,7 +1547,6 @@
 }
 
 /*
-
 %!assert(real (1), 1);
 %!assert(real (i), 0);
 %!assert(real (1+i), 1);
@@ -1468,7 +1559,6 @@
 
 %!error real ();
 %!error real (1, 2);
-
 */
 
 DEFUN (round, args, ,
@@ -1497,7 +1587,6 @@
 }
 
 /*
-
 %!assert(round (1), 1);
 %!assert(round (1.1), 1);
 %!assert(round (5.5), 6);
@@ -1516,7 +1605,6 @@
 
 %!error round ();
 %!error round (1, 2);
-
 */
 
 DEFUN (roundb, args, ,
@@ -1571,7 +1659,6 @@
 }
 
 /*
-
 %!assert(sign (-2) , -1);
 %!assert(sign (3), 1);
 %!assert(sign (0), 0);
@@ -1584,7 +1671,6 @@
 
 %!error sign ();
 %!error sign (1, 2);
-
 */
 
 DEFUN (sin, args, ,
@@ -1604,7 +1690,6 @@
 }
 
 /*
-
 %!test
 %! rt2 = sqrt (2);
 %! rt3 = sqrt (3);
@@ -1621,7 +1706,6 @@
 
 %!error sin ();
 %!error sin (1, 2);
-
 */
 
 DEFUN (sinh, args, ,
@@ -1641,7 +1725,6 @@
 }
 
 /*
-
 %!test
 %! x = [0, pi/2*i, pi*i, 3*pi/2*i];
 %! v = [0, i, 0, -i];
@@ -1654,8 +1737,7 @@
 
 %!error sinh ();
 %!error sinh (1, 2);
-
- */
+*/
 
 DEFUN (sqrt, args, ,
     "-*- texinfo -*-\n\
@@ -1676,7 +1758,6 @@
 }
 
 /*
-
 %!assert(sqrt (4), 2)
 %!assert(sqrt (-1), i)
 %!assert(sqrt (1+i), exp (0.5 * log (1+i)), sqrt (eps));
@@ -1689,7 +1770,6 @@
 
 %!error sqrt ();
 %!error sqrt (1, 2);
-
 */
 
 DEFUN (tan, args, ,
@@ -1709,7 +1789,6 @@
 }
 
 /*
-
 %!test
 %! rt2 = sqrt (2);
 %! rt3 = sqrt (3);
@@ -1726,7 +1805,6 @@
 
 %!error tan ();
 %!error tan (1, 2);
-
 */
 
 DEFUN (tanh, args, ,
@@ -1746,7 +1824,6 @@
 }
 
 /*
-
 %!test
 %! x = [0, pi*i];
 %! v = [0, 0];
@@ -1759,7 +1836,6 @@
 
 %!error tanh ();
 %!error tanh (1, 2);
-
 */
 
 DEFUNX ("toascii", Ftoascii, args, ,
@@ -1786,6 +1862,17 @@
   return retval;
 }
 
+/*
+%!assert(toascii (char (0:127)), 0:127);
+%!assert(toascii (" ":"@"), 32:64);
+%!assert(toascii ("A":"Z"), 65:90);
+%!assert(toascii ("[":"`"), 91:96);
+%!assert(toascii ("a":"z"), 97:122);
+%!assert(toascii ("{":"~"), 123:126);
+%!error toascii (1, 2);
+%!error toascii (1, 2);
+*/
+
 DEFUNX ("tolower", Ftolower, args, ,
     "-*- texinfo -*-\n\
 @deftypefn  {Mapping Function} {} tolower (@var{s})\n\
@@ -1815,9 +1902,9 @@
 DEFALIAS (lower, tolower);
 
 /*
-
 %!error <Invalid call to tolower.*> tolower();
 %!error <Invalid call to tolower.*> lower();
+%!error tolower (1, 2);
 %!assert(tolower("OCTAVE"), "octave");
 %!assert(tolower("123OCTave!_&"), "123octave!_&");
 %!assert(tolower({"ABC", "DEF", {"GHI", {"JKL"}}}), {"abc", "def", {"ghi", {"jkl"}}});
@@ -1829,9 +1916,14 @@
 %!  a(3,3,3,3) = "D";
 %!  assert(tolower(a)(3,3,3,3), "d");
 
+%!test
+%! charset = setstr (0:127);
+%! result = charset;
+%! result ((toascii("A"):toascii("Z"))+1) \
+%! = result ((toascii("a"):toascii("z"))+1);
+%! assert(all (tolower (charset) == result));
 */
 
-
 DEFUNX ("toupper", Ftoupper, args, ,
     "-*- texinfo -*-\n\
 @deftypefn  {Mapping Function} {} toupper (@var{s})\n\
@@ -1861,9 +1953,9 @@
 DEFALIAS (upper, toupper);
 
 /*
-
 %!error <Invalid call to toupper.*> toupper();
 %!error <Invalid call to toupper.*> upper();
+%!error toupper (1, 2);
 %!assert(toupper("octave"), "OCTAVE");
 %!assert(toupper("123OCTave!_&"), "123OCTAVE!_&");
 %!assert(toupper({"abc", "def", {"ghi", {"jkl"}}}), {"ABC", "DEF", {"GHI", {"JKL"}}});
@@ -1874,7 +1966,12 @@
 %!test
 %!  a(3,3,3,3) = "d";
 %!  assert(toupper(a)(3,3,3,3), "D");
-
+%!test
+%! charset = setstr (0:127);
+%! result = charset;
+%! result ((toascii("a"):toascii("z"))+1) \
+%! = result ((toascii("A"):toascii("Z"))+1);
+%! assert(all (toupper (charset) == result));
 */
 
 DEFALIAS (gammaln, lgamma);
--- a/src/mkoctfile.cc.in	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/mkoctfile.cc.in	Tue Sep 20 15:38:24 2011 -0400
@@ -219,7 +219,6 @@
   vars["DL_LD"] = get_variable ("DL_LD", %OCTAVE_CONF_DL_LD%);
   vars["DL_LDFLAGS"] = get_variable ("DL_LDFLAGS", %OCTAVE_CONF_MKOCTFILE_DL_LDFLAGS%);
 
-  vars["RLD_FLAG"] = get_variable ("RLD_FLAG", %OCTAVE_CONF_RLD_FLAG%);
   vars["RDYNAMIC_FLAG"] = get_variable ("RDYNAMIC_FLAG", %OCTAVE_CONF_RDYNAMIC_FLAG%);
   vars["LIBOCTAVE"] = "-loctave";
   vars["LIBOCTINTERP"] = "-loctinterp";
@@ -233,6 +232,10 @@
   vars["FFTW3F_LIBS"] = get_variable ("FFTW3F_LIBS", %OCTAVE_CONF_FFTW3F_LIBS%);
   vars["LIBS"] = get_variable ("LIBS", %OCTAVE_CONF_LIBS%);
   vars["FLIBS"] = get_variable ("FLIBS", %OCTAVE_CONF_FLIBS%);
+  vars["OCTAVE_LINK_DEPS"] = get_variable ("FLIBS", %OCTAVE_CONF_OCTAVE_LINK_DEPS%);
+  vars["OCT_LINK_DEPS"] = get_variable ("FLIBS", %OCTAVE_CONF_OCT_LINK_DEPS%);
+  vars["FLIBS"] = get_variable ("FLIBS", %OCTAVE_CONF_FLIBS%);
+
   vars["LD_CXX"] = get_variable ("LD_CXX", %OCTAVE_CONF_LD_CXX%);
   vars["LDFLAGS"] = get_variable ("LDFLAGS", %OCTAVE_CONF_LDFLAGS%);
   vars["LD_STATIC_FLAG"] = get_variable ("LD_STATIC_FLAG", %OCTAVE_CONF_LD_STATIC_FLAG%);
@@ -296,25 +299,30 @@
 "  -p VAR, --print VAR     Print configuration variable VAR.  Recognized\n"
 "                          variables are:\n"
 "\n"
-"                           ALL_CFLAGS                FLIBS\n"
-"                           ALL_CXXFLAGS              FPICFLAG\n"
-"                           ALL_FFLAGS                INCFLAGS\n"
-"                           ALL_LDFLAGS               LAPACK_LIBS\n"
-"                           BLAS_LIBS                 LDFLAGS\n"
-"                           CC                        LD_CXX\n"
-"                           CFLAGS                    LD_STATIC_FLAG\n"
-"                           CPICFLAG                  LFLAGS\n"
-"                           CPPFLAGS                  LIBCRUFT\n"
-"                           CXX                       LIBOCTAVE\n"
-"                           CXXFLAGS                  LIBOCTINTERP\n"
-"                           CXXPICFLAG                LIBS\n"
-"                           DEPEND_EXTRA_SED_PATTERN  OCTAVE_LIBS\n"
-"                           DEPEND_FLAGS              RDYNAMIC_FLAG\n"
-"                           DL_LD                     READLINE_LIBS\n"
-"                           DL_LDFLAGS                RLD_FLAG\n"
-"                           F77                       SED\n"
-"                           FFLAGS                    XTRA_CFLAGS\n"
-"                           FFTW_LIBS                 XTRA_CXXFLAGS\n"
+"                            ALL_CFLAGS                FLIBS\n"
+"                            ALL_CXXFLAGS              FPICFLAG\n"
+"                            ALL_FFLAGS                INCFLAGS\n"
+"                            ALL_LDFLAGS               LAPACK_LIBS\n"
+"                            BLAS_LIBS                 LDFLAGS\n"
+"                            CC                        LD_CXX\n"
+"                            CFLAGS                    LD_STATIC_FLAG\n"
+"                            CPICFLAG                  LFLAGS\n"
+"                            CPPFLAGS                  LIBCRUFT\n"
+"                            CXX                       LIBOCTAVE\n"
+"                            CXXFLAGS                  LIBOCTINTERP\n"
+"                            CXXPICFLAG                LIBS\n"
+"                            DEPEND_EXTRA_SED_PATTERN  OCTAVE_LIBS\n"
+"                            DEPEND_FLAGS              OCTAVE_LINK_DEPS\n"
+"                            DL_LD                     OCTAVE_LINK_OPTS\n"
+"                            DL_LDFLAGS                OCT_LINK_DEPS\n"
+"                            EXEEXT                    OCT_LINK_OPTS\n"
+"                            F77                       RDYNAMIC_FLAG\n"
+"                            F77_INTEGER_8_FLAG        READLINE_LIBS\n"
+"                            FFLAGS                    SED\n"
+"                            FFTW3_LDFLAGS             XTRA_CFLAGS\n"
+"                            FFTW3_LIBS                XTRA_CXXFLAGS\n"
+"                            FFTW3F_LDFLAGS\n"
+"                            FFTW3F_LIBS\n"
 "\n"
 "  --link-stand-alone      Link a stand-alone executable file.\n"
 "\n"
@@ -742,11 +750,10 @@
                 + vars["ALL_CXXFLAGS"] + " " + vars["RDYNAMIC_FLAG"]
                 + " " + vars["ALL_LDFLAGS"] + " " +  pass_on_options
                 + " " + output_option + " " + objfiles + " " + libfiles
-                + " " + ldflags + " " + vars["LFLAGS"] + " "
-                + vars["RLD_FLAG"] + " " + vars["OCTAVE_LIBS"] + " "
-                + vars["LAPACK_LIBS"] + " " + vars["BLAS_LIBS"] + " "
-                + vars["FFTW_LIBS"] + " " + vars["READLINE_LIBS"] + " "
-                + vars["LIBS"] + " " + vars["FLIBS"];
+                + " " + ldflags + " " + vars["LFLAGS"]
+                + " -loctinterp -loctave -lcruft "
+                + " " + vars["OCT_LINK_OPTS"]
+                + " " + vars["OCTAVE_LINK_DEPS"];
               result = run_command (cmd);
             }
           else
@@ -758,13 +765,11 @@
         }
       else
         {
-          string LINK_DEPS = vars["LFLAGS"] + " " + vars["OCTAVE_LIBS"]
-            + " " + vars["LDFLAGS"] + " "
-	    + vars["LAPACK_LIBS"] + " " +  vars["BLAS_LIBS"] + " "
-            + vars["FFTW_LIBS"] + " " + vars["LIBS"] + " " + vars["FLIBS"];
           string cmd = vars["DL_LD"] + " " + vars["DL_LDFLAGS"] + " "
             + pass_on_options + " -o " + octfile + " " + objfiles + " "
-            + libfiles + " " + ldflags + " " + LINK_DEPS;
+            + libfiles + " " + ldflags + " " + vars["LFLAGS"]
+            + " -loctinterp -loctave -lcruft "
+            + vars["OCT_LINK_OPTS"] + " " + vars["OCT_LINK_DEPS"];
           result = run_command (cmd);
         }
 
--- a/src/mkoctfile.in	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/mkoctfile.in	Tue Sep 20 15:38:24 2011 -0400
@@ -85,7 +85,6 @@
 : ${DL_LD=%OCTAVE_CONF_DL_LD%}
 : ${DL_LDFLAGS=%OCTAVE_CONF_MKOCTFILE_DL_LDFLAGS%}
 
-: ${RLD_FLAG=%OCTAVE_CONF_RLD_FLAG%}
 : ${RDYNAMIC_FLAG=%OCTAVE_CONF_RDYNAMIC_FLAG%}
 : ${LIBOCTAVE=-loctave}
 : ${LIBOCTINTERP=-loctinterp}
@@ -99,6 +98,10 @@
 : ${FFTW3F_LIBS=%OCTAVE_CONF_FFTW3F_LIBS%}
 : ${LIBS=%OCTAVE_CONF_LIBS%}
 : ${FLIBS=%OCTAVE_CONF_FLIBS%}
+: ${OCTAVE_LINK_DEPS=%OCTAVE_CONF_OCTAVE_LINK_DEPS%}
+: ${OCTAVE_LINK_OPTS=%OCTAVE_CONF_OCTAVE_LINK_OPTS%}
+: ${OCT_LINK_DEPS=%OCTAVE_CONF_OCT_LINK_DEPS%}
+: ${OCT_LINK_OPTS=%OCTAVE_CONF_OCT_LINK_OPTS%}
 : ${LD_CXX=%OCTAVE_CONF_LD_CXX%}
 : ${LDFLAGS=%OCTAVE_CONF_LDFLAGS%}
 : ${LD_STATIC_FLAG=%OCTAVE_CONF_LD_STATIC_FLAG%}
@@ -221,7 +224,7 @@
 
   -s, --strip             Strip output file.
 
-  --mex                   Create a MEX file.  
+  --mex                   Create a MEX file.
                           Set the default output extension to ".mex".
 
   -o FILE, --output FILE  Output file name.  Default extension is .oct
@@ -231,28 +234,29 @@
   -p VAR, --print VAR     Print configuration variable VAR.  Recognized
                           variables are:
 
-                            ALL_CFLAGS                FFTW3F_LDFLAGS
-                            ALL_CXXFLAGS              FFTW3F_LIBS
-                            ALL_FFLAGS                FLIBS
-                            ALL_LDFLAGS               FPICFLAG
-                            BLAS_LIBS                 INCFLAGS
-                            CC                        LAPACK_LIBS
-                            CFLAGS                    LDFLAGS
-                            CPICFLAG                  LD_CXX
-                            CPPFLAGS                  LD_STATIC_FLAG
-                            CXX                       LFLAGS
-                            CXXFLAGS                  LIBCRUFT
-                            CXXPICFLAG                LIBOCTAVE
-                            DEPEND_EXTRA_SED_PATTERN  LIBOCTINTERP
-                            DEPEND_FLAGS              LIBS
-                            DL_LD                     OCTAVE_LIBS
-                            DL_LDFLAGS                RDYNAMIC_FLAG
-                            EXEEXT                    READLINE_LIBS
-                            F77                       RLD_FLAG
+                            ALL_CFLAGS                FFTW3F_LIBS
+                            ALL_CXXFLAGS              FLIBS
+                            ALL_FFLAGS                FPICFLAG
+                            ALL_LDFLAGS               INCFLAGS
+                            BLAS_LIBS                 LAPACK_LIBS
+                            CC                        LDFLAGS
+                            CFLAGS                    LD_CXX
+                            CPICFLAG                  LD_STATIC_FLAG
+                            CPPFLAGS                  LFLAGS
+                            CXX                       LIBCRUFT
+                            CXXFLAGS                  LIBOCTAVE
+                            CXXPICFLAG                LIBOCTINTERP
+                            DEPEND_EXTRA_SED_PATTERN  LIBS
+                            DEPEND_FLAGS              OCTAVE_LIBS
+                            DL_LD                     OCTAVE_LINK_DEPS
+                            DL_LDFLAGS                OCT_LINK_DEPS
+                            EXEEXT                    RDYNAMIC_FLAG
+                            F77                       READLINE_LIBS
                             F77_INTEGER_8_FLAG        SED
                             FFLAGS                    XTRA_CFLAGS
                             FFTW3_LDFLAGS             XTRA_CXXFLAGS
                             FFTW3_LIBS
+                            FFTW3F_LDFLAGS
 
   -v, --verbose           Echo commands as they are executed.
 
@@ -529,7 +533,7 @@
 if $link && [ -n "$objfiles" ]; then
   if $link_stand_alone; then
     if [ -n "$LD_CXX" ]; then
-      cmd="$LD_CXX $CPPFLAGS $ALL_CXXFLAGS $RDYNAMIC_FLAG $ALL_LDFLAGS $pass_on_options $output_option $objfiles $libfiles $ldflags $LFLAGS $RLD_FLAG $OCTAVE_LIBS $LAPACK_LIBS $BLAS_LIBS $FFTW_LIBS $READLINE_LIBS $LIBS $FLIBS"
+      cmd="$LD_CXX $CPPFLAGS $ALL_CXXFLAGS $RDYNAMIC_FLAG $ALL_LDFLAGS $pass_on_options $output_option $objfiles $libfiles $ldflags $LFLAGS -loctinterp -loctave -lcruft $OCTAVE_LINK_OPTS $OCTAVE_LINK_DEPS"
       $dbg $cmd
       eval $cmd
     else
@@ -537,8 +541,7 @@
       exit 1
     fi
   else
-    LINK_DEPS="$LFLAGS $OCTAVE_LIBS $LDFLAGS $LAPACK_LIBS $BLAS_LIBS $FFTW_LIBS $LIBS $FLIBS"
-    cmd="$DL_LD $DL_LDFLAGS $pass_on_options -o $octfile $objfiles $libfiles $ldflags $LINK_DEPS"
+    cmd="$DL_LD $DL_LDFLAGS $pass_on_options -o $octfile $objfiles $libfiles $ldflags $LFLAGS -loctinterp -loctave -lcruft $OCT_LINK_OPTS $OCT_LINK_DEPS"
     $dbg $cmd
     eval $cmd
   fi
--- a/src/oct-conf.h.in	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/oct-conf.h.in	Tue Sep 20 15:38:24 2011 -0400
@@ -376,6 +376,14 @@
 #define OCTAVE_CONF_MKOCTFILE_DL_LDFLAGS %OCTAVE_CONF_MKOCTFILE_DL_LDFLAGS%
 #endif
 
+#ifndef OCTAVE_CONF_OCTAVE_LINK_DEPS
+#define OCTAVE_CONF_OCTAVE_LINK_DEPS %OCTAVE_CONF_OCTAVE_LINK_DEPS%
+#endif
+
+#ifndef OCTAVE_CONF_OCTAVE_LINK_OPTS
+#define OCTAVE_CONF_OCTAVE_LINK_OPTS %OCTAVE_CONF_OCTAVE_LINK_OPTS%
+#endif
+
 #ifndef OCTAVE_CONF_OCTINCLUDEDIR
 #define OCTAVE_CONF_OCTINCLUDEDIR %OCTAVE_CONF_OCTINCLUDEDIR%
 #endif
@@ -384,6 +392,14 @@
 #define OCTAVE_CONF_OCTLIBDIR %OCTAVE_CONF_OCTLIBDIR%
 #endif
 
+#ifndef OCTAVE_CONF_OCT_LINK_DEPS
+#define OCTAVE_CONF_OCT_LINK_DEPS %OCTAVE_CONF_OCT_LINK_DEPS%
+#endif
+
+#ifndef OCTAVE_CONF_OCT_LINK_OPTS
+#define OCTAVE_CONF_OCT_LINK_OPTS %OCTAVE_CONF_OCT_LINK_OPTS%
+#endif
+
 #ifndef OCTAVE_CONF_OPENGL_LIBS
 #define OCTAVE_CONF_OPENGL_LIBS %OCTAVE_CONF_OPENGL_LIBS%
 #endif
@@ -440,10 +456,6 @@
 #define OCTAVE_CONF_REGEX_LIBS %OCTAVE_CONF_REGEX_LIBS%
 #endif
 
-#ifndef OCTAVE_CONF_RLD_FLAG
-#define OCTAVE_CONF_RLD_FLAG %OCTAVE_CONF_RLD_FLAG%
-#endif
-
 #ifndef OCTAVE_CONF_SED
 #define OCTAVE_CONF_SED %OCTAVE_CONF_SED%
 #endif
--- a/src/oct-hist.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/oct-hist.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -88,9 +88,6 @@
   return file;
 }
 
-// Where history is saved.
-static std::string Vhistory_file = default_history_file ();
-
 static int
 default_history_size (void)
 {
@@ -109,27 +106,6 @@
   return size;
 }
 
-// The number of lines to keep in the history file.
-static int Vhistory_size = default_history_size ();
-
-static std::string
-default_history_control (void)
-{
-  std::string retval;
-
-  std::string env_histcontrol = octave_env::getenv ("OCTAVE_HISTCONTROL");
-
-  if (! env_histcontrol.empty ())
-    {
-      return env_histcontrol;
-    }
-
-  return retval;
-}
-
-// The number of lines to keep in the history file.
-static std::string Vhistory_control = default_history_control ();
-
 static std::string
 default_history_timestamp_format (void)
 {
@@ -146,9 +122,6 @@
 static std::string Vhistory_timestamp_format_string
   = default_history_timestamp_format ();
 
-// TRUE if we are saving history.
-bool Vsaving_history = true;
-
 // Display, save, or load history.  Stolen and modified from bash.
 //
 // Arg of -w FILENAME means write file, arg of -r FILENAME
@@ -160,6 +133,10 @@
 {
   int numbered_output = 1;
 
+  unwind_protect frame;
+
+  frame.add_fcn (command_history::set_file, command_history::file ());
+
   int i;
   for (i = 1; i < argc; i++)
     {
@@ -537,8 +514,10 @@
 void
 initialize_history (bool read_history_file)
 {
-  command_history::initialize (read_history_file, Vhistory_file, Vhistory_size,
-                               Vhistory_control);
+  command_history::initialize (read_history_file,
+                               default_history_file (),
+                               default_history_size (),
+                               octave_env::getenv ("OCTAVE_HISTCONTROL"));
 }
 
 void
@@ -691,12 +670,15 @@
 @seealso{history_file, history_size, history_timestamp_format_string, saving_history}\n\
 @end deftypefn")
 {
-  std::string saved_history_control = Vhistory_control;
+  std::string old_history_control = command_history::histcontrol ();
+
+  std::string tmp = old_history_control;
 
-  octave_value retval = SET_INTERNAL_VARIABLE (history_control);
+  octave_value retval = set_internal_variable (tmp, args, nargout,
+                                               "history_control");
 
-  if (Vhistory_control != saved_history_control)
-    command_history::process_histcontrol (Vhistory_control);
+  if (tmp != old_history_control)
+    command_history::process_histcontrol (tmp);
 
   return retval;
 }
@@ -711,13 +693,15 @@
 @seealso{history_file, history_timestamp_format_string, saving_history}\n\
 @end deftypefn")
 {
-  int saved_history_size = Vhistory_size;
+  int old_history_size = command_history::size ();
+
+  int tmp = old_history_size;
 
-  octave_value retval
-    = SET_INTERNAL_VARIABLE_WITH_LIMITS (history_size, -1, INT_MAX);
+  octave_value retval = set_internal_variable (tmp, args, nargout,
+                                               "history_size", -1, INT_MAX);
 
-  if (Vhistory_size != saved_history_size)
-    command_history::set_size (Vhistory_size);
+  if (tmp != old_history_size)
+    command_history::set_size (tmp);
 
   return retval;
 }
@@ -733,12 +717,15 @@
 @seealso{history_size, saving_history, history_timestamp_format_string}\n\
 @end deftypefn")
 {
-  std::string saved_history_file = Vhistory_file;
+  std::string old_history_file = command_history::file ();
+
+  std::string tmp = old_history_file;
 
-  octave_value retval = SET_INTERNAL_VARIABLE (history_file);
+  octave_value retval = set_internal_variable (tmp, args, nargout,
+                                               "history_file");
 
-  if (Vhistory_file != saved_history_file)
-    command_history::set_file (Vhistory_file);
+  if (tmp != old_history_file)
+    command_history::set_file (tmp);
 
   return retval;
 }
@@ -770,9 +757,15 @@
 @seealso{history_control, history_file, history_size, history_timestamp_format_string}\n\
 @end deftypefn")
 {
-  octave_value retval = SET_INTERNAL_VARIABLE (saving_history);
+  bool old_saving_history = ! command_history::ignoring_entries ();
+
+  bool tmp = old_saving_history;
 
-  command_history::ignore_entries (! Vsaving_history);
+  octave_value retval = set_internal_variable (tmp, args, nargout,
+                                               "saving_history");
+
+  if (tmp != old_saving_history)
+    command_history::ignore_entries (! tmp);
 
   return retval;
 }
--- a/src/oct-hist.h	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/oct-hist.h	Tue Sep 20 15:38:24 2011 -0400
@@ -35,7 +35,4 @@
 // TRUE means input is coming from temporary history file.
 extern bool input_from_tmp_history_file;
 
-// TRUE if we are saving history.
-extern bool Vsaving_history;
-
 #endif
--- a/src/oct-parse.yy	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/oct-parse.yy	Tue Sep 20 15:38:24 2011 -0400
@@ -471,7 +471,7 @@
 %type <tree_matrix_type> matrix_rows matrix_rows1
 %type <tree_cell_type> cell_rows cell_rows1
 %type <tree_expression_type> matrix cell
-%type <tree_expression_type> primary_expr postfix_expr prefix_expr binary_expr
+%type <tree_expression_type> primary_expr oper_expr
 %type <tree_expression_type> simple_expr colon_expr assign_expr expression
 %type <tree_identifier_type> identifier fcn_name magic_tilde
 %type <tree_identifier_type> superclass_identifier meta_identifier
@@ -514,7 +514,6 @@
 %type <dummy_type> class_body
 
 // Precedence and associativity.
-%left ';' ',' '\n'
 %right '=' ADD_EQ SUB_EQ MUL_EQ DIV_EQ LEFTDIV_EQ POW_EQ EMUL_EQ EDIV_EQ ELEFTDIV_EQ EPOW_EQ OR_EQ AND_EQ LSHIFT_EQ RSHIFT_EQ
 %left EXPR_OR_OR
 %left EXPR_AND_AND
@@ -525,8 +524,9 @@
 %left ':'
 %left '-' '+' EPLUS EMINUS
 %left '*' '/' LEFTDIV EMUL EDIV ELEFTDIV
-%left UNARY PLUS_PLUS MINUS_MINUS EXPR_NOT
+%right UNARY EXPR_NOT
 %left POW EPOW QUOTE TRANSPOSE
+%right PLUS_PLUS MINUS_MINUS
 %left '(' '.' '{'
 
 // Where to start.
@@ -796,69 +796,61 @@
                   { lexer_flags.looking_at_indirect_ref = true; }
                 ;
 
-postfix_expr    : primary_expr
+oper_expr       : primary_expr
                   { $$ = $1; }
-                | postfix_expr '(' ')'
+                | oper_expr PLUS_PLUS
+                  { $$ = make_postfix_op (PLUS_PLUS, $1, $2); }
+                | oper_expr MINUS_MINUS
+                  { $$ = make_postfix_op (MINUS_MINUS, $1, $2); }
+                | oper_expr '(' ')'
                   { $$ = make_index_expression ($1, 0, '('); }
-                | postfix_expr '(' arg_list ')'
+                | oper_expr '(' arg_list ')'
                   { $$ = make_index_expression ($1, $3, '('); }
-                | postfix_expr '{' '}'
+                | oper_expr '{' '}'
                   { $$ = make_index_expression ($1, 0, '{'); }
-                | postfix_expr '{' arg_list '}'
+                | oper_expr '{' arg_list '}'
                   { $$ = make_index_expression ($1, $3, '{'); }
-                | postfix_expr PLUS_PLUS
-                  { $$ = make_postfix_op (PLUS_PLUS, $1, $2); }
-                | postfix_expr MINUS_MINUS
-                  { $$ = make_postfix_op (MINUS_MINUS, $1, $2); }
-                | postfix_expr QUOTE
+                | oper_expr QUOTE
                   { $$ = make_postfix_op (QUOTE, $1, $2); }
-                | postfix_expr TRANSPOSE
+                | oper_expr TRANSPOSE
                   { $$ = make_postfix_op (TRANSPOSE, $1, $2); }
-                | postfix_expr indirect_ref_op STRUCT_ELT
+                | oper_expr indirect_ref_op STRUCT_ELT
                   { $$ = make_indirect_ref ($1, $3->text ()); }
-                | postfix_expr indirect_ref_op '(' expression ')'
+                | oper_expr indirect_ref_op '(' expression ')'
                   { $$ = make_indirect_ref ($1, $4); }
-                ;
-
-prefix_expr     : postfix_expr
-                  { $$ = $1; }
-                | binary_expr
-                  { $$ = $1; }
-                | PLUS_PLUS prefix_expr %prec UNARY
+                | PLUS_PLUS oper_expr %prec UNARY
                   { $$ = make_prefix_op (PLUS_PLUS, $2, $1); }
-                | MINUS_MINUS prefix_expr %prec UNARY
+                | MINUS_MINUS oper_expr %prec UNARY
                   { $$ = make_prefix_op (MINUS_MINUS, $2, $1); }
-                | EXPR_NOT prefix_expr %prec UNARY
+                | EXPR_NOT oper_expr %prec UNARY
                   { $$ = make_prefix_op (EXPR_NOT, $2, $1); }
-                | '+' prefix_expr %prec UNARY
+                | '+' oper_expr %prec UNARY
                   { $$ = make_prefix_op ('+', $2, $1); }
-                | '-' prefix_expr %prec UNARY
+                | '-' oper_expr %prec UNARY
                   { $$ = make_prefix_op ('-', $2, $1); }
-                ;
-
-binary_expr     : prefix_expr POW prefix_expr
+                | oper_expr POW oper_expr
                   { $$ = make_binary_op (POW, $1, $2, $3); }
-                | prefix_expr EPOW prefix_expr
+                | oper_expr EPOW oper_expr
                   { $$ = make_binary_op (EPOW, $1, $2, $3); }
-                | prefix_expr '+' prefix_expr
+                | oper_expr '+' oper_expr
                   { $$ = make_binary_op ('+', $1, $2, $3); }
-                | prefix_expr '-' prefix_expr
+                | oper_expr '-' oper_expr
                   { $$ = make_binary_op ('-', $1, $2, $3); }
-                | prefix_expr '*' prefix_expr
+                | oper_expr '*' oper_expr
                   { $$ = make_binary_op ('*', $1, $2, $3); }
-                | prefix_expr '/' prefix_expr
+                | oper_expr '/' oper_expr
                   { $$ = make_binary_op ('/', $1, $2, $3); }
-                | prefix_expr EPLUS prefix_expr
+                | oper_expr EPLUS oper_expr
                   { $$ = make_binary_op ('+', $1, $2, $3); }
-                | prefix_expr EMINUS prefix_expr
+                | oper_expr EMINUS oper_expr
                   { $$ = make_binary_op ('-', $1, $2, $3); }
-                | prefix_expr EMUL prefix_expr
+                | oper_expr EMUL oper_expr
                   { $$ = make_binary_op (EMUL, $1, $2, $3); }
-                | prefix_expr EDIV prefix_expr
+                | oper_expr EDIV oper_expr
                   { $$ = make_binary_op (EDIV, $1, $2, $3); }
-                | prefix_expr LEFTDIV prefix_expr
+                | oper_expr LEFTDIV oper_expr
                   { $$ = make_binary_op (LEFTDIV, $1, $2, $3); }
-                | prefix_expr ELEFTDIV prefix_expr
+                | oper_expr ELEFTDIV oper_expr
                   { $$ = make_binary_op (ELEFTDIV, $1, $2, $3); }
                 ;
 
@@ -866,9 +858,9 @@
                   { $$ = finish_colon_expression ($1); }
                 ;
 
-colon_expr1     : prefix_expr
+colon_expr1     : oper_expr
                   { $$ = new tree_colon_expression ($1); }
-                | colon_expr1 ':' prefix_expr
+                | colon_expr1 ':' oper_expr
                   {
                     if (! ($$ = $1->append ($3)))
                       ABORT_PARSE;
@@ -2079,9 +2071,8 @@
 make_anon_fcn_handle (tree_parameter_list *param_list, tree_statement *stmt)
 {
   // FIXME -- need to get these from the location of the @ symbol.
-
-  int l = -1;
-  int c = -1;
+  int l = input_line_number;
+  int c = current_input_column;
 
   tree_parameter_list *ret_list = 0;
 
@@ -2102,6 +2093,9 @@
 
   tree_anon_fcn_handle *retval
     = new tree_anon_fcn_handle (param_list, ret_list, body, fcn_scope, l, c);
+  // FIXME: Stash the filename.  This does not work and produces
+  // errors when executed.
+  //retval->stash_file_name (curr_fcn_file_name);
 
   return retval;
 }
@@ -2908,6 +2902,7 @@
     }
 
   fcn->stash_function_name (id_name);
+  fcn->stash_fcn_location (input_line_number, current_input_column);
 
   if (! help_buf.empty () && current_function_depth == 1
       && ! parsing_subfunctions)
@@ -3348,11 +3343,10 @@
           break;
 
         case '\n':
-          current_input_column = 0;
+          current_input_column = 1;
           break;
 
         default:
-          current_input_column--;
           reader.ungetc (c);
           goto done;
         }
@@ -3479,18 +3473,11 @@
   parsing_subfunctions = false;
   endfunction_found = false;
 
-  // The next four lines must be in this order.
-  frame.add_fcn (command_history::ignore_entries, ! Vsaving_history);
-
-  // FIXME -- we shouldn't need both the
-  // command_history object and the
-  // Vsaving_history variable...
+  frame.add_fcn (command_history::ignore_entries,
+                 command_history::ignoring_entries ());
+
   command_history::ignore_entries ();
 
-  frame.protect_var (Vsaving_history);
-
-  Vsaving_history = false;
-
   FILE *ffile = get_input_from_file (ff, 0);
 
   frame.add_fcn (safe_fclose, ffile);
--- a/src/oct-stream.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/oct-stream.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -1227,158 +1227,9 @@
 
         if (c1 != EOF)
           {
-            if (c1 == 'N')
-              {
-                int c2 = is.get ();
-
-                if (c2 != EOF)
-                  {
-                    if (c2 == 'A')
-                      {
-                        int c3 = is.get ();
-
-                        if (c3 != EOF)
-                          {
-                            is.putback (c3);
-
-                            if (isspace (c3) || ispunct (c3))
-                              ref = octave_NA;
-                            else
-                              {
-                                is.putback (c2);
-                                is.putback (c1);
-
-                                is >> ref;
-                              }
-                          }
-                        else
-                          {
-                            is.clear ();
-
-                            ref = octave_NA;
-                          }
-                      }
-                    else if (c2 == 'a')
-                      {
-                        int c3 = is.get ();
-
-                        if (c3 != EOF)
-                          {
-                            if (c3 == 'N')
-                              {
-                                int c4 = is.get ();
-
-                                if (c4 != EOF)
-                                  {
-                                    is.putback (c4);
-
-                                    if (isspace (c4) || ispunct (c4))
-                                      ref = octave_NaN;
-                                    else
-                                      {
-                                        is.putback (c3);
-                                        is.putback (c2);
-                                        is.putback (c1);
-
-                                        is >> ref;
-                                      }
-                                  }
-                                else
-                                  {
-                                    is.clear ();
-
-                                    ref = octave_NaN;
-                                  }
-                              }
-                            else
-                              {
-                                is.putback (c3);
-                                is.putback (c2);
-                                is.putback (c1);
-
-                                is >> ref;
-                              }
-                          }
-                      }
-                    else
-                      {
-                        is.putback (c2);
-                        is.putback (c1);
-
-                        is >> ref;
-                      }
-                  }
-              }
-            else if (c1 == 'I')
-              {
-                int c2 = is.get ();
-
-                if (c2 != EOF)
-                  {
-                    if (c2 == 'n')
-                      {
-                        int c3 = is.get ();
-
-                        if (c3 != EOF)
-                          {
-                            if (c3 == 'f')
-                              {
-                                int c4 = is.get ();
-
-                                if (c4 != EOF)
-                                  {
-                                    is.putback (c4);
-
-                                    if (isspace (c4) || ispunct (c4))
-                                      ref = octave_Inf;
-                                    else
-                                      {
-                                        is.putback (c3);
-                                        is.putback (c2);
-                                        is.putback (c1);
-
-                                        is >> ref;
-                                      }
-                                  }
-                                else
-                                  {
-                                    is.clear ();
-
-                                    ref = octave_Inf;
-                                  }
-                              }
-                            else
-                              {
-                                is.putback (c3);
-                                is.putback (c2);
-                                is.putback (c1);
-                                
-                                is >> ref;
-                              }
-                          }
-                        else
-                          {
-                            is.putback (c2);
-                            is.putback (c1);
-                            
-                            is >> ref;
-                          }
-                      }
-                    else
-                      {
-                        is.putback (c2);
-                        is.putback (c1);
-                        
-                        is >> ref;
-                      }
-                  }
-              }
-            else
-              {
-                is.putback (c1);
-
-                is >> ref;
-              }
+            is.putback (c1);
+
+            ref = octave_read_value<double> (is);
           }
       }
       break;
@@ -3011,38 +2862,60 @@
     {
       clearerr ();
 
+      // Find current position so we can return to it if needed.
+
       long orig_pos = rep->tell ();
 
-      status = rep->seek (offset, origin);
+      // Move to end of file.  If successful, find the offset of the end.
+
+      status = rep->seek (0, SEEK_END);
 
       if (status == 0)
         {
-          long save_pos = rep->tell ();
-
-          rep->seek (0, SEEK_END);
-
-          long pos_eof = rep->tell ();
-
-          // I don't think save_pos can be less than zero, but we'll
-          // check anyway...
-
-          if (save_pos > pos_eof || save_pos < 0)
+          long eof_pos = rep->tell ();
+
+          if (origin == SEEK_CUR)
+            {
+              // Move back to original position, otherwise we will be
+              // seeking from the end of file which is probably not the
+              // original location.
+
+              rep->seek (orig_pos, SEEK_SET);
+            }
+
+          // Attempt to move to desired position; may be outside bounds
+          // of existing file.
+
+          status = rep->seek (offset, origin);
+
+          if (status == 0)
             {
-              // Seek outside bounds of file.  Failure should leave
-              // position unchanged.
+              // Where are we after moving to desired position?
+
+              long desired_pos = rep->tell ();
+
+              // I don't think save_pos can be less than zero, but we'll
+              // check anyway...
+
+              if (desired_pos > eof_pos || desired_pos < 0)
+                {
+                  // Seek outside bounds of file.  Failure should leave
+                  // position unchanged.
+
+                  rep->seek (orig_pos, SEEK_SET);
+
+                  status = -1;
+                }
+            }
+          else
+            {
+              // Seeking to the desired position failed.  Move back to
+              // original position and return failure status.
 
               rep->seek (orig_pos, SEEK_SET);
 
               status = -1;
             }
-          else
-            {
-              // Is it possible for this to fail?  We are just
-              // returning to a position after the first successful
-              // seek.
-
-              rep->seek (save_pos, SEEK_SET);
-            }
         }
     }
 
--- a/src/octave-config.cc.in	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/octave-config.cc.in	Tue Sep 20 15:38:24 2011 -0400
@@ -219,6 +219,6 @@
 	  return 1;
 	}
     }
-  
+
   return 0;
 }
--- a/src/octave-config.in	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/octave-config.in	Tue Sep 20 15:38:24 2011 -0400
@@ -19,7 +19,7 @@
 ## You should have received a copy of the GNU General Public License
 ## along with Octave; see the file COPYING.  If not, see
 ## <http://www.gnu.org/licenses/>.
-## 
+##
 ## Original version by Rafael Laboissiere <rafael@laboissiere.net>
 ## distributed as free software in the public domain.
 
--- a/src/octave.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/octave.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -971,6 +971,11 @@
   return retval;
 }
 
+/*
+%!error argv (1);
+%!assert (iscellstr (argv ()));
+*/
+
 DEFUN (program_invocation_name, args, ,
   "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} program_invocation_name ()\n\
@@ -993,6 +998,11 @@
   return retval;
 }
 
+/*
+%!error program_invocation_name (1);
+%!assert (ischar (program_invocation_name ()));
+*/
+
 DEFUN (program_name, args, ,
   "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} program_name ()\n\
@@ -1010,3 +1020,8 @@
 
   return retval;
 }
+
+/*
+%!error program_name (1);
+%!assert (ischar (program_name ()));
+*/
--- a/src/ov-base.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/ov-base.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -50,6 +50,7 @@
 #include "ov-str-mat.h"
 #include "ov-fcn-handle.h"
 #include "parse.h"
+#include "pr-output.h"
 #include "utils.h"
 #include "variables.h"
 
@@ -419,7 +420,9 @@
     {
       os << name << " =";
       newline (os);
-      newline (os);
+      if (! Vcompact_format)
+        newline (os);
+
       retval = true;
     }
 
@@ -435,7 +438,7 @@
 
   print (output_buf);
 
-  if (print_padding && pad_after)
+  if (print_padding  && pad_after && ! Vcompact_format)
     newline (output_buf);
 }
 
@@ -1548,3 +1551,16 @@
 {
   return SET_INTERNAL_VARIABLE (sparse_auto_mutate);
 }
+
+/*
+
+%!test
+ s = speye(3);
+ sparse_auto_mutate (false);
+ s(:, 1) = 1;
+ assert (typeinfo (s), "sparse matrix");
+ sparse_auto_mutate (true);
+ s(1, :) = 1;
+ assert (typeinfo (s), "matrix");
+
+*/
--- a/src/ov-bool.h	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/ov-bool.h	Tue Sep 20 15:38:24 2011 -0400
@@ -119,6 +119,30 @@
   uint64_array_value (void) const
     { return uint64NDArray (dim_vector (1, 1), scalar); }
 
+  octave_int8
+  int8_scalar_value (void) const { return octave_int8 (scalar); }
+
+  octave_int16
+  int16_scalar_value (void) const { return octave_int16 (scalar); }
+
+  octave_int32
+  int32_scalar_value (void) const { return octave_int32 (scalar); }
+
+  octave_int64
+  int64_scalar_value (void) const { return octave_int64 (scalar); }
+
+  octave_uint8
+  uint8_scalar_value (void) const { return octave_uint8 (scalar); }
+
+  octave_uint16
+  uint16_scalar_value (void) const { return octave_uint16 (scalar); }
+
+  octave_uint32
+  uint32_scalar_value (void) const { return octave_uint32 (scalar); }
+
+  octave_uint64
+  uint64_scalar_value (void) const { return octave_uint64 (scalar); }
+
   double double_value (bool = false) const { return scalar; }
 
   float float_value (bool = false) const { return scalar; }
--- a/src/ov-builtin.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/ov-builtin.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -29,6 +29,7 @@
 #include "oct-obj.h"
 #include "ov-builtin.h"
 #include "ov.h"
+#include "profiler.h"
 #include "toplev.h"
 #include "unwind-prot.h"
 
@@ -125,6 +126,8 @@
 
       try
         {
+          BEGIN_PROFILER_BLOCK (profiler_name ())
+
           retval = (*f) (args, nargout);
           // Do not allow null values to be returned from functions.
           // FIXME -- perhaps true builtins should be allowed?
@@ -137,6 +140,8 @@
           // the idiom is very common, so we solve that here.
           if (retval.length () == 1 && retval.xelem (0).is_undefined ())
             retval.clear ();
+
+          END_PROFILER_BLOCK
         }
       catch (octave_execution_exception)
         {
--- a/src/ov-class.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/ov-class.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -1020,7 +1020,8 @@
   indent (os);
   os << name << " =";
   newline (os);
-  newline (os);
+  if (! Vcompact_format)
+    newline (os);
 
   return retval;
 }
--- a/src/ov-class.h	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/ov-class.h	Tue Sep 20 15:38:24 2011 -0400
@@ -127,14 +127,14 @@
   size_t nparents (void) const { return parent_list.size (); }
 
   octave_value reshape (const dim_vector& new_dims) const
-    { 
+    {
       octave_class retval = octave_class (*this);
       retval.map = retval.map_value().reshape (new_dims);
       return octave_value (new octave_class (retval));
     }
 
   octave_value resize (const dim_vector& dv, bool = false) const
-    { 
+    {
       octave_class retval = octave_class (*this);
       retval.map.resize (dv);
       return octave_value (new octave_class (retval));
--- a/src/ov-cx-sparse.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/ov-cx-sparse.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -904,7 +904,7 @@
       ARRAY_MAPPER (atan, Complex, ::atan);
       ARRAY_MAPPER (atanh, Complex, ::atanh);
       ARRAY_MAPPER (ceil, Complex, ::ceil);
-      ARRAY_MAPPER (conj, Complex, std::conj);
+      ARRAY_MAPPER (conj, Complex, std::conj<double>);
       ARRAY_MAPPER (cos, Complex, std::cos);
       ARRAY_MAPPER (cosh, Complex, std::cosh);
       ARRAY_MAPPER (exp, Complex, std::exp);
--- a/src/ov-fcn.h	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/ov-fcn.h	Tue Sep 20 15:38:24 2011 -0400
@@ -61,6 +61,9 @@
 
   virtual std::string fcn_file_name (void) const { return std::string (); }
 
+  // The name to show in the profiler (also used as map-key).
+  virtual std::string profiler_name (void) const { return name (); }
+
   virtual std::string parent_fcn_name (void) const { return std::string (); }
 
   virtual symbol_table::scope_id parent_fcn_scope (void) const { return -1; }
--- a/src/ov-flt-re-mat.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/ov-flt-re-mat.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -839,3 +839,32 @@
 
   return octave_value ();
 }
+
+/*
+
+%!assert (class (single(1)), "single")
+%!assert (class (single(1 + i)), "single")
+%!assert (class (single (int8 (1))), "single")
+%!assert (class (single (uint8 (1))), "single")
+%!assert (class (single (int16 (1))), "single")
+%!assert (class (single (uint16 (1))), "single")
+%!assert (class (single (int32 (1))), "single")
+%!assert (class (single (uint32 (1))), "single")
+%!assert (class (single (int64 (1))), "single")
+%!assert (class (single (uint64 (1))), "single")
+%!assert (class (single (true)), "single")
+%!assert (class (single ("A")), "single")
+%!error (single (sparse (1)))
+%!test
+%! x = diag ([1 3 2]);
+%! y = single (x);
+%! assert (class (x), "double");
+%! assert (class (y), "single");
+%!test
+%! x = diag ([i 3 2]);
+%! y = single (x);
+%! assert (class (x), "double");
+%! assert (class (y), "single");
+
+*/
+
--- a/src/ov-int16.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/ov-int16.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -82,3 +82,15 @@
 {
   OCTAVE_TYPE_CONV_BODY (int16);
 }
+
+/*
+
+%!assert (class (int16 (1)), "int16")
+%!assert (int16 (1.25), int16 (1))
+%!assert (int16 (1.5), int16 (2))
+%!assert (int16 (-1.5), int16 (-2))
+%!assert (int16 (2^17), int16 (2^16-1))
+%!assert (int16 (-2^17), int16 (-2^16))
+
+*/
+
--- a/src/ov-int32.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/ov-int32.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -82,3 +82,15 @@
 {
   OCTAVE_TYPE_CONV_BODY (int32);
 }
+
+/*
+
+%!assert (class (int32 (1)), "int32")
+%!assert (int32 (1.25), int32 (1))
+%!assert (int32 (1.5), int32 (2))
+%!assert (int32 (-1.5), int32 (-2))
+%!assert (int32 (2^33), int32 (2^32-1))
+%!assert (int32 (-2^33), int32 (-2^32))
+
+*/
+
--- a/src/ov-int64.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/ov-int64.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -82,3 +82,15 @@
 {
   OCTAVE_TYPE_CONV_BODY (int64);
 }
+
+/*
+
+%!assert (class (int64 (1)), "int64")
+%!assert (int64 (1.25), int64 (1))
+%!assert (int64 (1.5), int64 (2))
+%!assert (int64 (-1.5), int64 (-2))
+%!assert (int64 (2^65), int64 (2^64-1))
+%!assert (int64 (-2^65), int64 (-2^64))
+
+*/
+
--- a/src/ov-int8.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/ov-int8.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -82,3 +82,14 @@
 {
   OCTAVE_TYPE_CONV_BODY (int8);
 }
+
+/*
+
+%!assert (class (int8 (1)), "int8")
+%!assert (int8 (1.25), int8 (1))
+%!assert (int8 (1.5), int8 (2))
+%!assert (int8 (-1.5), int8 (-2))
+%!assert (int8 (2^9), int8 (2^8-1))
+%!assert (int8 (-2^9), int8 (-2^8))
+
+*/
--- a/src/ov-mex-fcn.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/ov-mex-fcn.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -33,6 +33,7 @@
 #include "oct-obj.h"
 #include "ov-mex-fcn.h"
 #include "ov.h"
+#include "profiler.h"
 #include "toplev.h"
 #include "unwind-prot.h"
 
@@ -147,7 +148,9 @@
 
       try
         {
+          BEGIN_PROFILER_BLOCK (profiler_name ())
           retval = call_mex (have_fmex, mex_fcn_ptr, args, nargout, this);
+          END_PROFILER_BLOCK
         }
       catch (octave_execution_exception)
         {
--- a/src/ov-null-mat.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/ov-null-mat.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -118,3 +118,17 @@
   return retval;
 }
 
+/*
+
+%!assert (isnull ([]), true)
+%!assert (isnull ([1]), false)
+%!assert (isnull (zeros (0,3)), false)
+%!assert (isnull (""), true)
+%!assert (isnull ("A"), false)
+%!assert (isnull (''), true)
+%!assert (isnull ('A'), false)
+%!test
+%! x = [];
+%! assert (isnull (x), false);
+
+*/
--- a/src/ov-perm.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/ov-perm.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -217,6 +217,12 @@
   return SparseMatrix (matrix);
 }
 
+SparseBoolMatrix
+octave_perm_matrix::sparse_bool_matrix_value (bool) const
+{
+  return SparseBoolMatrix (matrix);
+}
+
 SparseComplexMatrix
 octave_perm_matrix::sparse_complex_matrix_value (bool) const
 {
--- a/src/ov-perm.h	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/ov-perm.h	Tue Sep 20 15:38:24 2011 -0400
@@ -160,6 +160,8 @@
 
   SparseMatrix sparse_matrix_value (bool = false) const;
 
+  SparseBoolMatrix sparse_bool_matrix_value (bool = false) const;
+
   SparseComplexMatrix sparse_complex_matrix_value (bool = false) const;
 
   int8NDArray
--- a/src/ov-range.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/ov-range.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -370,7 +370,9 @@
     {
       os << name << " =";
       newline (os);
-      newline (os);
+      if (! Vcompact_format)
+        newline (os);
+
       retval = true;
     }
 
@@ -655,3 +657,16 @@
 {
   return SET_INTERNAL_VARIABLE (allow_noninteger_range_as_index);
 }
+
+/*
+%!test
+%! x = 0:10;
+%! save = allow_noninteger_range_as_index (0);
+%! fail ('x(2.1:5)');
+%! assert (x(2:5), 1:4);
+%! allow_noninteger_range_as_index (1);
+%! assert (x(2.49:5), 1:3);
+%! assert (x(2.5:5), 2:4);
+%! assert (x(2.51:5), 2:4);
+%! allow_noninteger_range_as_index (save);
+*/
--- a/src/ov-re-mat.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/ov-re-mat.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -979,3 +979,36 @@
 
   return octave_value ();
 }
+
+/*
+
+%!assert (class (double (single (1))), "double")
+%!assert (class (double (single (1 + i))), "double")
+%!assert (class (double (int8 (1))), "double")
+%!assert (class (double (uint8 (1))), "double")
+%!assert (class (double (int16 (1))), "double")
+%!assert (class (double (uint16 (1))), "double")
+%!assert (class (double (int32 (1))), "double")
+%!assert (class (double (uint32 (1))), "double")
+%!assert (class (double (int64 (1))), "double")
+%!assert (class (double (uint64 (1))), "double")
+%!assert (class (double (true)), "double")
+%!assert (class (double ("A")), "double")
+%!test
+%! x = sparse (logical ([1 0; 0 1]));
+%! y = double (x);
+%! assert (class (x), "logical");
+%! assert (class (y), "double");
+%! assert (issparse (y));
+%!test
+%! x = diag (single ([1 3 2]));
+%! y = double (x);
+%! assert (class (x), "single");
+%! assert (class (y), "double");
+%!test
+%! x = diag (single ([i 3 2]));
+%! y = double (x);
+%! assert (class (x), "single");
+%! assert (class (y), "double");
+
+*/
--- a/src/ov-struct.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/ov-struct.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -1335,11 +1335,14 @@
 
       increment_indent_level ();
 
-      newline (os);
+      if (! Vcompact_format)
+        newline (os);
+
       indent (os);
       os << "scalar structure containing the fields:";
       newline (os);
-      newline (os);
+      if (! Vcompact_format)
+        newline (os);
 
       increment_indent_level ();
 
--- a/src/ov-typeinfo.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/ov-typeinfo.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -595,7 +595,7 @@
 @deftypefnx {Built-in Function} {} typeinfo (@var{expr})\n\
 \n\
 Return the type of the expression @var{expr}, as a string.  If\n\
-@var{expr} is omitted, return an array of strings containing all the\n\
+@var{expr} is omitted, return an cell array of strings containing all the\n\
 currently installed data types.\n\
 @end deftypefn")
 {
@@ -612,3 +612,74 @@
 
   return retval;
 }
+
+/*
+%!error typeinfo ("foo", 1);
+
+%!assert (iscellstr (typeinfo ()));
+
+%!assert (typeinfo (false), "bool");
+%!assert (typeinfo ([true, false]), "bool matrix");
+
+%!assert (typeinfo (1:2), "range");
+
+%!assert (typeinfo ("string"), "string");
+%!assert (typeinfo ('string'), "sq_string");
+
+%!assert (typeinfo (diag ([1, 2])), "diagonal matrix")
+%!assert (typeinfo (diag ([i, 2])), "complex diagonal matrix")
+%!assert (typeinfo (single (diag ([1, 2]))), "float diagonal matrix")
+%!assert (typeinfo (single (diag ([i, 2]))), "float complex diagonal matrix")
+%!assert (typeinfo (diag (single ([1, 2]))), "float diagonal matrix")
+%!assert (typeinfo (diag (single ([i, 2]))), "float complex diagonal matrix")
+
+%!assert (typeinfo ([]), "null_matrix");
+%!assert (typeinfo (""), "null_string");
+%!assert (typeinfo (''), "null_sq_string");
+
+%!assert (typeinfo (1), "scalar");
+%!assert (typeinfo (double (1)), "scalar");
+%!assert (typeinfo ([1, 2]), "matrix");
+%!assert (typeinfo (double ([1, 2])), "matrix");
+
+%!assert (typeinfo (i), "complex scalar");
+%!assert (typeinfo ([i, 2]), "complex matrix");
+
+%!assert (typeinfo (single (1)), "float scalar");
+%!assert (typeinfo (single ([1, 2])), "float matrix");
+
+%!assert (typeinfo (single (i)), "float complex scalar");
+%!assert (typeinfo (single ([i, 2])), "float complex matrix");
+
+%!assert (typeinfo (sparse (eye (10))), "sparse matrix");
+%!assert (typeinfo (sparse (i * eye (10))), "sparse complex matrix");
+%!assert (typeinfo (logical (sparse (i * eye (10)))), "sparse bool matrix");
+
+%!assert (typeinfo (int8 (1)), "int8 scalar");
+%!assert (typeinfo (int16 (1)), "int16 scalar");
+%!assert (typeinfo (int32 (1)), "int32 scalar");
+%!assert (typeinfo (int64 (1)), "int64 scalar");
+%!assert (typeinfo (uint8 (1)), "uint8 scalar");
+%!assert (typeinfo (uint16 (1)), "uint16 scalar");
+%!assert (typeinfo (uint32 (1)), "uint32 scalar");
+%!assert (typeinfo (uint64 (1)), "uint64 scalar");
+
+%!test
+%! s.a = 1;
+%! assert (typeinfo (s), "scalar struct");
+
+%!test
+%! s(2).a = 1;
+%! assert (typeinfo (s), "struct");
+
+%!assert (typeinfo ({"cell"}), "cell");
+
+%!assert (typeinfo (@sin), "function handle");
+%!assert (typeinfo (@(x) x), "function handle");
+
+%!assert (typeinfo (inline ('x^2')), "inline function");
+
+%!test
+%! [l, u, p] = lu (rand (3));
+%! assert (typeinfo (p), "permutation matrix");
+*/
--- a/src/ov-uint16.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/ov-uint16.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -82,3 +82,15 @@
 {
   OCTAVE_TYPE_CONV_BODY (uint16);
 }
+
+/*
+
+%!assert (class (uint16 (1)), "uint16")
+%!assert (uint16 (1.25), uint16 (1))
+%!assert (uint16 (1.5), uint16 (2))
+%!assert (uint16 (-1.5), uint16 (0))
+%!assert (uint16 (2^17), uint16 (2^16-1))
+%!assert (uint16 (-2^17), uint16 (0))
+
+*/
+
--- a/src/ov-uint32.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/ov-uint32.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -82,3 +82,14 @@
 {
   OCTAVE_TYPE_CONV_BODY (uint32);
 }
+
+/*
+
+%!assert (class (uint32 (1)), "uint32")
+%!assert (uint32 (1.25), uint32 (1))
+%!assert (uint32 (1.5), uint32 (2))
+%!assert (uint32 (-1.5), uint32 (0))
+%!assert (uint32 (2^33), uint32 (2^32-1))
+%!assert (uint32 (-2^33), uint32 (0))
+
+*/
--- a/src/ov-uint64.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/ov-uint64.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -82,3 +82,14 @@
 {
   OCTAVE_TYPE_CONV_BODY (uint64);
 }
+
+/*
+
+%!assert (class (uint64 (1)), "uint64")
+%!assert (uint64 (1.25), uint64 (1))
+%!assert (uint64 (1.5), uint64 (2))
+%!assert (uint64 (-1.5), uint64 (0))
+%!assert (uint64 (2^65), uint64 (2^64-1))
+%!assert (uint64 (-2^65), uint64 (0))
+
+*/
--- a/src/ov-uint8.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/ov-uint8.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -82,3 +82,14 @@
 {
   OCTAVE_TYPE_CONV_BODY (uint8);
 }
+
+/*
+
+%!assert (class (uint8 (1)), "uint8")
+%!assert (uint8 (1.25), uint8 (1))
+%!assert (uint8 (1.5), uint8 (2))
+%!assert (uint8 (-1.5), uint8 (0))
+%!assert (uint8 (2^9), uint8 (2^8-1))
+%!assert (uint8 (-2^9), uint8 (0))
+
+*/
--- a/src/ov-usr-fcn.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/ov-usr-fcn.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -24,6 +24,8 @@
 #include <config.h>
 #endif
 
+#include <sstream>
+
 #include "str-vec.h"
 
 #include <defaults.h>
@@ -47,6 +49,7 @@
 #include "unwind-prot.h"
 #include "utils.h"
 #include "parse.h"
+#include "profiler.h"
 #include "variables.h"
 
 // Whether to optimize subsasgn method calls.
@@ -131,7 +134,9 @@
                   frame.protect_var (tree_evaluator::statement_context);
                   tree_evaluator::statement_context = tree_evaluator::script;
 
+                  BEGIN_PROFILER_BLOCK (profiler_name ())
                   cmd_list->accept (*current_evaluator);
+                  END_PROFILER_BLOCK
 
                   if (tree_return_command::returning)
                     tree_return_command::returning = 0;
@@ -176,6 +181,7 @@
   : octave_user_code (std::string (), std::string ()),
     param_list (pl), ret_list (rl), cmd_list (cl),
     lead_comm (), trail_comm (), file_name (),
+    location_line (0), location_column (0),
     parent_name (), t_parsed (static_cast<time_t> (0)),
     t_checked (static_cast<time_t> (0)),
     system_fcn_file (false), call_depth (-1),
@@ -217,6 +223,22 @@
   file_name = nm;
 }
 
+std::string
+octave_user_function::profiler_name (void) const
+{
+  std::ostringstream result;
+
+  if (is_inline_function ())
+    result << "anonymous@" << fcn_file_name ()
+           << ":" << location_line << ":" << location_column;
+  else if (is_subfunction ())
+    result << parent_fcn_name () << ">" << name ();
+  else
+    result << name ();
+
+  return result.str ();
+}
+
 void
 octave_user_function::mark_as_system_fcn_file (void)
 {
@@ -431,6 +453,8 @@
   bool special_expr = (is_inline_function ()
                        || cmd_list->is_anon_function_body ());
 
+  BEGIN_PROFILER_BLOCK (profiler_name ())
+
   if (special_expr)
     {
       assert (cmd_list->length () == 1);
@@ -448,6 +472,8 @@
   else
     cmd_list->accept (*current_evaluator);
 
+  END_PROFILER_BLOCK
+
   if (echo_commands)
     print_code_function_trailer ();
 
--- a/src/ov-usr-fcn.h	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/ov-usr-fcn.h	Tue Sep 20 15:38:24 2011 -0400
@@ -189,6 +189,12 @@
 
   void stash_fcn_file_name (const std::string& nm);
 
+  void stash_fcn_location (int line, int col)
+    {
+      location_line = line;
+      location_column = col;
+    }
+
   void stash_parent_fcn_name (const std::string& p) { parent_name = p; }
 
   void stash_parent_fcn_scope (symbol_table::scope_id ps) { parent_scope = ps; }
@@ -207,6 +213,8 @@
 
   std::string fcn_file_name (void) const { return file_name; }
 
+  std::string profiler_name (void) const;
+
   std::string parent_fcn_name (void) const { return parent_name; }
 
   symbol_table::scope_id parent_fcn_scope (void) const { return parent_scope; }
@@ -344,6 +352,10 @@
   // The name of the file we parsed.
   std::string file_name;
 
+  // Location where this function was defined.
+  int location_line;
+  int location_column;
+
   // The name of the parent function, if any.
   std::string parent_name;
 
--- a/src/ov.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/ov.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -2690,25 +2690,6 @@
   octave_lazy_index::register_type ();
 }
 
-#if 0
-DEFUN (cast, args, ,
-  "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {} cast (@var{val}, @var{type})\n\
-Convert @var{val} to the new data type @var{type}.\n\
-@seealso{class, typeinfo}\n\
-@end deftypefn")
-{
-  octave_value retval;
-
-  if (args.length () == 2)
-    error ("cast: not implemented");
-  else
-    print_usage ();
-
-  return retval;
-}
-#endif
-
 DEFUN (sizeof, args, ,
   "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} sizeof (@var{val})\n\
@@ -2726,6 +2707,12 @@
   return retval;
 }
 
+/*
+%!assert (sizeof (uint64 (ones (3))), 72)
+%!assert (sizeof (double (zeros (2,4))), 64)
+%!assert (sizeof ({"foo", "bar", "baaz"}), 10)
+*/
+
 DEFUN (subsref, args, nargout,
   "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} subsref (@var{val}, @var{idx})\n\
@@ -2834,3 +2821,63 @@
 
   return retval;
 }
+
+/*
+%!test
+%! a = reshape ([1:25], 5,5);
+%! idx1 = substruct ( "()", {3, 3});
+%! idx2 = substruct ( "()", {2:2:5, 2:2:5});
+%! idx3 = substruct ( "()", {":", [1,5]});
+%! assert (subsref (a, idx1), 13)
+%! assert (subsref (a, idx2), [7 17; 9 19])
+%! assert (subsref (a, idx3), [1:5; 21:25]')
+%! a = subsasgn (a, idx1, 0);
+%! a = subsasgn (a, idx2, 0);
+%! a = subsasgn (a, idx3, 0);
+%! b = [0    6   11   16    0
+%!      0    0   12    0    0
+%!      0    8    0   18    0
+%!      0    0   14    0    0
+%!      0   10   15   20    0];
+%! assert (a,b);
+
+%!test
+%! c = num2cell (reshape ([1:25],5,5));
+%! idx1 = substruct  ( "{}", {3, 3});
+%! idx2 = substruct  ( "()", {2:2:5, 2:2:5});
+%! idx3 = substruct  ( "()", {":", [1,5]});
+%! idx2p = substruct  ( "{}", {2:2:5, 2:2:5});
+%! idx3p = substruct  ( "{}", {":", [1,5]});
+%! assert ({ subsref(c, idx1) }, {13})
+%! assert ({ subsref(c, idx2p) }, {7 9 17 19})
+%! assert ({ subsref(c, idx3p) }, num2cell ([1:5, 21:25]))
+%! c = subsasgn (c, idx1, 0);
+%! c = subsasgn (c, idx2, 0);
+%! c = subsasgn (c, idx3, 0);
+%! d = {0    6   11   16    0
+%!      0    0   12    0    0
+%!      0    8    0   18    0
+%!      0    0   14    0    0
+%!      0   10   15   20    0};
+%! assert (c,d);
+
+%!test
+%! s.a = "ohai";
+%! s.b = "dere";
+%! s.c = 42;
+%! idx1 = substruct (".", "a");
+%! idx2 = substruct (".", "b");
+%! idx3 = substruct (".", "c");
+%! assert (subsref (s, idx1), "ohai")
+%! assert (subsref (s, idx2), "dere")
+%! assert (subsref (s, idx3), 42)
+%! s = subsasgn (s, idx1, "Hello");
+%! s = subsasgn (s, idx2, "There");
+%! s = subsasgn (s, idx3, 163);
+%! t.a = "Hello";
+%! t.b = "There";
+%! t.c = 163;
+%! assert (s, t)
+
+*/
+
--- a/src/ov.h	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/ov.h	Tue Sep 20 15:38:24 2011 -0400
@@ -987,9 +987,8 @@
   bool print_name_tag (std::ostream& os, const std::string& name) const
     { return rep->print_name_tag (os, name); }
 
-  void print_with_name (std::ostream& os, const std::string& name,
-                        bool print_padding = true) const
-    { rep->print_with_name (os, name, print_padding); }
+  void print_with_name (std::ostream& os, const std::string& name) const
+  { rep->print_with_name (os, name, true); }
 
   int type_id (void) const { return rep->type_id (); }
 
--- a/src/pr-output.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/pr-output.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -103,7 +103,7 @@
 static int bit_format = 0;
 
 // TRUE means don't put newlines around the column number headers.
-static bool compact_format = false;
+bool Vcompact_format = false;
 
 // TRUE means use an e format.
 static bool print_e = false;
@@ -1658,7 +1658,7 @@
          << std::resetiosflags (std::ios::scientific|std::ios::left)
          << " *\n";
 
-      if (! compact_format)
+      if (! Vcompact_format)
         os << "\n";
     }
 }
@@ -1671,7 +1671,7 @@
     {
       if (col != 0)
         {
-          if (compact_format)
+          if (Vcompact_format)
             os << "\n";
           else
             os << "\n\n";
@@ -1688,7 +1688,7 @@
       else
         os << " Columns " << col + 1 << " through " << lim << ":\n";
 
-      if (! compact_format)
+      if (! Vcompact_format)
         os << "\n";
     }
 }
@@ -1956,7 +1956,10 @@
         }
       else
         {
-          os << "Diagonal Matrix\n\n";
+          os << "Diagonal Matrix\n";
+          if (! Vcompact_format)
+            os << "\n";
+
           pr_scale_header (os, scale);
 
           // kluge. Get the true width of a number.
@@ -1999,80 +2002,82 @@
         }
     }
 }
-#define PRINT_ND_ARRAY(os, nda, NDA_T, ELT_T, MAT_T) \
-  do \
-    { \
-      if (nda.is_empty ()) \
-        print_empty_nd_array (os, nda.dims (), pr_as_read_syntax); \
-      else \
-        { \
- \
-          int ndims = nda.ndims (); \
- \
-          dim_vector dims = nda.dims (); \
- \
-          Array<octave_idx_type> ra_idx (dim_vector (ndims, 1), 0);\
- \
-          octave_idx_type m = 1; \
- \
-          for (int i = 2; i < ndims; i++) \
-            m *= dims(i); \
- \
-          octave_idx_type nr = dims(0); \
-          octave_idx_type nc = dims(1); \
- \
-          for (octave_idx_type i = 0; i < m; i++) \
-            { \
-              octave_quit (); \
- \
-              std::string nm = "ans"; \
- \
-              if (m > 1) \
-                { \
-                  nm += "(:,:,"; \
- \
-                  std::ostringstream buf; \
- \
-                  for (int k = 2; k < ndims; k++) \
-                    { \
-                      buf << ra_idx(k) + 1; \
- \
-                      if (k < ndims - 1) \
-                        buf << ","; \
-                      else \
-                        buf << ")"; \
-                    } \
- \
-                  nm += buf.str (); \
-                } \
- \
-              Array<idx_vector> idx (dim_vector (ndims, 1)); \
- \
-              idx(0) = idx_vector (':'); \
-              idx(1) = idx_vector (':'); \
- \
-              for (int k = 2; k < ndims; k++) \
-                idx(k) = idx_vector (ra_idx(k)); \
- \
-              octave_value page \
-                = MAT_T (Array<ELT_T> (nda.index (idx), dim_vector (nr, nc))); \
- \
-              if (i != m - 1) \
-                { \
-                  page.print_with_name (os, nm); \
-                } \
-              else \
-                { \
-                  page.print_name_tag (os, nm); \
-                  page.print_raw (os); \
-                } \
-              \
-              if (i < m) \
-                NDA_T::increment_index (ra_idx, dims, 2); \
-            } \
-        } \
-    } \
-  while (0)
+
+template <typename NDA_T, typename ELT_T, typename MAT_T>
+void print_nd_array(std::ostream& os, const NDA_T& nda,
+                    bool pr_as_read_syntax)
+{
+
+  if (nda.is_empty ())
+    print_empty_nd_array (os, nda.dims (), pr_as_read_syntax);
+  else
+    {
+
+      int ndims = nda.ndims ();
+
+      dim_vector dims = nda.dims ();
+
+      Array<octave_idx_type> ra_idx (dim_vector (ndims, 1), 0);
+
+      octave_idx_type m = 1;
+
+      for (int i = 2; i < ndims; i++)
+        m *= dims(i);
+
+      octave_idx_type nr = dims(0);
+      octave_idx_type nc = dims(1);
+
+      for (octave_idx_type i = 0; i < m; i++)
+        {
+          octave_quit ();
+
+          std::string nm = "ans";
+
+          if (m > 1)
+            {
+              nm += "(:,:,";
+
+              std::ostringstream buf;
+
+              for (int k = 2; k < ndims; k++)
+                {
+                  buf << ra_idx(k) + 1;
+
+                  if (k < ndims - 1)
+                    buf << ",";
+                  else
+                    buf << ")";
+                }
+
+              nm += buf.str ();
+            }
+
+          Array<idx_vector> idx (dim_vector (ndims, 1));
+
+          idx(0) = idx_vector (':');
+          idx(1) = idx_vector (':');
+
+          for (int k = 2; k < ndims; k++)
+            idx(k) = idx_vector (ra_idx(k));
+
+          octave_value page
+            = MAT_T (Array<ELT_T> (nda.index (idx), dim_vector (nr, nc)));
+
+          if (i != m - 1)
+            {
+              page.print_with_name (os, nm);
+            }
+          else
+            {
+              page.print_name_tag (os, nm);
+              page.print_raw (os);
+            }
+
+          if (i < m)
+            NDA_T::increment_index (ra_idx, dims, 2);
+        }
+    }
+}
 
 void
 octave_print_internal (std::ostream& os, const NDArray& nda,
@@ -2087,7 +2092,7 @@
       break;
 
     default:
-      PRINT_ND_ARRAY (os, nda, NDArray, double, Matrix);
+      print_nd_array <NDArray, double, Matrix> (os, nda, pr_as_read_syntax);
       break;
     }
 }
@@ -2367,7 +2372,10 @@
         }
       else
         {
-          os << "Diagonal Matrix\n\n";
+          os << "Diagonal Matrix\n";
+          if (! Vcompact_format)
+            os << "\n";
+
           pr_scale_header (os, scale);
 
           // kluge. Get the true width of a number.
@@ -2512,7 +2520,9 @@
         }
       else
         {
-          os << "Permutation Matrix\n\n";
+          os << "Permutation Matrix\n";
+          if (! Vcompact_format)
+            os << "\n";
 
           for (octave_idx_type col = 0; col < nc; col += inc)
             {
@@ -2555,7 +2565,8 @@
       break;
 
     default:
-      PRINT_ND_ARRAY (os, nda, ComplexNDArray, Complex, ComplexMatrix);
+      print_nd_array <ComplexNDArray, Complex,
+                      ComplexMatrix> (os, nda, pr_as_read_syntax);
       break;
     }
 }
@@ -2756,7 +2767,8 @@
       break;
 
     default:
-      PRINT_ND_ARRAY (os, nda, boolNDArray, bool, boolMatrix);
+      print_nd_array<boolNDArray, bool,
+                     boolMatrix> (os, nda, pr_as_read_syntax);
       break;
     }
 }
@@ -2822,7 +2834,8 @@
       break;
 
     default:
-      PRINT_ND_ARRAY (os, nda, charNDArray, char, charMatrix);
+      print_nd_array <charNDArray, char,
+                      charMatrix> (os, nda, pr_as_read_syntax);
       break;
     }
 }
@@ -2840,8 +2853,8 @@
 octave_print_internal (std::ostream& os, const Array<std::string>& nda,
                        bool pr_as_read_syntax, int /* extra_indent */)
 {
-  // FIXME -- this mostly duplicates the code in the
-  // PRINT_ND_ARRAY macro.
+  // FIXME -- this mostly duplicates the code in the print_nd_array<>
+  // function. Can fix this with std::is_same from C++11.
 
   if (nda.is_empty ())
     print_empty_nd_array (os, nda.dims (), pr_as_read_syntax);
@@ -2904,7 +2917,9 @@
           octave_idx_type n_rows = page.rows ();
           octave_idx_type n_cols = page.cols ();
 
-          os << nm << " =\n\n";
+          os << nm << " =\n";
+          if (! Vcompact_format)
+            os << "\n";
 
           for (octave_idx_type ii = 0; ii < n_rows; ii++)
             {
@@ -3109,8 +3124,8 @@
 octave_print_internal_template (std::ostream& os, const intNDArray<T>& nda,
                                 bool pr_as_read_syntax, int extra_indent)
 {
-  // FIXME -- this mostly duplicates the code in the
-  // PRINT_ND_ARRAY macro.
+  // FIXME -- this mostly duplicates the code in the print_nd_array<>
+  // function. Can fix this with std::is_same from C++11.
 
   if (nda.is_empty ())
     print_empty_nd_array (os, nda.dims (), pr_as_read_syntax);
@@ -3152,7 +3167,9 @@
 
               nm += buf.str ();
 
-              os << nm << " =\n\n";
+              os << nm << " =\n";
+              if (! Vcompact_format)
+                os << "\n";
             }
 
           Array<idx_vector> idx (dim_vector (ndims, 1));
@@ -3257,7 +3274,9 @@
 
               nm += buf.str ();
 
-              os << nm << " =\n\n";
+              os << nm << " =\n";
+              if (! Vcompact_format)
+                os << "\n";
             }
 
           Array<idx_vector> idx (dim_vector (ndims, 1));
@@ -3528,6 +3547,21 @@
 %!   endfor
 %! endfor
 %! fclose (fd);
+
+%!test
+%! foo.real = pi * ones (3,20,3);
+%! foo.complex = pi * ones (3,20,3) + 1i;
+%! foo.char = repmat ("- Hello World -", [3, 20]);
+%! foo.cell = {foo.real, foo.complex, foo.char};
+%! fields = fieldnames (foo);
+%! for f = 1:numel(fields)
+%!   format loose
+%!   loose = disp (foo.(fields{f}));
+%!   format compact
+%!   compact = disp (foo.(fields{f}));
+%!   expected = strrep (loose, "\n\n", "\n");
+%!   assert (expected, compact)
+%! endfor
 */
 
 static void
@@ -3539,7 +3573,7 @@
   bank_format = false;
   hex_format = 0;
   bit_format = 0;
-  compact_format = false;
+  Vcompact_format = false;
   print_e = false;
   print_big_e = false;
   print_g = false;
@@ -3714,11 +3748,11 @@
         }
       else if (arg == "compact")
         {
-          compact_format = true;
+          Vcompact_format = true;
         }
       else if (arg == "loose")
         {
-          compact_format = false;
+          Vcompact_format = false;
         }
       else
         error ("format: unrecognized format state `%s'", arg.c_str ());
@@ -3890,12 +3924,12 @@
 \n\
 @table @code\n\
 @item compact\n\
-Remove extra blank space around column number labels producing more compact\n\
-output with more data per page.\n\
+Remove blank lines around column number labels and between\n\
+matrices producing more compact output with more data per page.\n\
 \n\
 @item loose\n\
-Insert blank lines above and below column number labels to produce a more\n\
-readable output with less data per page.  (default).\n\
+Insert blank lines above and below column number labels and between matrices\n\
+to produce a more readable output with less data per page.  (default).\n\
 @end table\n\
 @seealso{fixed_point_format, output_max_field_width, output_precision, split_long_rows, rats}\n\
 @end deftypefn")
--- a/src/pr-output.h	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/pr-output.h	Tue Sep 20 15:38:24 2011 -0400
@@ -256,4 +256,7 @@
 // like this: x = [](2x0).
 extern bool Vprint_empty_dimensions;
 
+// TRUE means don't put empty lines in output
+extern bool Vcompact_format;
+
 #endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/profiler.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,459 @@
+/*
+
+Copyright (C) 2011 Daniel Kraft
+
+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 3 of the License, 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, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <cstddef>
+#include <iostream>
+
+#include "defun.h"
+#include "oct-time.h"
+#include "ov-struct.h"
+#include "pager.h"
+#include "profiler.h"
+
+profile_data_accumulator::enter::enter (profile_data_accumulator& a,
+                                        const std::string& f)
+  : acc (a)
+{
+  if (acc.is_active ())
+    {
+      fcn = f;
+      acc.enter_function (fcn);
+    }
+  else
+    fcn = "";
+}
+
+profile_data_accumulator::enter::~enter ()
+{
+  if (fcn != "")
+    acc.exit_function (fcn);
+}
+
+profile_data_accumulator::stats::stats ()
+  : time (0.0), calls (0), recursive (false),
+    parents (), children ()
+{}
+
+octave_value
+profile_data_accumulator::stats::function_set_value (const function_set& list)
+{
+  const octave_idx_type n = list.size ();
+
+  RowVector retval (n);
+  octave_idx_type i = 0;
+  for (function_set::const_iterator p = list.begin (); p != list.end (); ++p)
+    {
+      retval(i) = *p;
+      ++i;
+    }
+  assert (i == n);
+
+  return retval;
+}
+
+profile_data_accumulator::tree_node::tree_node (tree_node* p, octave_idx_type f)
+  : parent (p), fcn_id (f), children (), time (0.0), calls (0)
+{}
+
+profile_data_accumulator::tree_node::~tree_node ()
+{
+  for (child_map::iterator i = children.begin (); i != children.end (); ++i)
+    delete i->second;
+}
+
+profile_data_accumulator::tree_node*
+profile_data_accumulator::tree_node::enter (octave_idx_type fcn)
+{
+  tree_node* retval;
+
+  child_map::iterator pos = children.find (fcn);
+  if (pos == children.end ())
+    {
+      retval = new tree_node (this, fcn);
+      children[fcn] = retval;
+    }
+  else
+    retval = pos->second;
+
+  ++retval->calls;
+  return retval;
+}
+
+profile_data_accumulator::tree_node*
+profile_data_accumulator::tree_node::exit (octave_idx_type fcn)
+{
+  assert (parent);
+  assert (fcn_id == fcn);
+
+  return parent;
+}
+
+void
+profile_data_accumulator::tree_node::build_flat (flat_profile& data) const
+{
+  // If this is not the top-level node, update profile entry for this function.
+  if (fcn_id != 0)
+    {
+      stats& entry = data[fcn_id - 1];
+
+      entry.time += time;
+      entry.calls += calls;
+
+      assert (parent);
+      if (parent->fcn_id != 0)
+        {
+          entry.parents.insert (parent->fcn_id);
+          data[parent->fcn_id - 1].children.insert (fcn_id);
+        }
+
+      if (!entry.recursive)
+        for (const tree_node* i = parent; i; i = i->parent)
+          if (i->fcn_id == fcn_id)
+            {
+              entry.recursive = true;
+              break;
+            }
+    }
+
+  // Recurse on children.
+  for (child_map::const_iterator i = children.begin ();
+       i != children.end (); ++i)
+    i->second->build_flat (data);
+}
+
+octave_value
+profile_data_accumulator::tree_node::get_hierarchical (void) const
+{
+  /* Note that we don't generate the entry just for this node, but rather
+     a struct-array with entries for all children.  This way, the top-node
+     (for which we don't want a real entry) generates already the final
+     hierarchical profile data.  */
+
+  const octave_idx_type n = children.size ();
+
+  Cell rv_indices (n, 1);
+  Cell rv_times (n, 1);
+  Cell rv_calls (n, 1);
+  Cell rv_children (n, 1);
+
+  octave_idx_type i = 0;
+  for (child_map::const_iterator p = children.begin ();
+       p != children.end (); ++p)
+    {
+      const tree_node& entry = *p->second;
+
+      rv_indices(i) = octave_value (p->first);
+      rv_times(i) = octave_value (entry.time);
+      rv_calls(i) = octave_value (entry.calls);
+      rv_children(i) = entry.get_hierarchical ();
+
+      ++i;
+    }
+  assert (i == n);
+
+  octave_map retval;
+
+  retval.assign ("Index", rv_indices);
+  retval.assign ("SelfTime", rv_times);
+  retval.assign ("NumCalls", rv_calls);
+  retval.assign ("Children", rv_children);
+
+  return retval;
+}
+
+profile_data_accumulator::profile_data_accumulator ()
+  : known_functions (), fcn_index (),
+    enabled (false), call_tree (NULL), last_time (-1.0)
+{}
+
+profile_data_accumulator::~profile_data_accumulator ()
+{
+  if (call_tree)
+    delete call_tree;
+}
+
+void
+profile_data_accumulator::set_active (bool value)
+{
+  if (value)
+    {
+      // Create a call-tree top-node if there isn't yet one.
+      if (!call_tree)
+        call_tree = new tree_node (NULL, 0);
+
+      // Let the top-node be the active one.  This ensures we have a clean
+      // fresh start collecting times.
+      active_fcn = call_tree;
+    }
+  else
+    {
+      // Make sure we start with fresh timing if we're re-enabled later.
+      last_time = -1.0;
+    }
+
+  enabled = value;
+}
+
+void
+profile_data_accumulator::enter_function (const std::string& fcn)
+{
+  // The enter class will check and only call us if the profiler is active.
+  assert (is_active ());
+  assert (call_tree);
+
+  // If there is already an active function, add to its time before
+  // pushing the new one.
+  if (active_fcn != call_tree)
+    add_current_time ();
+
+  // Map the function's name to its index.
+  octave_idx_type fcn_idx;
+  fcn_index_map::iterator pos = fcn_index.find (fcn);
+  if (pos == fcn_index.end ())
+    {
+      known_functions.push_back (fcn);
+      fcn_idx = known_functions.size ();
+      fcn_index[fcn] = fcn_idx;
+    }
+  else
+    fcn_idx = pos->second;
+
+  active_fcn = active_fcn->enter (fcn_idx);
+  last_time = query_time ();
+}
+
+void
+profile_data_accumulator::exit_function (const std::string& fcn)
+{
+  assert (call_tree);
+  assert (active_fcn != call_tree);
+
+  // Usually, if we are disabled this function is not even called.  But the
+  // call disabling the profiler is an exception.  So also check here
+  // and only record the time if enabled.
+  if (is_active ())
+    add_current_time ();
+
+  fcn_index_map::iterator pos = fcn_index.find (fcn);
+  assert (pos != fcn_index.end ());
+  active_fcn = active_fcn->exit (pos->second);
+
+  // If this was an "inner call", we resume executing the parent function
+  // up the stack.  So note the start-time for this!
+  last_time = query_time ();
+}
+
+void
+profile_data_accumulator::reset (void)
+{
+  if (is_active ())
+    {
+      error ("Can't reset active profiler.");
+      return;
+    }
+
+  known_functions.clear ();
+  fcn_index.clear ();
+
+  if (call_tree)
+    {
+      delete call_tree;
+      call_tree = NULL;
+    }
+
+  last_time = -1.0;
+}
+
+octave_value
+profile_data_accumulator::get_flat (void) const
+{
+  octave_value retval;
+
+  const octave_idx_type n = known_functions.size ();
+
+  flat_profile flat (n);
+
+  if (call_tree)
+    {
+      call_tree->build_flat (flat);
+
+      Cell rv_names (n, 1);
+      Cell rv_times (n, 1);
+      Cell rv_calls (n, 1);
+      Cell rv_recursive (n, 1);
+      Cell rv_parents (n, 1);
+      Cell rv_children (n, 1);
+
+      for (octave_idx_type i = 0; i != n; ++i)
+        {
+          rv_names(i) = octave_value (known_functions[i]);
+          rv_times(i) = octave_value (flat[i].time);
+          rv_calls(i) = octave_value (flat[i].calls);
+          rv_recursive(i) = octave_value (flat[i].recursive);
+          rv_parents(i) = stats::function_set_value (flat[i].parents);
+          rv_children(i) = stats::function_set_value (flat[i].children);
+        }
+
+      octave_map m;
+
+      m.assign ("FunctionName", rv_names);
+      m.assign ("TotalTime", rv_times);
+      m.assign ("NumCalls", rv_calls);
+      m.assign ("IsRecursive", rv_recursive);
+      m.assign ("Parents", rv_parents);
+      m.assign ("Children", rv_children);
+
+      retval = m;
+    }
+  else
+    {
+      static const char *fn[] =
+        {
+          "FunctionName",
+          "TotalTime",
+          "NumCalls",
+          "IsRecursive",
+          "Parents",
+          "Children",
+          0
+        };
+
+      static octave_map m (dim_vector (0, 1), string_vector (fn));
+
+      retval = m;
+    }
+
+  return retval;
+}
+
+octave_value
+profile_data_accumulator::get_hierarchical (void) const
+{
+  octave_value retval;
+
+  if (call_tree)
+    retval = call_tree->get_hierarchical ();
+  else
+    {
+      static const char *fn[] =
+        {
+          "Index",
+          "SelfTime",
+          "NumCalls",
+          "Children",
+          0
+        };
+
+      static octave_map m (dim_vector (0, 1), string_vector (fn));
+
+      retval = m;
+    }
+
+  return retval;
+}
+
+double
+profile_data_accumulator::query_time (void) const
+{
+  octave_time now;
+  return now.double_value ();
+}
+
+void
+profile_data_accumulator::add_current_time (void)
+{
+  const double t = query_time ();
+  assert (last_time >= 0.0 && last_time <= t);
+
+  assert (call_tree && active_fcn != call_tree);
+  active_fcn->add_time (t - last_time);
+}
+
+profile_data_accumulator profiler;
+
+// Enable or disable the profiler data collection.
+DEFUN (__profiler_enable__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Function File} __profiler_enable ()\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value_list retval;
+
+  const int nargin = args.length ();
+  if (nargin > 0)
+    {
+      if (nargin > 1)
+        {
+          print_usage ();
+          return retval;
+        }
+
+      profiler.set_active (args(0).bool_value ());
+    }
+
+  retval(0) = profiler.is_active ();
+
+  return retval;
+}
+
+// Clear all collected profiling data.
+DEFUN (__profiler_reset__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Function File} __profiler_reset ()\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value_list retval;
+  const int nargin = args.length ();
+
+  if (nargin > 0)
+    warning ("profiler_reset: ignoring extra arguments");
+
+  profiler.reset ();
+
+  return retval;
+}
+
+// Query the timings collected by the profiler.
+DEFUN (__profiler_data__, args, nargout,
+  "-*- texinfo -*-\n\
+@deftypefn {Function File} __profiler_data ()\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value_list retval;
+  const int nargin = args.length ();
+
+  if (nargin > 0)
+    warning ("profiler_data: ignoring extra arguments");
+
+  retval(0) = profiler.get_flat ();
+  if (nargout > 1)
+    retval(1) = profiler.get_hierarchical ();
+
+  return retval;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/profiler.h	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,185 @@
+/*
+
+Copyright (C) 2011 Daniel Kraft
+
+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 3 of the License, 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, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_profiler_h)
+#define octave_profiler_h 1
+
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+class octave_value;
+
+class
+OCTINTERP_API
+profile_data_accumulator
+{
+public:
+
+  // This is a utility class that can be used to call the enter/exit
+  // functions in a manner protected from stack unwinding.
+  class enter
+  {
+  private:
+
+    profile_data_accumulator& acc;
+    std::string fcn;
+
+  public:
+
+    enter (profile_data_accumulator&, const std::string&);
+    virtual ~enter (void);
+
+  private:
+
+    // No copying!
+    enter (const enter&);
+    enter& operator = (const enter&);
+  };
+
+  profile_data_accumulator (void);
+  virtual ~profile_data_accumulator ();
+
+  bool is_active (void) const { return enabled; }
+  void set_active (bool);
+
+  void reset (void);
+
+  octave_value get_flat (void) const;
+  octave_value get_hierarchical (void) const;
+
+private:
+
+  // One entry in the flat profile (i.e., a collection of data for a single
+  // function).  This is filled in when building the flat profile from the
+  // hierarchical call tree.
+  struct stats
+  {
+    stats ();
+
+    double time;
+    unsigned calls;
+
+    bool recursive;
+
+    typedef std::set<octave_idx_type> function_set;
+    function_set parents;
+    function_set children;
+
+    // Convert a function_set list to an Octave array of indices.
+    static octave_value function_set_value (const function_set&);
+  };
+
+  typedef std::vector<stats> flat_profile;
+
+  // Store data for one node in the call-tree of the hierarchical profiler
+  // data we collect.
+  class tree_node
+  {
+  public:
+
+    tree_node (tree_node*, octave_idx_type);
+    virtual ~tree_node ();
+
+    void add_time (double dt) { time += dt; }
+
+    // Enter a child function.  It is created in the list of children if it
+    // wasn't already there.  The now-active child node is returned.
+    tree_node* enter (octave_idx_type);
+
+    // Exit function.  As a sanity-check, it is verified that the currently
+    // active function actually is the one handed in here.  Returned is the
+    // then-active node, which is our parent.
+    tree_node* exit (octave_idx_type);
+
+    void build_flat (flat_profile&) const;
+    octave_value get_hierarchical (void) const;
+
+  private:
+
+    tree_node* parent;
+    octave_idx_type fcn_id;
+
+    typedef std::map<octave_idx_type, tree_node*> child_map;
+    child_map children;
+
+    // This is only time spent *directly* on this level, excluding children!
+    double time;
+
+    unsigned calls;
+
+    // No copying!
+    tree_node (const tree_node&);
+    tree_node& operator = (const tree_node&);
+  };
+
+  // Each function we see in the profiler is given a unique index (which
+  // simply counts starting from 1).  We thus have to map profiler-names to
+  // those indices.  For all other stuff, we identify functions by their index.
+
+  typedef std::vector<std::string> function_set;
+  typedef std::map<std::string, octave_idx_type> fcn_index_map;
+
+  function_set known_functions;
+  fcn_index_map fcn_index;
+
+  bool enabled;
+
+  tree_node* call_tree;
+  tree_node* active_fcn;
+
+  // Store last timestamp we had, when the currently active function was called.
+  double last_time;
+
+  // These are private as only the unwind-protecting inner class enter
+  // should be allowed to call them.
+  void enter_function (const std::string&);
+  void exit_function (const std::string&);
+
+  // Query a timestamp, used for timing calls (obviously).
+  // This is not static because in the future, maybe we want a flag
+  // in the profiler or something to choose between cputime, wall-time,
+  // user-time, system-time, ...
+  double query_time () const;
+
+  // Add the time elapsed since last_time to the function we're currently in.
+  // This is called from two different positions, thus it is useful to have
+  // it as a seperate function.
+  void add_current_time (void);
+
+  // No copying!
+  profile_data_accumulator (const profile_data_accumulator&);
+  profile_data_accumulator& operator = (const profile_data_accumulator&);
+};
+
+// The instance used.
+extern OCTINTERP_API profile_data_accumulator profiler;
+
+// Helper macro to profile a block of code.
+#define BEGIN_PROFILER_BLOCK(name) \
+  { \
+    profile_data_accumulator::enter pe (profiler, (name));
+#define END_PROFILER_BLOCK \
+  }
+
+#endif
--- a/src/pt-binop.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/pt-binop.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -28,6 +28,7 @@
 #include "defun.h"
 #include "oct-obj.h"
 #include "ov.h"
+#include "profiler.h"
 #include "pt-binop.h"
 #include "pt-bp.h"
 #include "pt-walk.h"
@@ -120,10 +121,20 @@
 
           if (! error_state && b.is_defined ())
             {
+              BEGIN_PROFILER_BLOCK ("binary " + oper ())
+
+              // Note: The profiler does not catch the braindead
+              // short-circuit evaluation code above, but that should be
+              // ok. The evaluation of operands and the operator itself
+              // is entangled and it's not clear where to start/stop
+              // timing the operator to make it reasonable.
+
               retval = ::do_binary_op (etype, a, b);
 
               if (error_state)
                 retval = octave_value ();
+
+              END_PROFILER_BLOCK
             }
         }
     }
@@ -183,6 +194,11 @@
 
   bool result = false;
 
+  // This evaluation is not caught by the profiler, since we can't find
+  // a reasonable place where to time. Note that we don't want to
+  // include evaluation of LHS or RHS into the timing, but this is
+  // entangled together with short-circuit evaluation here.
+
   if (op_lhs)
     {
       octave_value a = op_lhs->rvalue1 ();
@@ -279,3 +295,19 @@
 {
   return SET_INTERNAL_VARIABLE (do_braindead_shortcircuit_evaluation);
 }
+
+/*
+
+%!test
+%! x = 0;
+%! do_braindead_shortcircuit_evaluation (0);
+%! if (1 | (x = 1))
+%! endif
+%! assert (x, 1);
+%! do_braindead_shortcircuit_evaluation (1);
+%! if (1 | (x = 0))
+%! endif
+%! assert (x, 1);
+
+*/
+
--- a/src/pt-eval.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/pt-eval.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -1202,6 +1202,17 @@
   return SET_INTERNAL_VARIABLE (max_recursion_depth);
 }
 
+/*
+%!error (max_recursion_depth (1, 2));
+%!test
+%! orig_val = max_recursion_depth ();
+%! old_val = max_recursion_depth (2*orig_val);
+%! assert (orig_val, old_val);
+%! assert (max_recursion_depth (), 2*orig_val);
+%! max_recursion_depth (orig_val);
+%! assert (max_recursion_depth (), orig_val);
+*/
+
 DEFUN (silent_functions, args, nargout,
   "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {@var{val} =} silent_functions ()\n\
@@ -1214,3 +1225,14 @@
 {
   return SET_INTERNAL_VARIABLE (silent_functions);
 }
+
+/*
+%!error (silent_functions (1, 2));
+%!test
+%! orig_val = silent_functions ();
+%! old_val = silent_functions (! orig_val);
+%! assert (orig_val, old_val);
+%! assert (silent_functions (), ! orig_val);
+%! silent_functions (orig_val);
+%! assert (silent_functions (), orig_val);
+*/
--- a/src/pt-fcn-handle.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/pt-fcn-handle.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -127,6 +127,8 @@
     }
 
   uf->mark_as_inline_function ();
+  uf->stash_fcn_file_name (file_name);
+  uf->stash_fcn_location (line (), column ());
 
   octave_value ov_fcn (uf);
 
--- a/src/pt-fcn-handle.h	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/pt-fcn-handle.h	Tue Sep 20 15:38:24 2011 -0400
@@ -92,13 +92,14 @@
 public:
 
   tree_anon_fcn_handle (int l = -1, int c = -1)
-    : tree_expression (l, c), fcn (0) { }
+    : tree_expression (l, c), fcn (0), file_name () { }
 
   tree_anon_fcn_handle (tree_parameter_list *pl, tree_parameter_list *rl,
                         tree_statement_list *cl, symbol_table::scope_id sid,
                         int l = -1, int c = -1)
     : tree_expression (l, c),
-      fcn (new octave_user_function (sid, pl, rl, cl)) { }
+      fcn (new octave_user_function (sid, pl, rl, cl)),
+      file_name () { }
 
   ~tree_anon_fcn_handle (void) { delete fcn; }
 
@@ -135,11 +136,16 @@
 
   void accept (tree_walker& tw);
 
+  void stash_file_name (const std::string& file) { file_name = file; }
+
 private:
 
   // The function.
   octave_user_function *fcn;
 
+  // Filename where the handle was defined.
+  std::string file_name;
+
   // No copying!
 
   tree_anon_fcn_handle (const tree_anon_fcn_handle&);
--- a/src/pt-mat.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/pt-mat.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -68,15 +68,17 @@
       : count (1), dv (0, 0), all_str (false),
         all_sq_str (false), all_dq_str (false),
         some_str (false), all_real (false), all_cmplx (false),
-        all_mt (true), any_sparse (false), any_class (false),
-        all_1x1 (false), class_nm (), ok (false)
+        all_mt (true), any_cell (false), any_sparse (false),
+        any_class (false), all_1x1 (false),
+        first_elem_is_struct (false), class_nm (), ok (false)
     { }
 
     tm_row_const_rep (const tree_argument_list& row)
       : count (1), dv (0, 0), all_str (false), all_sq_str (false),
         some_str (false), all_real (false), all_cmplx (false),
-        all_mt (true), any_sparse (false), any_class (false),
-        all_1x1 (! row.empty ()), class_nm (), ok (false)
+        all_mt (true), any_cell (false), any_sparse (false),
+        any_class (false), all_1x1 (! row.empty ()),
+        first_elem_is_struct (false), class_nm (), ok (false)
     { init (row); }
 
     ~tm_row_const_rep (void) { }
@@ -92,18 +94,22 @@
     bool all_real;
     bool all_cmplx;
     bool all_mt;
+    bool any_cell;
     bool any_sparse;
     bool any_class;
     bool all_1x1;
+    bool first_elem_is_struct;
 
     std::string class_nm;
 
     bool ok;
 
-    bool do_init_element (tree_expression *, const octave_value&, bool&);
+    void do_init_element (const octave_value&, bool&);
 
     void init (const tree_argument_list&);
 
+    void cellify (void);
+
   private:
 
     tm_row_const_rep (const tm_row_const_rep&);
@@ -169,12 +175,16 @@
   bool all_real_p (void) const { return rep->all_real; }
   bool all_complex_p (void) const { return rep->all_cmplx; }
   bool all_empty_p (void) const { return rep->all_mt; }
+  bool any_cell_p (void) const { return rep->any_cell; }
   bool any_sparse_p (void) const { return rep->any_sparse; }
   bool any_class_p (void) const { return rep->any_class; }
   bool all_1x1_p (void) const { return rep->all_1x1; }
+  bool first_elem_struct_p (void) const { return rep->first_elem_is_struct; }
 
   std::string class_name (void) const { return rep->class_nm; }
 
+  void cellify (void) { rep->cellify (); }
+
   operator bool () const { return (rep && rep->ok); }
 
   iterator begin (void) { return rep->begin (); }
@@ -199,6 +209,8 @@
     retval = c2;
   else if (c2.empty ())
     retval = c1;
+  else if (c1 == "class" || c2 == "class")
+    retval = "class";
   else
     {
       bool c1_is_int = (c1 == "int8" || c1 == "uint8"
@@ -232,7 +244,11 @@
 
       // Order is important here...
 
-      if (c1_is_char && c2_is_built_in_type)
+      if (c1 == "struct" && c2 == c1)
+        retval = c1;
+      else if (c1 == "cell" || c2 == "cell")
+        retval = "cell";
+      else if (c1_is_char && c2_is_built_in_type)
         retval = c1;
       else if (c2_is_char && c1_is_built_in_type)
         retval = c2;
@@ -250,54 +266,38 @@
         retval = c2;
       else if (c1_is_logical && c2_is_logical)
         retval = c1;
-      else if (c1 == "struct" && c2 == c1)
-        retval = c1;
-      else if (c1 == "cell" && c2 == c1)
-        retval = c1;
     }
 
   return retval;
 }
 
 static void
-eval_error (const char *msg, int l, int c,
-            const dim_vector& x, const dim_vector& y)
+eval_error (const char *msg, const dim_vector& x, const dim_vector& y)
 {
-  if (l == -1 && c == -1)
-    {
-      ::error ("%s (%s vs %s)", msg, x.str ().c_str (), y.str ().c_str ());
-    }
-  else
-    {
-      ::error ("%s (%s vs %s) near line %d, column %d", msg,
-               x.str ().c_str (), y.str ().c_str (), l, c);
-    }
+  ::error ("%s (%s vs %s)", msg, x.str ().c_str (), y.str ().c_str ());
 }
 
-bool
-tm_row_const::tm_row_const_rep::do_init_element (tree_expression *elt,
-                                                 const octave_value& val,
+void
+tm_row_const::tm_row_const_rep::do_init_element (const octave_value& val,
                                                  bool& first_elem)
 {
-  std::string this_elt_class_nm = val.class_name ();
+  std::string this_elt_class_nm
+    = val.is_object () ? std::string ("class") : val.class_name ();
+
+  class_nm = get_concat_class (class_nm, this_elt_class_nm);
 
   dim_vector this_elt_dv = val.dims ();
 
-  class_nm = get_concat_class (class_nm, this_elt_class_nm);
-
   if (! this_elt_dv.zero_by_zero ())
     {
       all_mt = false;
 
       if (first_elem)
         {
+          if (val.is_map ())
+            first_elem_is_struct = true;
+
           first_elem = false;
-          dv = this_elt_dv;
-        }
-      else if (! dv.hvcat (this_elt_dv, 1))
-        {
-          eval_error ("horizontal dimensions mismatch", elt->line (), elt->column (), dv, this_elt_dv);
-          return false;
         }
     }
 
@@ -321,6 +321,9 @@
   if (all_cmplx && ! (val.is_complex_type () || val.is_real_type ()))
     all_cmplx = false;
 
+  if (!any_cell && val.is_cell ())
+    any_cell = true;
+
   if (!any_sparse && val.is_sparse_type ())
     any_sparse = true;
 
@@ -328,8 +331,6 @@
     any_class = true;
 
   all_1x1 = all_1x1 && val.numel () == 1;
-
-  return true;
 }
 
 void
@@ -340,6 +341,7 @@
   all_dq_str = true;
   all_real = true;
   all_cmplx = true;
+  any_cell = false;
   any_sparse = false;
   any_class = false;
 
@@ -356,7 +358,10 @@
       octave_value tmp = elt->rvalue1 ();
 
       if (error_state || tmp.is_undefined ())
-        break;
+        {
+          ok = ! error_state;
+          return;
+        }
       else
         {
           if (tmp.is_cs_list ())
@@ -367,21 +372,91 @@
                 {
                   octave_quit ();
 
-                  if (! do_init_element (elt, tlst(i), first_elem))
-                    goto done;
+                  do_init_element (tlst(i), first_elem);
                 }
             }
           else
+            do_init_element (tmp, first_elem);
+        }
+    }
+
+  if (any_cell && ! any_class && ! first_elem_is_struct)
+    cellify ();
+
+  first_elem = true;
+
+  for (iterator p = begin (); p != end (); p++)
+    {
+      octave_quit ();
+
+      octave_value val = *p;
+
+      dim_vector this_elt_dv = val.dims ();
+
+      if (! this_elt_dv.zero_by_zero ())
+        {
+          all_mt = false;
+
+          if (first_elem)
             {
-              if (! do_init_element (elt, tmp, first_elem))
-                goto done;
+              first_elem = false;
+              dv = this_elt_dv;
+            }
+          else if (! dv.hvcat (this_elt_dv, 1))
+            {
+              eval_error ("horizontal dimensions mismatch", dv, this_elt_dv);
+              break;
             }
         }
     }
 
- done:
+  ok = ! error_state;
+}
+
+void
+tm_row_const::tm_row_const_rep::cellify (void)
+{
+  bool elt_changed = false;
+
+  for (iterator p = begin (); p != end (); p++)
+    {
+      octave_quit ();
+
+      if (! p->is_cell ())
+        {
+          elt_changed = true;
+
+          *p = Cell (*p);
+        }
+    }
+
+  if (elt_changed)
+    {
+      bool first_elem = true;
 
-  ok = ! error_state;
+      for (iterator p = begin (); p != end (); p++)
+        {
+          octave_quit ();
+
+          octave_value val = *p;
+
+          dim_vector this_elt_dv = val.dims ();
+
+          if (! this_elt_dv.zero_by_zero ())
+            {
+              if (first_elem)
+                {
+                  first_elem = false;
+                  dv = this_elt_dv;
+                }
+              else if (! dv.hvcat (this_elt_dv, 1))
+                {
+                  eval_error ("horizontal dimensions mismatch", dv, this_elt_dv);
+                  break;
+                }
+            }
+        }
+    }
 }
 
 void
@@ -403,8 +478,8 @@
   tm_const (const tree_matrix& tm)
     : dv (0, 0), all_str (false), all_sq_str (false), all_dq_str (false),
       some_str (false), all_real (false), all_cmplx (false),
-      all_mt (true), any_sparse (false), any_class (false),
-      class_nm (), ok (false)
+      all_mt (true), any_cell (false), any_sparse (false),
+      any_class (false), class_nm (), ok (false)
   { init (tm); }
 
   ~tm_const (void) { }
@@ -421,6 +496,7 @@
   bool all_real_p (void) const { return all_real; }
   bool all_complex_p (void) const { return all_cmplx; }
   bool all_empty_p (void) const { return all_mt; }
+  bool any_cell_p (void) const { return any_cell; }
   bool any_sparse_p (void) const { return any_sparse; }
   bool any_class_p (void) const { return any_class; }
   bool all_1x1_p (void) const { return all_1x1; }
@@ -440,6 +516,7 @@
   bool all_real;
   bool all_cmplx;
   bool all_mt;
+  bool any_cell;
   bool any_sparse;
   bool any_class;
   bool all_1x1;
@@ -465,11 +542,13 @@
   all_dq_str = true;
   all_real = true;
   all_cmplx = true;
+  any_cell = false;
   any_sparse = false;
   any_class = false;
   all_1x1 = ! empty ();
 
   bool first_elem = true;
+  bool first_elem_is_struct = false;
 
   // Just eval and figure out if what we have is complex or all
   // strings.  We can't check columns until we know that this is a
@@ -484,6 +563,13 @@
 
       tm_row_const tmp (*elt);
 
+      if (first_elem)
+        {
+          first_elem_is_struct = tmp.first_elem_struct_p ();
+
+          first_elem = false;
+        }
+
       if (tmp && ! tmp.empty ())
         {
           if (all_str && ! tmp.all_strings_p ())
@@ -507,6 +593,9 @@
           if (all_mt && ! tmp.all_empty_p ())
             all_mt = false;
 
+          if (!any_cell && tmp.any_cell_p ())
+            any_cell = true;
+
           if (!any_sparse && tmp.any_sparse_p ())
             any_sparse = true;
 
@@ -523,6 +612,20 @@
 
   if (! error_state)
     {
+      iterator p = begin ();
+
+      if (any_cell && ! any_class && ! first_elem_is_struct)
+        {
+          for (iterator p = begin (); p != end (); p++)
+            {
+              octave_quit ();
+
+              p->cellify ();
+            }
+        }
+
+      first_elem = true;
+
       for (iterator p = begin (); p != end (); p++)
         {
           octave_quit ();
@@ -556,8 +659,7 @@
             }
           else if (! dv.hvcat (this_elt_dv, 0))
             {
-              eval_error ("vertical dimensions mismatch", -1, -1,
-                          dv, this_elt_dv);
+              eval_error ("vertical dimensions mismatch", dv, this_elt_dv);
               return;
             }
         }
@@ -928,6 +1030,10 @@
                 ::error ("cannot find overloaded vertcat function");
             }
         }
+      else if (result_type == "cell")
+        {
+          retval = do_single_type_concat<Cell> (dv, tmp);
+        }
       else if (result_type == "double")
         {
           if (any_sparse_p)
@@ -1125,6 +1231,201 @@
   tw.visit_matrix (*this);
 }
 
+/*
+%% test concatenation with all zero matrices
+%!assert([ '' 65*ones(1,10) ], 'AAAAAAAAAA');
+%!assert([ 65*ones(1,10) '' ], 'AAAAAAAAAA');
+
+%!test
+%! c = {'foo'; 'bar'; 'bazoloa'};
+%! assert ([c; 'a'; 'bc'; 'def'], {'foo'; 'bar'; 'bazoloa'; 'a'; 'bc'; 'def'});
+
+%!assert (class ([int64(1), int64(1)]), 'int64')
+%!assert (class ([int64(1), int32(1)]), 'int64')
+%!assert (class ([int64(1), int16(1)]), 'int64')
+%!assert (class ([int64(1), int8(1)]), 'int64')
+%!assert (class ([int64(1), uint64(1)]), 'int64')
+%!assert (class ([int64(1), uint32(1)]), 'int64')
+%!assert (class ([int64(1), uint16(1)]), 'int64')
+%!assert (class ([int64(1), uint8(1)]), 'int64')
+%!assert (class ([int64(1), single(1)]), 'int64')
+%!assert (class ([int64(1), double(1)]), 'int64')
+%!assert (class ([int64(1), cell(1)]), 'cell')
+%!assert (class ([int64(1), true]), 'int64')
+%!assert (class ([int64(1), 'a']), 'char')
+
+%!assert (class ([int32(1), int64(1)]), 'int32')
+%!assert (class ([int32(1), int32(1)]), 'int32')
+%!assert (class ([int32(1), int16(1)]), 'int32')
+%!assert (class ([int32(1), int8(1)]), 'int32')
+%!assert (class ([int32(1), uint64(1)]), 'int32')
+%!assert (class ([int32(1), uint32(1)]), 'int32')
+%!assert (class ([int32(1), uint16(1)]), 'int32')
+%!assert (class ([int32(1), uint8(1)]), 'int32')
+%!assert (class ([int32(1), single(1)]), 'int32')
+%!assert (class ([int32(1), double(1)]), 'int32')
+%!assert (class ([int32(1), cell(1)]), 'cell')
+%!assert (class ([int32(1), true]), 'int32')
+%!assert (class ([int32(1), 'a']), 'char')
+
+%!assert (class ([int16(1), int64(1)]), 'int16')
+%!assert (class ([int16(1), int32(1)]), 'int16')
+%!assert (class ([int16(1), int16(1)]), 'int16')
+%!assert (class ([int16(1), int8(1)]), 'int16')
+%!assert (class ([int16(1), uint64(1)]), 'int16')
+%!assert (class ([int16(1), uint32(1)]), 'int16')
+%!assert (class ([int16(1), uint16(1)]), 'int16')
+%!assert (class ([int16(1), uint8(1)]), 'int16')
+%!assert (class ([int16(1), single(1)]), 'int16')
+%!assert (class ([int16(1), double(1)]), 'int16')
+%!assert (class ([int16(1), cell(1)]), 'cell')
+%!assert (class ([int16(1), true]), 'int16')
+%!assert (class ([int16(1), 'a']), 'char')
+
+%!assert (class ([int8(1), int64(1)]), 'int8')
+%!assert (class ([int8(1), int32(1)]), 'int8')
+%!assert (class ([int8(1), int16(1)]), 'int8')
+%!assert (class ([int8(1), int8(1)]), 'int8')
+%!assert (class ([int8(1), uint64(1)]), 'int8')
+%!assert (class ([int8(1), uint32(1)]), 'int8')
+%!assert (class ([int8(1), uint16(1)]), 'int8')
+%!assert (class ([int8(1), uint8(1)]), 'int8')
+%!assert (class ([int8(1), single(1)]), 'int8')
+%!assert (class ([int8(1), double(1)]), 'int8')
+%!assert (class ([int8(1), cell(1)]), 'cell')
+%!assert (class ([int8(1), true]), 'int8')
+%!assert (class ([int8(1), 'a']), 'char')
+
+%!assert (class ([uint64(1), int64(1)]), 'uint64')
+%!assert (class ([uint64(1), int32(1)]), 'uint64')
+%!assert (class ([uint64(1), int16(1)]), 'uint64')
+%!assert (class ([uint64(1), int8(1)]), 'uint64')
+%!assert (class ([uint64(1), uint64(1)]), 'uint64')
+%!assert (class ([uint64(1), uint32(1)]), 'uint64')
+%!assert (class ([uint64(1), uint16(1)]), 'uint64')
+%!assert (class ([uint64(1), uint8(1)]), 'uint64')
+%!assert (class ([uint64(1), single(1)]), 'uint64')
+%!assert (class ([uint64(1), double(1)]), 'uint64')
+%!assert (class ([uint64(1), cell(1)]), 'cell')
+%!assert (class ([uint64(1), true]), 'uint64')
+%!assert (class ([uint64(1), 'a']), 'char')
+
+%!assert (class ([uint32(1), int64(1)]), 'uint32')
+%!assert (class ([uint32(1), int32(1)]), 'uint32')
+%!assert (class ([uint32(1), int16(1)]), 'uint32')
+%!assert (class ([uint32(1), int8(1)]), 'uint32')
+%!assert (class ([uint32(1), uint64(1)]), 'uint32')
+%!assert (class ([uint32(1), uint32(1)]), 'uint32')
+%!assert (class ([uint32(1), uint16(1)]), 'uint32')
+%!assert (class ([uint32(1), uint8(1)]), 'uint32')
+%!assert (class ([uint32(1), single(1)]), 'uint32')
+%!assert (class ([uint32(1), double(1)]), 'uint32')
+%!assert (class ([uint32(1), cell(1)]), 'cell')
+%!assert (class ([uint32(1), true]), 'uint32')
+%!assert (class ([uint32(1), 'a']), 'char')
+
+%!assert (class ([uint16(1), int64(1)]), 'uint16')
+%!assert (class ([uint16(1), int32(1)]), 'uint16')
+%!assert (class ([uint16(1), int16(1)]), 'uint16')
+%!assert (class ([uint16(1), int8(1)]), 'uint16')
+%!assert (class ([uint16(1), uint64(1)]), 'uint16')
+%!assert (class ([uint16(1), uint32(1)]), 'uint16')
+%!assert (class ([uint16(1), uint16(1)]), 'uint16')
+%!assert (class ([uint16(1), uint8(1)]), 'uint16')
+%!assert (class ([uint16(1), single(1)]), 'uint16')
+%!assert (class ([uint16(1), double(1)]), 'uint16')
+%!assert (class ([uint16(1), cell(1)]), 'cell')
+%!assert (class ([uint16(1), true]), 'uint16')
+%!assert (class ([uint16(1), 'a']), 'char')
+
+%!assert (class ([uint8(1), int64(1)]), 'uint8')
+%!assert (class ([uint8(1), int32(1)]), 'uint8')
+%!assert (class ([uint8(1), int16(1)]), 'uint8')
+%!assert (class ([uint8(1), int8(1)]), 'uint8')
+%!assert (class ([uint8(1), uint64(1)]), 'uint8')
+%!assert (class ([uint8(1), uint32(1)]), 'uint8')
+%!assert (class ([uint8(1), uint16(1)]), 'uint8')
+%!assert (class ([uint8(1), uint8(1)]), 'uint8')
+%!assert (class ([uint8(1), single(1)]), 'uint8')
+%!assert (class ([uint8(1), double(1)]), 'uint8')
+%!assert (class ([uint8(1), cell(1)]), 'cell')
+%!assert (class ([uint8(1), true]), 'uint8')
+%!assert (class ([uint8(1), 'a']), 'char')
+
+%!assert (class ([single(1), int64(1)]), 'int64')
+%!assert (class ([single(1), int32(1)]), 'int32')
+%!assert (class ([single(1), int16(1)]), 'int16')
+%!assert (class ([single(1), int8(1)]), 'int8')
+%!assert (class ([single(1), uint64(1)]), 'uint64')
+%!assert (class ([single(1), uint32(1)]), 'uint32')
+%!assert (class ([single(1), uint16(1)]), 'uint16')
+%!assert (class ([single(1), uint8(1)]), 'uint8')
+%!assert (class ([single(1), single(1)]), 'single')
+%!assert (class ([single(1), double(1)]), 'single')
+%!assert (class ([single(1), cell(1)]), 'cell')
+%!assert (class ([single(1), true]), 'single')
+%!assert (class ([single(1), 'a']), 'char')
+
+%!assert (class ([double(1), int64(1)]), 'int64')
+%!assert (class ([double(1), int32(1)]), 'int32')
+%!assert (class ([double(1), int16(1)]), 'int16')
+%!assert (class ([double(1), int8(1)]), 'int8')
+%!assert (class ([double(1), uint64(1)]), 'uint64')
+%!assert (class ([double(1), uint32(1)]), 'uint32')
+%!assert (class ([double(1), uint16(1)]), 'uint16')
+%!assert (class ([double(1), uint8(1)]), 'uint8')
+%!assert (class ([double(1), single(1)]), 'single')
+%!assert (class ([double(1), double(1)]), 'double')
+%!assert (class ([double(1), cell(1)]), 'cell')
+%!assert (class ([double(1), true]), 'double')
+%!assert (class ([double(1), 'a']), 'char')
+
+%!assert (class ([cell(1), int64(1)]), 'cell')
+%!assert (class ([cell(1), int32(1)]), 'cell')
+%!assert (class ([cell(1), int16(1)]), 'cell')
+%!assert (class ([cell(1), int8(1)]), 'cell')
+%!assert (class ([cell(1), uint64(1)]), 'cell')
+%!assert (class ([cell(1), uint32(1)]), 'cell')
+%!assert (class ([cell(1), uint16(1)]), 'cell')
+%!assert (class ([cell(1), uint8(1)]), 'cell')
+%!assert (class ([cell(1), single(1)]), 'cell')
+%!assert (class ([cell(1), double(1)]), 'cell')
+%!assert (class ([cell(1), cell(1)]), 'cell')
+%!assert (class ([cell(1), true]), 'cell')
+%!assert (class ([cell(1), 'a']), 'cell')
+
+%!assert (class ([true, int64(1)]), 'int64')
+%!assert (class ([true, int32(1)]), 'int32')
+%!assert (class ([true, int16(1)]), 'int16')
+%!assert (class ([true, int8(1)]), 'int8')
+%!assert (class ([true, uint64(1)]), 'uint64')
+%!assert (class ([true, uint32(1)]), 'uint32')
+%!assert (class ([true, uint16(1)]), 'uint16')
+%!assert (class ([true, uint8(1)]), 'uint8')
+%!assert (class ([true, single(1)]), 'single')
+%!assert (class ([true, double(1)]), 'double')
+%!assert (class ([true, cell(1)]), 'cell')
+%!assert (class ([true, true]), 'logical')
+%!assert (class ([true, 'a']), 'char')
+
+%!assert (class (['a', int64(1)]), 'char')
+%!assert (class (['a', int32(1)]), 'char')
+%!assert (class (['a', int16(1)]), 'char')
+%!assert (class (['a', int8(1)]), 'char')
+%!assert (class (['a', int64(1)]), 'char')
+%!assert (class (['a', int32(1)]), 'char')
+%!assert (class (['a', int16(1)]), 'char')
+%!assert (class (['a', int8(1)]), 'char')
+%!assert (class (['a', single(1)]), 'char')
+%!assert (class (['a', double(1)]), 'char')
+%!assert (class (['a', cell(1)]), 'cell')
+%!assert (class (['a', true]), 'char')
+%!assert (class (['a', 'a']), 'char')
+
+%!assert (class ([cell(1), struct('foo', 'bar')]), 'cell')
+%!error [struct('foo', 'bar'), cell(1)];
+*/
+
 DEFUN (string_fill_char, args, nargout,
   "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {@var{val} =} string_fill_char ()\n\
@@ -1146,3 +1447,18 @@
 {
   return SET_INTERNAL_VARIABLE (string_fill_char);
 }
+
+/*
+%!error (string_fill_char (1, 2));
+%% string_fill_char() function call must be outside of %!test block
+%% due to the way a %!test block is wrapped inside a function
+%!shared orig_val, old_val
+%! orig_val = string_fill_char ();
+%! old_val  = string_fill_char ("X");
+%!test
+%! assert (orig_val, old_val);
+%! assert (string_fill_char (), "X");
+%! assert (["these"; "are"; "strings"], ["theseXX"; "areXXXX"; "strings"]);
+%! string_fill_char (orig_val);
+%! assert (string_fill_char (), orig_val);
+*/
--- a/src/pt-unop.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/pt-unop.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -28,6 +28,7 @@
 #include "oct-obj.h"
 #include "oct-lvalue.h"
 #include "ov.h"
+#include "profiler.h"
 #include "pt-bp.h"
 #include "pt-unop.h"
 #include "pt-walk.h"
@@ -72,10 +73,14 @@
 
           if (! error_state)
             {
+              BEGIN_PROFILER_BLOCK ("prefix " + oper ())
+
               ref.do_unary_op (etype);
 
               if (! error_state)
                 retval = ref.value ();
+
+              END_PROFILER_BLOCK
             }
         }
       else
@@ -84,6 +89,8 @@
 
           if (! error_state && val.is_defined ())
             {
+              BEGIN_PROFILER_BLOCK ("prefix " + oper ())
+
               // Attempt to do the operation in-place if it is unshared
               // (a temporary expression).
               if (val.get_count () == 1)
@@ -93,6 +100,8 @@
 
               if (error_state)
                 retval = octave_value ();
+
+              END_PROFILER_BLOCK
             }
         }
     }
@@ -153,7 +162,9 @@
             {
               retval = ref.value ();
 
+              BEGIN_PROFILER_BLOCK ("postfix " + oper ())
               ref.do_unary_op (etype);
+              END_PROFILER_BLOCK
             }
         }
       else
@@ -162,10 +173,14 @@
 
           if (! error_state && val.is_defined ())
             {
+              BEGIN_PROFILER_BLOCK ("postfix " + oper ())
+
               retval = ::do_unary_op (etype, val);
 
               if (error_state)
                 retval = octave_value ();
+
+              END_PROFILER_BLOCK
             }
         }
     }
--- a/src/sighandlers.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/sighandlers.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -945,6 +945,12 @@
   return retval;
 }
 
+/*
+%!error SIG (1);
+%!assert (isstruct (SIG ()));
+%!assert (! isempty (SIG ()));
+*/
+
 DEFUN (debug_on_interrupt, args, nargout,
   "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {@var{val} =} debug_on_interrupt ()\n\
@@ -958,6 +964,17 @@
   return SET_INTERNAL_VARIABLE (debug_on_interrupt);
 }
 
+/*
+%!error (debug_on_interrupt (1, 2));
+%!test
+%! orig_val = debug_on_interrupt ();
+%! old_val = debug_on_interrupt (! orig_val);
+%! assert (orig_val, old_val);
+%! assert (debug_on_interrupt (), ! orig_val);
+%! debug_on_interrupt (orig_val);
+%! assert (debug_on_interrupt (), orig_val);
+*/
+
 DEFUN (sighup_dumps_octave_core, args, nargout,
   "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {@var{val} =} sighup_dumps_octave_core ()\n\
@@ -970,6 +987,17 @@
   return SET_INTERNAL_VARIABLE (sighup_dumps_octave_core);
 }
 
+/*
+%!error (sighup_dumps_octave_core (1, 2));
+%!test
+%! orig_val = sighup_dumps_octave_core ();
+%! old_val = sighup_dumps_octave_core (! orig_val);
+%! assert (orig_val, old_val);
+%! assert (sighup_dumps_octave_core (), ! orig_val);
+%! sighup_dumps_octave_core (orig_val);
+%! assert (sighup_dumps_octave_core (), orig_val);
+*/
+
 DEFUN (sigterm_dumps_octave_core, args, nargout,
   "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {@var{val} =} sigterm_dumps_octave_core ()\n\
@@ -981,3 +1009,14 @@
 {
   return SET_INTERNAL_VARIABLE (sigterm_dumps_octave_core);
 }
+
+/*
+%!error (sigterm_dumps_octave_core (1, 2));
+%!test
+%! orig_val = sigterm_dumps_octave_core ();
+%! old_val = sigterm_dumps_octave_core (! orig_val);
+%! assert (orig_val, old_val);
+%! assert (sigterm_dumps_octave_core (), ! orig_val);
+%! sigterm_dumps_octave_core (orig_val);
+%! assert (sigterm_dumps_octave_core (), orig_val);
+*/
--- a/src/strfns.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/strfns.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -80,10 +80,12 @@
 
   int nargin = args.length ();
 
-  if (nargin == 1)
+  if (nargin == 0)
+    retval = "";
+  else if (nargin == 1)
     retval = args(0).convert_to_str (true, true,
                                      args(0).is_dq_string () ? '"' : '\'');
-  else if (nargin > 1)
+  else
     {
       int n_elts = 0;
 
@@ -144,14 +146,12 @@
 
       retval = octave_value (result, '\'');
     }
-  else
-    print_usage ();
 
   return retval;
 }
 
 /*
-%!error <Invalid call to char> char()
+%!assert (char (), '');
 %!assert (char (100) == "d");
 %!assert (all(char (100,100) == ["d";"d"]));
 %!assert (all(char ({100,100}) == ["d";"d"]));
@@ -162,6 +162,13 @@
 %!assert (all(char ({100,{100, {""}}}) == ["d";"d";" "]))
 %!assert (all(char (["a";"be"], {"c", 100}) == ["a";"be";"c";"d"]))
 %!assert(strcmp (char ("a", "bb", "ccc"), ["a  "; "bb "; "ccc"]));
+%!assert(strcmp (char ([65, 83, 67, 73, 73]), "ASCII"));
+
+%!test
+%! x = char ("foo", "bar", "foobar");
+%! assert((strcmp (x(1,:), "foo   ")
+%! && strcmp (x(2,:), "bar   ")
+%! && strcmp (x(3,:), "foobar")));
 */
 
 DEFUN (strvcat, args, ,
@@ -314,14 +321,20 @@
 }
 
 /*
-
 %!assert (ischar ("a"), logical (1));
 %!assert (ischar (["ab";"cd"]), logical (1));
 %!assert (ischar ({"ab"}), logical (0));
 %!assert (ischar (1), logical (0));
+%!assert(ischar ([1, 2]), logical (0));
+%!assert(ischar ([]), logical (0));
+%!assert(ischar ([1, 2; 3, 4]), logical (0));
+%!assert(ischar (""), logical (1));
+%!assert(ischar ("test"), logical (1));
+%!assert(ischar (["test"; "ing"]), logical (1));
+%!assert(ischar (struct ("foo", "bar")), logical (0));
 %!error <Invalid call to ischar.*> ischar ();
-
- */
+%!error <Invalid call to ischar.*> ischar ("test", 1);
+*/
 
 static octave_value
 do_strcmp_fun (const octave_value& arg0, const octave_value& arg1,
@@ -576,12 +589,15 @@
 }
 
 /*
+%!error <Invalid call to strcmp.*> strcmp ();
+%!error <Invalid call to strcmp.*> strcmp ("foo", "bar", 3);
+%!
 %!shared x
 %!  x = char (zeros (0, 2));
 %!assert (strcmp ('', x) == false);
 %!assert (strcmp (x, '') == false);
 %!assert (strcmp (x, x) == true);
-## %!assert (strcmp ({''}, x) == false);
+## %!assert (strcmp ({''}, x) == true);
 ## %!assert (strcmp ({x}, '') == false);
 ## %!assert (strcmp ({x}, x) == true);
 ## %!assert (strcmp ('', {x}) == false);
@@ -608,14 +624,16 @@
 %!assert (all (strcmp ('', {y}) == [true; true]));
 %!assert (all (strcmp (y, {''}) == [true; true]));
 %!assert (all (strcmp (y, {y}) == [true; true]));
-## %!assert (all (strcmp ({y; y}, '') == [false; false]));
-## %!assert (all (strcmp ({y; y}, {''}) == [false; false]));
-## %!assert (all (strcmp ('', {y; y}) == [false; false]));
-## %!assert (all (strcmp ({''}, {y; y}) == [false; false]));
+%!assert (all (strcmp ({y; y}, '') == [true; true]));
+%!assert (all (strcmp ({y; y}, {''}) == [true; true]));
+%!assert (all (strcmp ('', {y; y}) == [true; true]));
+%!assert (all (strcmp ({''}, {y; y}) == [true; true]));
 %!assert (all (strcmp ({'foo'}, y) == [false; false]));
 %!assert (all (strcmp ({'foo'}, y) == [false; false]));
 %!assert (all (strcmp (y, {'foo'}) == [false; false]));
 %!assert (all (strcmp (y, {'foo'}) == [false; false]));
+%!assert (strcmp ("foobar", "foobar"), true);
+%!assert (strcmp ("fooba", "foobar"), false);
 */
 
 // Apparently, Matlab ignores the dims with strncmp. It also
--- a/src/symtab.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/symtab.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -575,13 +575,16 @@
 //   variable
 //   subfunction
 //   private function
+//   class method
 //   class constructor
-//   class method
 //   legacy dispatch
 //   command-line function
 //   autoload function
 //   function on the path
 //   built-in function
+//
+// Matlab documentation states that constructors have higher precedence
+// than methods, but that does not seem to be the case.
 
 octave_value
 symbol_table::fcn_info::fcn_info_rep::find (const octave_value_list& args,
@@ -687,6 +690,18 @@
         }
     }
 
+  // Class methods.
+
+  if (! args.empty ())
+    {
+      std::string dispatch_type = get_dispatch_type (args);
+
+      octave_value fcn = find_method (dispatch_type);
+
+      if (fcn.is_defined ())
+        return fcn;
+    }
+
   // Class constructors.  The class name and function name are the same.
 
   str_val_iterator q = class_constructors.find (name);
@@ -716,18 +731,6 @@
         }
     }
 
-  // Class methods.
-
-  if (! args.empty ())
-    {
-      std::string dispatch_type = get_dispatch_type (args);
-
-      octave_value fcn = find_method (dispatch_type);
-
-      if (fcn.is_defined ())
-        return fcn;
-    }
-
   // Legacy dispatch.
 
   if (! args.empty () && ! dispatch_map.empty ())
@@ -1463,7 +1466,9 @@
 {
   octave_value retval;
 
-  if (nargout > 0)
+  int nargin = args.length ();
+
+  if (nargout > 0 || nargin == 0)
     {
       switch (Vignore_function_time_stamp)
         {
@@ -1481,8 +1486,6 @@
         }
     }
 
-  int nargin = args.length ();
-
   if (nargin == 1)
     {
       std::string sval = args(0).string_value ();
@@ -1507,6 +1510,25 @@
   return retval;
 }
 
+/*
+%!shared old_state
+%! old_state = ignore_function_time_stamp ();
+%!test
+%! state = ignore_function_time_stamp ("all");
+%! assert (state, old_state);
+%! assert (ignore_function_time_stamp (), "all");
+%! state = ignore_function_time_stamp ("system");
+%! assert (state, "all");
+%! assert (ignore_function_time_stamp (), "system");
+%! ignore_function_time_stamp (old_state);
+
+%% Test input validation
+%!error (ignore_function_time_stamp ("all", "all"))
+%!error (ignore_function_time_stamp ("UNKNOWN_VALUE"))
+%!error (ignore_function_time_stamp (42))
+
+*/
+
 DEFUN (__current_scope__, , ,
   "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {[@var{scope}, @var{context}]} __dump_symtab_info__ ()\n\
--- a/src/symtab.h	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/symtab.h	Tue Sep 20 15:38:24 2011 -0400
@@ -790,6 +790,11 @@
       return rep->built_in_function;
     }
 
+    octave_value find_cmdline_function (void) const
+    {
+      return rep->cmdline_function;
+    }
+
     octave_value find_autoload (void)
     {
       return rep->find_autoload ();
@@ -1787,6 +1792,25 @@
     return retval;
   }
 
+  static std::list<std::string> cmdline_function_names (void)
+  {
+    std::list<std::string> retval;
+
+    for (fcn_table_const_iterator p = fcn_table.begin ();
+         p != fcn_table.end (); p++)
+      {
+        octave_value fcn = p->second.find_cmdline_function ();
+
+        if (fcn.is_defined ())
+          retval.push_back (p->first);
+      }
+
+    if (! retval.empty ())
+      retval.sort ();
+
+    return retval;
+  }
+
   static bool is_local_variable (const std::string& name)
   {
     if (xcurrent_scope == xglobal_scope)
--- a/src/sysdep.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/sysdep.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -586,8 +586,16 @@
 
   return retval;
 }
+
 DEFALIAS (setenv, putenv);
 
+/*
+%!assert (ischar (getenv ("OCTAVE_HOME")));
+%!test
+%! setenv ("dummy_variable_that_cannot_matter", "foobar");
+%! assert (getenv ("dummy_variable_that_cannot_matter"), "foobar");
+*/
+
 // FIXME -- perhaps kbhit should also be able to print a prompt?
 
 DEFUN (kbhit, args, ,
@@ -695,6 +703,12 @@
   return retval;
 }
 
+/*
+%!error (pause (1, 2));
+%!test
+%! pause (1);
+*/
+
 DEFUN (sleep, args, ,
   "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} sleep (@var{seconds})\n\
@@ -724,6 +738,13 @@
   return retval;
 }
 
+/*
+%!error (sleep ());
+%!error (sleep (1, 2));
+%!test
+%! sleep (1);
+*/
+
 DEFUN (usleep, args, ,
   "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} usleep (@var{microseconds})\n\
@@ -760,6 +781,13 @@
   return retval;
 }
 
+/*
+%!error (usleep ());
+%!error (usleep (1, 2));
+%!test
+%! usleep (1000);
+*/
+
 // FIXME -- maybe this should only return 1 if IEEE floating
 // point functions really work.
 
@@ -776,6 +804,10 @@
                        || flt_fmt == oct_mach_info::flt_fmt_ieee_big_endian);
 }
 
+/*
+%!assert (islogical (isieee ()));
+*/
+
 DEFUN (native_float_format, , ,
   "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} native_float_format ()\n\
@@ -787,6 +819,10 @@
   return octave_value (oct_mach_info::float_format_as_string (flt_fmt));
 }
 
+/*
+%!assert (ischar (native_float_format ()));
+*/
+
 DEFUN (tilde_expand, args, ,
   "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} tilde_expand (@var{string})\n\
@@ -835,3 +871,14 @@
 
   return retval;
 }
+
+/*
+%!test
+%! if (isempty (getenv ("HOME")))
+%!   setenv ("HOME", "foobar");
+%! endif
+%! home = getenv ("HOME");
+%! assert (tilde_expand ("~/foobar"), fullfile (home, "foobar"));
+%! assert (tilde_expand ("/foo/bar"), "/foo/bar");
+%! assert (tilde_expand ("foo/bar"), "foo/bar");
+*/
--- a/src/toplev.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/toplev.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -39,6 +39,7 @@
 #include <unistd.h>
 
 #include "cmd-edit.h"
+#include "cmd-hist.h"
 #include "file-ops.h"
 #include "lo-error.h"
 #include "lo-mappers.h"
@@ -1001,6 +1002,20 @@
 
 DEFALIAS (shell_cmd, system);
 
+/*
+%!error (system ());
+%!error (system (1, 2, 3));
+%!test
+%! if (ispc ())
+%!   cmd = "dir";
+%! else
+%!   cmd = "ls";
+%! endif
+%! [status, output] = system (cmd);
+%! assert (ischar (output));
+%! assert (! isempty (output));
+*/
+
 // FIXME -- this should really be static, but that causes
 // problems on some systems.
 std::list<std::string> octave_atexit_functions;
@@ -1039,7 +1054,7 @@
 
       SAFE_CALL (octave_history_write_timestamp, ())
 
-      if (Vsaving_history)
+      if (! command_history::ignoring_entries ())
         SAFE_CALL (command_history::clean_up_and_save, ())
 
       SAFE_CALL (close_files, ())
@@ -1285,6 +1300,10 @@
       { false, "MAGICK_LDFLAGS", OCTAVE_CONF_MAGICK_LDFLAGS },
       { false, "MAGICK_LIBS", OCTAVE_CONF_MAGICK_LIBS },
       { false, "MKOCTFILE_DL_LDFLAGS", OCTAVE_CONF_MKOCTFILE_DL_LDFLAGS },
+      { false, "OCTAVE_LINK_DEPS", OCTAVE_CONF_OCTAVE_LINK_DEPS },
+      { false, "OCTAVE_LINK_OPTS", OCTAVE_CONF_OCTAVE_LINK_OPTS },
+      { false, "OCT_LINK_DEPS", OCTAVE_CONF_OCT_LINK_DEPS },
+      { false, "OCT_LINK_OPTS", OCTAVE_CONF_OCT_LINK_OPTS },
       { false, "OPENGL_LIBS", OCTAVE_CONF_OPENGL_LIBS },
       { false, "PTHREAD_CFLAGS", OCTAVE_CONF_PTHREAD_CFLAGS },
       { false, "PTHREAD_LIBS", OCTAVE_CONF_PTHREAD_LIBS },
@@ -1298,7 +1317,6 @@
       { false, "RDYNAMIC_FLAG", OCTAVE_CONF_RDYNAMIC_FLAG },
       { false, "READLINE_LIBS", OCTAVE_CONF_READLINE_LIBS },
       { false, "REGEX_LIBS", OCTAVE_CONF_REGEX_LIBS },
-      { false, "RLD_FLAG", OCTAVE_CONF_RLD_FLAG },
       { false, "SED", OCTAVE_CONF_SED },
       { false, "SHARED_LIBS", OCTAVE_CONF_SHARED_LIBS },
       { false, "SHLEXT", OCTAVE_CONF_SHLEXT },
@@ -1439,6 +1457,15 @@
   return retval;
 }
 
+/*
+%!error octave_config_info (1, 2);
+%!assert (ischar (octave_config_info ("version")));
+%!test
+%! x = octave_config_info ();
+%! assert (isstruct (x));
+%! assert (! isempty (x));
+*/
+
 #if defined (__GNUG__) && defined (DEBUG_NEW_DELETE)
 
 int debug_new_delete = 0;
--- a/src/txt-eng-ft.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/txt-eng-ft.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -202,7 +202,8 @@
 
 ft_render::ft_render (void)
     : text_processor (), face (0), bbox (1, 4, 0.0),
-      xoffset (0), yoffset (0), mode (MODE_BBOX),
+      xoffset (0), yoffset (0), multiline_halign (0),
+      multiline_align_xoffsets(), mode (MODE_BBOX),
       red (0), green (0), blue (0)
 {
 }
@@ -270,15 +271,23 @@
 {
   if (face)
     {
+      int line_index = 0;
+      FT_UInt box_line_width = 0;
       std::string str = e.string_value ();
       FT_UInt glyph_index, previous = 0;
 
+      if (mode == MODE_BBOX)
+        multiline_align_xoffsets.clear();
+      else if (mode == MODE_RENDER)
+        xoffset += multiline_align_xoffsets[line_index];
+
       for (size_t i = 0; i < str.length (); i++)
         {
           glyph_index = FT_Get_Char_Index (face, str[i]);
 
-          if (! glyph_index
-              || FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT))
+          if (str[i] != '\n'
+              && (! glyph_index
+              || FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT)))
             ::warning ("ft_render: skipping missing glyph for character `%c'",
                        str[i]);
           else
@@ -286,7 +295,21 @@
               switch (mode)
                 {
                 case MODE_RENDER:
-                  if (FT_Render_Glyph (face->glyph, FT_RENDER_MODE_NORMAL))
+                  if (str[i] == '\n')
+                    {
+                    glyph_index = FT_Get_Char_Index(face, ' ');
+                    if (!glyph_index || FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT))
+                      {
+                        ::warning ("ft_render: skipping missing glyph for character ` '");
+                      }
+                    else
+                      {
+                        line_index++;
+                        xoffset = multiline_align_xoffsets[line_index];
+                        yoffset -= (face->size->metrics.height >> 6);
+                      }
+                  }
+                  else if (FT_Render_Glyph (face->glyph, FT_RENDER_MODE_NORMAL))
                     ::warning ("ft_render: unable to render glyph for character `%c'",
                                str[i]);
                   else
@@ -304,6 +327,14 @@
 
                       x0 = xoffset+face->glyph->bitmap_left;
                       y0 = yoffset+face->glyph->bitmap_top;
+
+                      // 'w' seems to have a negative -1
+                      // face->glyph->bitmap_left, this is so we don't
+                      // index out of bound, and assumes we we allocated
+                      // the right amount of horizontal space in the bbox.
+                      if (x0 < 0)
+                        x0 = 0;
+
                       for (int r = 0; r < bitmap.rows; r++)
                         for (int c = 0; c < bitmap.width; c++)
                           {
@@ -327,43 +358,89 @@
                   break;
 
                 case MODE_BBOX:
-                  // width
-                  if (previous)
+                  if (str[i] == '\n')
                     {
-                      FT_Vector delta;
-
-                      FT_Get_Kerning (face, previous, glyph_index, FT_KERNING_DEFAULT, &delta);
-                      bbox(2) += (delta.x >> 6);
-                    }
-                  bbox(2) += (face->glyph->advance.x >> 6);
-
-                  int asc, desc;
-
-                  if (false /*tight*/)
-                    {
-                      desc = face->glyph->metrics.horiBearingY - face->glyph->metrics.height;
-                      asc = face->glyph->metrics.horiBearingY;
+                      glyph_index = FT_Get_Char_Index(face, ' ');
+                      if (! glyph_index
+                          || FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT))
+                      {
+                        ::warning ("ft_render: skipping missing glyph for character ` '");
+                      }
+                    else
+                      {
+                        multiline_align_xoffsets.push_back(box_line_width);
+                        // Reset the pixel width for this newline, so we don't
+                        // allocate a bounding box larger than the horizontal
+                        // width of the multi-line
+                        box_line_width = 0;
+                        bbox(1) -= (face->size->metrics.height >> 6);
+                      }
                     }
                   else
                     {
-                      asc = face->size->metrics.ascender;
-                      desc = face->size->metrics.descender;
-                    }
+                    // width
+                    if (previous)
+                      {
+                        FT_Vector delta;
 
-                  asc = yoffset + (asc >> 6);
-                  desc = yoffset + (desc >> 6);
+                        FT_Get_Kerning (face, previous, glyph_index,
+                                        FT_KERNING_DEFAULT, &delta);
+
+                        box_line_width += (delta.x >> 6);
+                      }
+
+                    box_line_width += (face->glyph->advance.x >> 6);
+
+                    int asc, desc;
 
-                  if (desc < bbox(1))
-                    {
-                      bbox(3) += (bbox(1) - desc);
-                      bbox(1) = desc;
-                    }
-                  if (asc > (bbox(3)+bbox(1)))
-                    bbox(3) = asc-bbox(1);
+                    if (false /*tight*/)
+                      {
+                        desc = face->glyph->metrics.horiBearingY - face->glyph->metrics.height;
+                        asc = face->glyph->metrics.horiBearingY;
+                      }
+                    else
+                      {
+                        asc = face->size->metrics.ascender;
+                        desc = face->size->metrics.descender;
+                      }
+
+                    asc = yoffset + (asc >> 6);
+                    desc = yoffset + (desc >> 6);
+
+                    if (desc < bbox(1))
+                      {
+                        bbox(3) += (bbox(1) - desc);
+                        bbox(1) = desc;
+                      }
+                    if (asc > (bbox(3)+bbox(1)))
+                      bbox(3) = asc-bbox(1);
+                    if (bbox(2) < box_line_width)
+                      bbox(2) = box_line_width;
+                  }
                   break;
                 }
+                if (str[i] == '\n')
+                  previous = 0;
+                else
+                  previous = glyph_index;
+            }
+        }
+      if (mode == MODE_BBOX)
+        {
+          /* Push last the width associated with the last line */
+          multiline_align_xoffsets.push_back(box_line_width);
 
-              previous = glyph_index;
+          for (unsigned int i = 0; i < multiline_align_xoffsets.size(); i++)
+            {
+            /* Center align */
+            if (multiline_halign == 1)
+              multiline_align_xoffsets[i] = (bbox(2) - multiline_align_xoffsets[i])/2;
+            /* Right align */
+            else if (multiline_halign == 2)
+              multiline_align_xoffsets[i] = (bbox(2) - multiline_align_xoffsets[i]);
+            /* Left align */
+            else
+              multiline_align_xoffsets[i] = 0;
             }
         }
     }
@@ -480,7 +557,7 @@
   text_element *elt = text_parser_none ().parse (txt);
   Matrix extent = get_extent (elt, rotation);
   delete elt;
-  
+
   return extent;
 }
 
@@ -507,6 +584,8 @@
   // FIXME: clip "rotation" between 0 and 360
   int rot_mode = rotation_to_mode (rotation);
 
+  multiline_halign = halign;
+
   text_element *elt = text_parser_none ().parse (txt);
   pixels_ = render (elt, box, rot_mode);
   delete elt;
--- a/src/txt-eng-ft.h	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/txt-eng-ft.h	Tue Sep 20 15:38:24 2011 -0400
@@ -25,6 +25,8 @@
 
 #if HAVE_FREETYPE
 
+#include <vector>
+
 #include <ft2build.h>
 #include FT_FREETYPE_H
 
@@ -94,6 +96,8 @@
   uint8NDArray pixels;
   int xoffset;
   int yoffset;
+  int multiline_halign;
+  std::vector<int> multiline_align_xoffsets;
   int mode;
   uint8_t red, green, blue;
 };
--- a/src/utils.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/utils.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -114,6 +114,17 @@
   return retval;
 }
 
+/*
+%!error isvarname ();
+%!error isvarname ("foo", "bar");
+
+%!assert (isvarname ("foo"), true);
+%!assert (isvarname ("_foo"), true);
+%!assert (isvarname ("_1"), true);
+%!assert (isvarname ("1foo"), false);
+%!assert (isvarname (""), false);
+*/
+
 // Return TRUE if F and G are both names for the same file.
 
 bool
@@ -325,6 +336,24 @@
   return retval;
 }
 
+/*
+%!error file_in_loadpath ();
+%!error file_in_loadpath ("foo", "bar", 1);
+
+%!test
+%! f = file_in_loadpath ("plot.m");
+%! assert (ischar (f));
+%! assert (! isempty (f));
+
+%!test
+%! f = file_in_loadpath ("$$probably_!!_not_&&_a_!!_file$$");
+%! assert (f, "");
+
+%!test
+%! lst = file_in_loadpath ("$$probably_!!_not_&&_a_!!_file$$", "all");
+%! assert (lst, {});
+*/
+
 DEFUN (file_in_path, args, ,
   "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {} file_in_path (@var{path}, @var{file})\n\
@@ -390,6 +419,25 @@
   return retval;
 }
 
+/*
+%!error file_in_path ();
+%!error file_in_path ("foo");
+%!error file_in_path ("foo", "bar", "baz", 1);
+
+%!test
+%! f = file_in_path (path (), "plot.m");
+%! assert (ischar (f));
+%! assert (! isempty (f));
+
+%!test
+%! f = file_in_path (path (), "$$probably_!!_not_&&_a_!!_file$$");
+%! assert (f, "");
+
+%!test
+%! lst = file_in_path (path (), "$$probably_!!_not_&&_a_!!_file$$", "all");
+%! assert (lst, {});
+*/
+
 std::string
 file_in_path (const std::string& name, const std::string& suffix)
 {
@@ -623,6 +671,22 @@
   return retval;
 }
 
+/*
+%!error do_string_escapes ();
+%!error do_string_escapes ("foo", "bar");
+
+%!assert (do_string_escapes ('foo\nbar'), "foo\nbar");
+%!assert (do_string_escapes ("foo\\nbar"), "foo\nbar");
+%!assert (do_string_escapes ("foo\\nbar"), ["foo", char(10), "bar"]);
+%!assert ("foo\nbar", ["foo", char(10), "bar"]);
+
+%!assert (do_string_escapes ('\a\b\f\n\r\t\v'), "\a\b\f\n\r\t\v");
+%!assert (do_string_escapes ("\\a\\b\\f\\n\\r\\t\\v"), "\a\b\f\n\r\t\v");
+%!assert (do_string_escapes ("\\a\\b\\f\\n\\r\\t\\v"),
+%!        char ([7, 8, 12, 10, 13, 9, 11]));
+%!assert ("\a\b\f\n\r\t\v", char ([7, 8, 12, 10, 13, 9, 11]));
+*/
+
 const char *
 undo_string_escape (char c)
 {
@@ -729,6 +793,20 @@
   return retval;
 }
 
+/*
+%!error undo_string_escapes ();
+%!error undo_string_escapes ("foo", "bar");
+
+%!assert (undo_string_escapes ("foo\nbar"), 'foo\nbar');
+%!assert (undo_string_escapes ("foo\nbar"), "foo\\nbar");
+%!assert (undo_string_escapes (["foo", char(10), "bar"]), "foo\\nbar");
+
+%!assert (undo_string_escapes ("\a\b\f\n\r\t\v"), '\a\b\f\n\r\t\v');
+%!assert (undo_string_escapes ("\a\b\f\n\r\t\v"), "\\a\\b\\f\\n\\r\\t\\v");
+%!assert (undo_string_escapes (char ([7, 8, 12, 10, 13, 9, 11])),
+%!        "\\a\\b\\f\\n\\r\\t\\v");
+*/
+
 DEFUN (is_absolute_filename, args, ,
   "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} is_absolute_filename (@var{file})\n\
@@ -747,6 +825,13 @@
   return retval;
 }
 
+/*
+%!error is_absolute_filename ();
+%!error is_absolute_filename ("foo", "bar");
+
+FIXME -- we need system-dependent tests here.
+*/
+
 DEFUN (is_rooted_relative_filename, args, ,
   "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} is_rooted_relative_filename (@var{file})\n\
@@ -765,6 +850,13 @@
   return retval;
 }
 
+/*
+%!error is_rooted_relative_filename ();
+%!error is_rooted_relative_filename ("foo", "bar");
+
+FIXME -- we need system-dependent tests here.
+*/
+
 DEFUN (make_absolute_filename, args, ,
   "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} make_absolute_filename (@var{file})\n\
@@ -789,6 +881,13 @@
   return retval;
 }
 
+/*
+%!error make_absolute_filename ();
+%!error make_absolute_filename ("foo", "bar");
+
+FIXME -- we need system-dependent tests here.
+*/
+
 DEFUN (find_dir_in_path, args, ,
   "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {} find_dir_in_path (@var{dir})\n\
@@ -829,6 +928,13 @@
   return retval;
 }
 
+/*
+%!error find_dir_in_path ();
+%!error find_dir_in_path ("foo", "bar", 1);
+
+FIXME -- need to create tests using current path, pathsep, and dirsep.
+*/
+
 DEFUNX ("errno", Ferrno, args, ,
   "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {@var{err} =} errno ()\n\
@@ -873,6 +979,21 @@
   return retval;
 }
 
+/*
+%!error errno ("foo", 1);
+
+%!assert (isnumeric (errno ()));
+
+%!test
+%! lst = errno_list ();
+%! fns = fieldnames (lst);
+%! oldval = errno (fns{1});
+%! assert (isnumeric (oldval));
+%! errno (oldval);
+%! newval = errno ();
+%! assert (oldval, newval);
+*/
+
 DEFUN (errno_list, args, ,
   "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} errno_list ()\n\
@@ -889,6 +1010,12 @@
   return retval;
 }
 
+/*
+%!error errno_list ("foo");
+
+%!assert (isstruct (errno_list ()));
+*/
+
 static void
 check_dimensions (octave_idx_type& nr, octave_idx_type& nc, const char *warnfor)
 {
@@ -1243,7 +1370,9 @@
 
       END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
 
-      if (nchars > -1 && nchars < size)
+      // Cast to avoid signed/unsigned comparison is safe due to
+      // short-circuiting
+      if (nchars > -1 && static_cast<size_t>(nchars) < size)
         break;
       else
         {
@@ -1352,6 +1481,14 @@
   return retval;
 }
 
+/*
+%!error isindex ();
+
+%!assert (isindex ([1, 2, 3]));
+%!assert (isindex (1:3));
+%!assert (isindex ([1, 2, -3]), false);
+*/
+
 octave_value_list
 do_simple_cellfun (octave_value_list (*fun) (const octave_value_list&, int),
                    const char *fun_name, const octave_value_list& args,
--- a/src/variables.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/variables.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -1043,11 +1043,12 @@
                  const std::string& expr_str = std::string (),
                  const octave_value& expr_val = octave_value ())
       : name (expr_str.empty () ? sr.name () : expr_str),
+        varval (expr_val.is_undefined () ? sr.varval () : expr_val),
         is_automatic (sr.is_automatic ()),
+        is_complex (varval.is_complex_type ()),
         is_formal (sr.is_formal ()),
         is_global (sr.is_global ()),
-        is_persistent (sr.is_persistent ()),
-        varval (expr_val.is_undefined () ? sr.varval () : expr_val)
+        is_persistent (sr.is_persistent ())
     { }
 
     void display_line (std::ostream& os,
@@ -1117,13 +1118,14 @@
                 {
                 case 'a':
                   {
-                    char tmp[5];
+                    char tmp[6];
 
                     tmp[0] = (is_automatic ? 'a' : ' ');
-                    tmp[1] = (is_formal ? 'f' : ' ');
-                    tmp[2] = (is_global ? 'g' : ' ');
-                    tmp[3] = (is_persistent ? 'p' : ' ');
-                    tmp[4] = 0;
+                    tmp[1] = (is_complex ? 'c' : ' ');
+                    tmp[2] = (is_formal ? 'f' : ' ');
+                    tmp[3] = (is_global ? 'g' : ' ');
+                    tmp[4] = (is_persistent ? 'p' : ' ');
+                    tmp[5] = 0;
 
                     os << tmp;
                   }
@@ -1172,11 +1174,12 @@
     }
 
     std::string name;
+    octave_value varval;
     bool is_automatic;
+    bool is_complex;
     bool is_formal;
     bool is_global;
     bool is_persistent;
-    octave_value varval;
   };
 
 public:
@@ -1333,6 +1336,9 @@
     for (size_t i = 0; i < param_string.length (); i++)
       param_length(i) = param_names(i) . length ();
 
+    // The attribute column needs size 5.
+    param_length(pos_a) = 5;
+
     // Calculating necessary spacing for name column,
     // bytes column, elements column and class column
 
@@ -1798,6 +1804,9 @@
 Automatic variable.  An automatic variable is one created by the\n\
 interpreter, for example @code{argn}.\n\
 \n\
+@item @code{c}\n\
+Variable of complex type.\n\
+\n\
 @item @code{f}\n\
 Formal parameter (function argument).\n\
 \n\
--- a/src/xpow.cc	Tue Sep 20 15:33:10 2011 -0400
+++ b/src/xpow.cc	Tue Sep 20 15:38:24 2011 -0400
@@ -49,6 +49,8 @@
 #include "utils.h"
 #include "xpow.h"
 
+#include "bsxfun.h"
+
 #ifdef _OPENMP
 #include <omp.h>
 #endif
@@ -1243,8 +1245,21 @@
 
   if (a_dims != b_dims)
     {
-      gripe_nonconformant ("operator .^", a_dims, b_dims);
-      return octave_value ();
+      if (is_valid_bsxfun (a_dims, b_dims))
+        {
+          //Potentially complex results
+          NDArray xa = octave_value_extract<NDArray> (a);
+          NDArray xb = octave_value_extract<NDArray> (b);
+          if (! xb.all_integers () && xa.any_element_is_negative ())
+            return octave_value (bsxfun_pow (ComplexNDArray (xa), xb));
+          else
+            return octave_value (bsxfun_pow (xa, xb));
+        }
+      else
+        {
+          gripe_nonconformant ("operator .^", a_dims, b_dims);
+          return octave_value ();
+        }
     }
 
   int len = a.length ();
@@ -1318,8 +1333,15 @@
 
   if (a_dims != b_dims)
     {
-      gripe_nonconformant ("operator .^", a_dims, b_dims);
-      return octave_value ();
+      if (is_valid_bsxfun (a_dims, b_dims))
+        {
+          return bsxfun_pow (a, b);
+        }
+      else
+        {
+          gripe_nonconformant ("operator .^", a_dims, b_dims);
+          return octave_value ();
+        }
     }
 
   ComplexNDArray result (a_dims);
@@ -1410,8 +1432,15 @@
 
   if (a_dims != b_dims)
     {
-      gripe_nonconformant ("operator .^", a_dims, b_dims);
-      return octave_value ();
+      if (is_valid_bsxfun (a_dims, b_dims))
+        {
+          return bsxfun_pow (a, b);
+        }
+      else
+        {
+          gripe_nonconformant ("operator .^", a_dims, b_dims);
+          return octave_value ();
+        }
     }
 
   ComplexNDArray result (a_dims);
@@ -1453,8 +1482,15 @@
 
   if (a_dims != b_dims)
     {
-      gripe_nonconformant ("operator .^", a_dims, b_dims);
-      return octave_value ();
+      if (is_valid_bsxfun (a_dims, b_dims))
+        {
+          return bsxfun_pow (a, b);
+        }
+      else
+        {
+          gripe_nonconformant ("operator .^", a_dims, b_dims);
+          return octave_value ();
+        }
     }
 
   ComplexNDArray result (a_dims);
@@ -2562,8 +2598,21 @@
 
   if (a_dims != b_dims)
     {
-      gripe_nonconformant ("operator .^", a_dims, b_dims);
-      return octave_value ();
+      if (is_valid_bsxfun (a_dims, b_dims))
+        {
+          //Potentially complex results
+          FloatNDArray xa = octave_value_extract<FloatNDArray> (a);
+          FloatNDArray xb = octave_value_extract<FloatNDArray> (b);
+          if (! xb.all_integers () && xa.any_element_is_negative ())
+            return octave_value (bsxfun_pow (FloatComplexNDArray (xa), xb));
+          else
+            return octave_value (bsxfun_pow (xa, xb));
+        }
+      else
+        {
+          gripe_nonconformant ("operator .^", a_dims, b_dims);
+          return octave_value ();
+        }
     }
 
   int len = a.length ();
@@ -2637,8 +2686,15 @@
 
   if (a_dims != b_dims)
     {
-      gripe_nonconformant ("operator .^", a_dims, b_dims);
-      return octave_value ();
+      if (is_valid_bsxfun (a_dims, b_dims))
+        {
+          return bsxfun_pow (a, b);
+        }
+      else
+        {
+          gripe_nonconformant ("operator .^", a_dims, b_dims);
+          return octave_value ();
+        }
     }
 
   FloatComplexNDArray result (a_dims);
@@ -2729,8 +2785,15 @@
 
   if (a_dims != b_dims)
     {
-      gripe_nonconformant ("operator .^", a_dims, b_dims);
-      return octave_value ();
+      if (is_valid_bsxfun (a_dims, b_dims))
+        {
+          return bsxfun_pow (a, b);
+        }
+      else
+        {
+          gripe_nonconformant ("operator .^", a_dims, b_dims);
+          return octave_value ();
+        }
     }
 
   FloatComplexNDArray result (a_dims);
@@ -2772,8 +2835,15 @@
 
   if (a_dims != b_dims)
     {
-      gripe_nonconformant ("operator .^", a_dims, b_dims);
-      return octave_value ();
+      if (is_valid_bsxfun (a_dims, b_dims))
+        {
+          return bsxfun_pow (a, b);
+        }
+      else
+        {
+          gripe_nonconformant ("operator .^", a_dims, b_dims);
+          return octave_value ();
+        }
     }
 
   FloatComplexNDArray result (a_dims);
--- a/test/Makefile.am	Tue Sep 20 15:33:10 2011 -0400
+++ b/test/Makefile.am	Tue Sep 20 15:38:24 2011 -0400
@@ -25,6 +25,7 @@
   test_args.m \
   test_classes.m \
   test_contin.m \
+  test_ctor_vs_method.m \
   test_diag_perm.m \
   test_error.m \
   test_eval-catch.m \
@@ -44,7 +45,6 @@
   test_recursion.m \
   test_return.m \
   test_slice.m \
-  test_string.m \
   test_struct.m \
   test_switch.m \
   test_system.m \
@@ -62,6 +62,8 @@
 include @Snork/module.mk
 include @Spork/module.mk
 
+include ctor-vs-method/module.mk
+
 check: test_sparse.m test_bc_overloads.m
 	$(top_builddir)/run-octave --norc --silent --no-history $(srcdir)/fntests.m $(srcdir)
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/ctor-vs-method/@derived/derived.m	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,5 @@
+function r = derived (varargin)
+  __trace__ ('begin derived/derived');
+  r = class (struct (), 'derived', parent ());
+  __trace__ ('end derived/derived');
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/ctor-vs-method/@derived/parent.m	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,9 @@
+function r = parent (a)
+  __trace__ ('begin derived/parent');
+  if (isa (a, 'parent'))
+    r = parent (a.parent);
+  else
+    error ('foo');
+  end
+  __trace__ ('end derived/parent');
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/ctor-vs-method/@other/other.m	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,5 @@
+function r = other (varargin)
+  __trace__ ('begin other/other');
+  r = class (struct (), 'other');
+  __trace__ ('end other/other');
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/ctor-vs-method/@other/parent.m	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,4 @@
+function r = parent (a)
+  __trace__ ('begin other/parent');
+  __trace__ ('end other/parent');
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/ctor-vs-method/@parent/method.m	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,5 @@
+function r = method (a)
+  __trace__ ('begin parent/method');
+  r = parent (a);
+  __trace__ ('end parent/method');
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/ctor-vs-method/@parent/parent.m	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,15 @@
+function rot = parent (a)
+  __trace__ ('begin parent/parent');
+  if (nargin == 0)
+    rot = class (struct (), 'parent');
+  else
+    switch class (a)
+      case 'parent'
+        %% copy constructor
+	rot = a;
+      otherwise
+	error ('type mismatch in parent constructor')
+    end
+  end
+  __trace__ ('end parent/parent');
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/ctor-vs-method/__trace__.m	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,18 @@
+function r = __trace__ (t)
+  persistent history
+  if (isempty (history))
+    history = {};
+  end
+  if (nargin == 0)
+    if (nargout == 0)
+      history = {};
+    else
+      r = history;
+    end
+  elseif (nargin == 1);
+    history = [history; t];
+  else
+    error ('incorrect call to __trace__');
+  end
+end
+    
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/ctor-vs-method/module.mk	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,10 @@
+ctor_vs_method_FCN_FILES = \
+  ctor-vs-method/@derived/derived.m \
+  ctor-vs-method/@derived/parent.m \
+  ctor-vs-method/@other/other.m \
+  ctor-vs-method/@other/parent.m \
+  ctor-vs-method/@parent/method.m \
+  ctor-vs-method/@parent/parent.m \
+  ctor-vs-method/__trace__.m
+
+FCN_FILES += $(ctor_vs_method_FCN_FILES)
--- a/test/fntests.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/test/fntests.m	Tue Sep 20 15:38:24 2011 -0400
@@ -91,7 +91,18 @@
   if (fid >= 0)
     str = fread (fid, "*char")';
     fclose (fid);
-    retval = ! isempty (regexp (str, '^%!(test|assert|error|warning)', "lineanchors"));
+    retval = ! isempty (regexp (str, '^%!(assert|error|fail|test|warning)', "lineanchors"));
+  else
+    error ("fopen failed: %s", f);
+  endif
+endfunction
+
+function retval = has_demos (f)
+  fid = fopen (f);
+  if (fid >= 0)
+    str = fread (fid, "*char")';
+    fclose (fid);
+    retval = ! isempty (regexp (str, '^%!demo', "lineanchors"));
   else
     error ("fopen failed: %s", f);
   endif
@@ -113,6 +124,8 @@
         [p, n, xf, sk] = test (nm(1:(end-2)), "quiet", fid);
         print_pass_fail (n, p);
         files_with_tests(end+1) = ffnm;
+      ##elseif (has_demos (ffnm))
+      ##  files_with_tests(end+1) = ffnm;
       else
         files_with_no_tests(end+1) = ffnm;
       endif
@@ -164,6 +177,8 @@
         dxf += xf;
         dsk += sk;
         files_with_tests(end+1) = f;
+      ##elseif (has_demos (f))
+      ##  files_with_tests(end+1) = f;
       elseif (has_functions (f))
         ## To reduce the list length, only mark .cc files that contain
         ## DEFUN definitions.
@@ -192,16 +207,11 @@
 endfunction
 
 function n = num_elts_matching_pattern (lst, pat)
-  n = 0;
-  for i = 1:length (lst)
-    if (! isempty (regexp (lst{i}, pat, "once")))
-      n++;
-    endif
-  endfor
+  n = sum (cellfun (@(x) !isempty (x), regexp (lst, pat, 'once')));
 endfunction
 
 function report_files_with_no_tests (with, without, typ)
-  pat = cstrcat ("\\", typ, "$");
+  pat = cstrcat ('\', typ, "$");
   n_with = num_elts_matching_pattern (with, pat);
   n_without = num_elts_matching_pattern (without, pat);
   n_tot = n_with + n_without;
@@ -258,6 +268,12 @@
     puts ("because the needed libraries were not present when Octave was built.\n");
   endif
 
+  ## Weed out deprecated and private functions
+  weed_idx = cellfun (@isempty, regexp (files_with_tests, '\bdeprecated\b|\bprivate\b', 'once'));
+  files_with_tests = files_with_tests(weed_idx);
+  weed_idx = cellfun (@isempty, regexp (files_with_no_tests, '\bdeprecated\b|\bprivate\b', 'once'));
+  files_with_no_tests = files_with_no_tests(weed_idx);
+
   report_files_with_no_tests (files_with_tests, files_with_no_tests, ".m");
   report_files_with_no_tests (files_with_tests, files_with_no_tests, ".cc");
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/test_ctor_vs_method.m	Tue Sep 20 15:38:24 2011 -0400
@@ -0,0 +1,56 @@
+## Copyright (C) 2011 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 3 of the License, 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, see
+## <http://www.gnu.org/licenses/>.
+
+%%  Test script for legacy OOP.
+%%  Requires the path to contain the directory ctor-vs-method.
+%%
+%%  Note: This script and all classes are also intended to run
+%%        in Matlab to test compatibility.  Don't break that!
+
+%!shared d, o
+%! d = derived ();
+%! o = other ();
+%!
+%!error method (o);
+
+%!test
+%! ctrace = {'begin parent/method';
+%!           'begin derived/parent';
+%!           'begin parent/parent';
+%!           'end parent/parent';
+%!           'end derived/parent';
+%!           'end parent/method'};
+%! __trace__ (); %% clear call trace info
+%! method (d);
+%! assert (__trace__ (), ctrace);
+
+%!test
+%! ctrace = {'begin other/parent';
+%!           'end other/parent'};
+%! __trace__ (); %% clear call trace info
+%! parent (o);
+%! assert (__trace__ (), ctrace);
+
+%!test
+%! ctrace = {'begin derived/parent';
+%!           'begin parent/parent';
+%!           'end parent/parent';
+%!           'end derived/parent'};
+%! __trace__ (); %% clear call trace info
+%! parent (d);
+%! assert (__trace__ (), ctrace);
--- a/test/test_io.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/test/test_io.m	Tue Sep 20 15:38:24 2011 -0400
@@ -245,6 +245,27 @@
 %!assert (sscanf ('123456', '%10c'), '123456')
 %!assert (sscanf ('123456', '%10s'), '123456')
 
+%!test
+%! [val, count, msg, pos] = sscanf ("3I2", "%f");
+%! assert (val, 3);
+%! assert (count, 1);
+%! assert (msg, "");
+%! assert (pos, 2);
+
+%!test
+%! [val, count, msg, pos] = sscanf ("3In2", "%f");
+%! assert (val, 3);
+%! assert (count, 1);
+%! assert (msg, "");
+%! assert (pos, 2);
+
+%!test
+%! [val, count, msg, pos] = sscanf ("3Inf2", "%f");
+%! assert (val, [3; Inf; 2]);
+%! assert (count, 3);
+%! assert (msg, "");
+%! assert (pos, 6);
+
 %% test/octave.test/io/sscanf-1.m
 %!test
 %! [a, b, c] = sscanf ("1.2 3 foo", "%f%d%s", "C");
--- a/test/test_parser.m	Tue Sep 20 15:33:10 2011 -0400
+++ b/test/test_parser.m	Tue Sep 20 15:38:24 2011 -0400
@@ -28,142 +28,222 @@
 %!assert ({1 2,{3,4}}, {1,2,{3,4}})
 %!assert ({1,2,{3 4}}, {1,2,{3,4}})
 
-%# Tests for operator precedence as documented in section 8.8 of manual
-%# There are 11 levels of precedence from "exponentiation" (highest) down to
-%# "statement operators" (lowest).
-%#
-%# Level 11 (exponentiation) overrides all others
+## Tests for operator precedence as documented in section 8.8 of manual
+## There are 13 levels of precedence from "parentheses and indexing" (highest)
+## down to "statement operators" (lowest).
+##
+## Level 13 (parentheses and indexing)
+## Overrides all other levels
+%!test
+%!  a.b = 1;
+%!  assert (a. b++, 1)
+%!  assert (a.b, 2)
+%!  clear a;
+%!  a.b = [0 1];
+%!  b = 2;
+%!  assert (a.b', [0;1])
+%!  assert (!a .b, logical ([1 0]))
+%!  assert (3*a .b, [0 3])
+%!  assert (a. b-1, [-1 0])
+%!  assert (a. b:3, 0:3)
+%!  assert (a. b>0.5, logical ([0 1]))
+%!  assert (a. b&0, logical ([0 0]))
+%!  assert (a. b|0, logical ([0 1]))
+%!  a.b = [1 2];
+%!  assert (a. b&&0, false)
+%!  assert (a. b||0, true)
+%!  a.b += a. b*2;
+%!  assert (a.b, [3 6])
+## Level 12 (postfix increment and decrement)
 %!test
-%!  assert (-2^2, -4)
-%!  assert (!0^0, false);
-# FIXME: This test is failing.  Transpose mistakenly has higher priority.
-%!#  assert ([2 3].^2', [4; 9])
-%!  assert (2*3^2, 18)
-%!  assert (2+3^2, 11)
-%!  assert ([1:10](1:2^2), [1 2 3 4])
-%!  assert (3 > 2^2, false)
-%!  assert (1 & 0^0, true)
-%!  assert (1 && 0^0, true)
+%!  a = [3 5];
+%!  assert (2.^a ++, [8 32])
+%!  assert (a, [4 6])
+%!  assert (a--', [4; 6])
+%!  assert (a, [3 5])
+%!  a = 0;
+%!  assert (!a --, true)
+%!  assert (-a ++, 1)
+%!  assert (3*a ++, 0)
+%!  assert (a++-2, -1)
+%!  assert (1:a ++, 1:2)
+%!  assert (4>a++, true)
+%!  a = [0 -1];
+%!  assert ([1 1] & a++, logical ([0 1]))
+%!  assert ([0 0] | a++, logical ([1 0]))
+%!  a = 0;
+%!  assert (1 && a ++, false)
+%!  assert (0 || a --, true)
+%!  a = 5; b = 2;
+%!  b +=a ++;
+%!  assert (b, 7)
+
+## Level 11 (transpose and exponentiation)
+%!test
+%!  assert (-2 ^2, -4)
+%!  assert (!0 ^0, false)
+%!  assert (2*3 ^2, 18)
+%!  assert (2+3 ^2, 11)
+%!  assert ([1:10](1:2 ^2), [1 2 3 4])
+%!  assert (3>2 ^2, false)
+%!  assert (1&0 ^0, true)
+%!  assert (0|0 ^0, true)
+%!  assert (1&&0 ^0, true)
+%!  assert (0||0 ^0, true)
 %!  a = 3;
-%!  a *= 0^0;
+%!  a *= 0 ^0;
 %!  assert (a, 3)
-%# Level 10 (unary plus, increment, not)
+## Level 10 (unary plus/minus, prefix increment/decrement, not)
 %!test
-# FIXME: No test for increment and transpose that I can think of.
 %!  a = 2;
-%!  assert (++a*3, 9)
-%!  assert (a++-2, 1)
-%!  assert (a, 4)
-%!  assert ([1:10](1:++a), [1:5])
-%!  assert (5 == a++, true)
-%!  assert (7 == ++a, true)
+%!  assert (++ a*3, 9)
+%!  assert (-- a-2, 0)
+%!  assert (a, 2)
+%!  assert (! a-2, -2)
+%!  assert ([1:10](++ a:5), 3:5)
+%!  a = [1 0];
+%!  assert (! a>=[1 0], [false true])
 %!  a = 0;
-%!  assert (1 & a++, false)
-%!  assert (a, 1)
-%!  assert (1 && --a, false)
+%!  assert (++ a&1, true)
+%!  assert (-- a|0, false)
+%!  assert (-- a&&1, true)
+%!  assert (++ a||0, false)
 %!  a = 3;
-%!  a *= a++;
-%!  assert (a, 12)
-%# Level 9 (transpose)
+%!  a *= ++a;
+%!  assert (a, 16)
+## Level 9 (multiply, divide)
 %!test
-%!  assert ([1 2]*[3 4]', 11)
-%!  assert ([1 2]'+[3 4]', [4; 6])
-%!  assert (1:5', 1:5)
-%!  assert ([1; 2] == [1 2]', [true; true])
-%!  assert ([1; 0] & [1 0]', [true; false])
-# FIXME: No test for transpose and short-circuit operator that I can think of.
-%!  a = [1 2];
-%!  a *= [3 4]';
-%!  assert (a, 11)
-%# Level 8 (multiply, divide)
-%!test
-%!  assert (3 + 4 * 5, 23)
-%!  assert (3 + 4 * 5, 23)
-%!  assert (5*1:6, [5 6])
-%!  assert (3 > 1 * 5, false)
-%!  assert (1 & 1 * 0, false)
-%!  assert (1 && 1 * 0, false)
+%!  assert (3+4 * 5, 23)
+%!  assert (5 * 1:6, [5 6])
+%!  assert (3>1 * 5, false)
+%!  assert (1&1 * 0, false)
+%!  assert (1|1 * 0, true)
+%!  assert (1&&1 * 0, false)
+%!  assert (1||1 * 0, true)
 %!  a = 3;
 %!  a /= a * 2;
 %!  assert (a, 0.5)
-%# Level 7 (add, subtract)
+## Level 8 (add, subtract)
 %!test
 %!  assert ([2 + 1:6], 3:6)
-%!  assert (3 > 1 + 5, false)
-%!  assert (1 & 1 - 1, false)
-%!  assert (1 && 1 - 1, false)
+%!  assert (3>1 + 5, false)
+%!  assert (1&1 - 1, false)
+%!  assert (0|1 - 2, true)
+%!  assert (1&&1 - 1, false)
+%!  assert (0||1 - 2, true)
 %!  a = 3;
 %!  a *= 1 + 1;
 %!  assert (a, 6)
-%# Level 6 (colon)
+## Level 7 (colon)
 %!test
-%!  assert (5:-1: 3 > 4, [true false false])
-%!  assert (1: 3 & 1, [true true true])
-%!  assert (-1: 3 && 1, false)
+%!  assert (5:-1: 3>4, [true false false])
+%!  assert (1: 3&1, [true true true])
+%!  assert (1: 3|0, [true true true])
+%!  assert (-1: 3&&1, false)
+%!  assert (-1: 3||0, false)
 %!  a = [1:3];
 %!  a += 3 : 5;
 %!  assert (a, [4 6 8])
-%# Level 5 (relational)
+## Level 6 (relational)
 %!test
-%!  assert (0 == -1 & 0, false)
-%!  assert (0 == -1 && 0, false)
+%!  assert (0 == -1&0, false)
+%!  assert (1 == -1|0, false)
+%!  assert (0 == -1&&0, false)
+%!  assert (1 == -1||0, false)
 %!  a = 2;
 %!  a *= 3 > 1;
 %!  assert (a, 2)
-%# Level 4 (element-wise and, or)
+## Level 5 (element-wise and)
 %!test
-%!  assert (0 & 1 || 1, true)
-%!  assert (0 == -1 && 0, false)
+%!  assert (0 & 1|1, true)
+%!  assert ([0 1] & 1&&1, false)
+%!  assert (0 & 1||1, true)
 %!  a = 2;
 %!  a *= 3 & 1;
 %!  assert (a, 2)
-%# Level 3 (logical and, or)
+## Level 4 (element-wise or)
 %!test
+%!  assert ([0 1] | 1&&0, false)
+%!  assert ([0 1] | 1||0, true)
+%!  a = 2;
+%!  a *= 0 | 1;
+%!  assert (a, 2)
+## Level 3 (logical and)
+%!test
+%!  assert (0 && 1||1, true)
 %!  a = 2;
 %!  a *= 3 && 1;
 %!  assert (a, 2)
+## Level 2 (logical or)
+%!test
+%!  a = 2;
+%!  a *= 0 || 1;
+%!  assert (a, 2)
 
-%# Tests for operator precedence within each level where ordering should
-%# be left to right except for exponents and assignments.
-%# Level 11 (exponentiation)
+## Tests for operator precedence within each level where ordering should
+## be left to right except for postfix and assignment operators.
+
+## Level 13 (parentheses and indexing)
 %!test
-%# FIXME : Exponentiation seems to work left to right, despite the 
-%#         documentation and ordinary mathematical rules of precedence.
-%!#  assert (2^3**2, 512)
-%# Level 10 (unary plus, increment, not)
+%!  a.b1 = 2;
+%!  assert (a.(strcat('b','1'))++, 2)
+%!  assert (a.b1, 3)
+%!  b = {1 2 3 4 5};
+%!  assert (b{(a. b1 + 1)}, 4)
+%!  b = 1:5;
+%!  assert (b(a. b1 + 1), 4)
+%!  assert ([2 3].^2', [4; 9])
+## Level 12 (postfix increment and decrement)
+## No tests possible since a++-- is not valid
+## Level 11 (transpose and exponentiation)
+## Note: Exponentiation works left to right for compatibility with Matlab.
+%!  assert (2^3**2, 64)
+%!  assert ([2 3].^2.', [4;9])
+%!  assert ([2 3].'.^2, [4;9])
+%!  assert (3*4i'.', 0 - 12i)
+%!  assert (3*4i.'.', 0 + 12i)
+## Level 10 (unary plus/minus, prefix increment/decrement, not)
 %!test
 %!  assert (+-+1, -1)
-%!  a = 0;
-%# FIXME : Should we test for this corner case at all?
-%#         (unary minus)(auto-decrement operator)
-%!#  assert (---a, 1);
 %!  a = -1;
 %!  assert (!++a, true)
 %!  assert (a, 0)
 %!  assert (-~a, -1)
-%!  assert (!~a++, false)
-%!  assert (a, 1)
-%# Level 9 (transpose)
+%!  assert (!~--a, true)
+%!  assert (a, -1)
+## Level 9 (multiply, divide)
 %!test
-%!  assert (3*4i'.', 0 - 12i)
-%!  assert (3*4i.'.', 0 + 12i)
-%# Level 8 (multiply, divide)
+%!  assert (3 * 4 / 5, 2.4)
+%!  assert (3 ./ 4 .* 5, 3.75)
+%!  assert (2 * 4 \ 6, 0.75)
+%!  assert (2 .\ 4 .* 6, 12)
+## Level 8 (add, subtract)
 %!test
-%!assert (3 * 4 / 5, 2.4)
-%!assert (3 ./ 4 .* 5, 3.75)
-%# Level 7 (add, subtract)
-%!test
-%!assert (-3 - 4 + 1 + 3 * 2, 0)
-%# Level 5 (relational)
+%!  assert (-3 - 4 + 1 + 3 * 2, 0)
+## Level 7 (colon)
+## No tests possible because colon operator can't be combined with second colon operator
+## Level 6 (relational)
 %!test
 %!  assert (0 < 1 <= 0.5 == 0 >= 0.5 > 0, true)
 %!  assert (1 < 1 == 0 != 0, true)
 %!  assert (1 < 1 == 0 ~= 0, true)
-%# Level 4 (element-wise and, or)
+## Level 5 (element-wise and)
+## No tests possible.  Only one operator (&) at this precedence level and operation is associative.
+## Level 4 (element-wise or)
+## No tests possible.  Only one operator (|) at this precedence level and operation is associative.
+## Level 3 (logical and)
 %!test
-%!  assert ([ 1 0] & [0 1] | [1 0], [true false])
-%# Level 2 (assignment)
+%!  a = 1;
+%!  assert (1 && 0 && ++a, false)
+%!  assert (a, 1)
+## Level 2 (logical or)
+%!test
+%!  a = 1;
+%!  assert (0 || 1 || ++a, true)
+%!  assert (a, 1)
+## Level 1 (assignment)
 %!test
 %! a = 2; b = 5; c = 7;
 %! assert (a += b *= c += 1, 42)
 %! assert (b == 40 && c == 8)
+
--- a/test/test_string.m	Tue Sep 20 15:33:10 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,454 +0,0 @@
-## Copyright (C) 2006-2011 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 3 of the License, 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, see
-## <http://www.gnu.org/licenses/>.
-
-%% test/octave.test/string/str-esc-1.m
-%!test
-%! x = 7;
-%! if (strcmp ("\a", setstr (x)))
-%! printf_assert ("ok\n");
-%! endif
-%! assert(prog_output_assert("ok"));
-
-%% test/octave.test/string/str-esc-2.m
-%!test
-%! x = 8;
-%! if (strcmp ("\b", setstr (x)))
-%! printf_assert ("ok\n");
-%! endif
-%! assert(prog_output_assert("ok"));
-
-%% test/octave.test/string/str-esc-3.m
-%!test
-%! x = 12;
-%! if (strcmp ("\f", setstr (x)))
-%! printf_assert ("ok\n");
-%! endif
-%! assert(prog_output_assert("ok"));
-
-%% test/octave.test/string/str-esc-4.m
-%!test
-%! x = 10;
-%! if (strcmp ("\n", setstr (x)))
-%! printf_assert ("ok\n");
-%! endif
-%! assert(prog_output_assert("ok"));
-
-%% test/octave.test/string/str-esc-5.m
-%!test
-%! x = 13;
-%! if (strcmp ("\r", setstr (x)))
-%! printf_assert ("ok\n");
-%! endif
-%! assert(prog_output_assert("ok"));
-
-%% test/octave.test/string/str-esc-6.m
-%!test
-%! x = 9;
-%! if (strcmp ("\t", setstr (x)))
-%! printf_assert ("ok\n");
-%! endif
-%! assert(prog_output_assert("ok"));
-
-%% test/octave.test/string/str-esc-7.m
-%!test
-%! x = 11;
-%! if (strcmp ("\v", setstr (x)))
-%! printf_assert ("ok\n");
-%! endif
-%! assert(prog_output_assert("ok"));
-
-%% test/octave.test/string/str-esc-8.m
-%!test
-%! x = 92;
-%! if (strcmp ("\\", setstr (x)))
-%! printf_assert ("ok\n");
-%! endif
-%! assert(prog_output_assert("ok"));
-
-%% test/octave.test/string/str-esc-9.m
-%!test
-%! x = 39;
-%! if (strcmp ("\'", setstr (x)))
-%! printf_assert ("ok\n");
-%! endif
-%! assert(prog_output_assert("ok"));
-
-%% test/octave.test/string/str-esc-10.m
-%!test
-%! x = 34;
-%! if (strcmp ("\"", setstr (x)))
-%! printf_assert ("ok\n");
-%! endif
-%! assert(prog_output_assert("ok"));
-
-%% test/octave.test/string/str-esc-11.m
-%!test
-%! x = 120;
-%! fail('strcmp ("\x", setstr (x))',"warning",".*unrecognized escape sequence.*");
-
-%% test/octave.test/string/str-esc-12.m
-%!test
-%! x = [7, 8, 12, 10, 13, 9, 11, 92, 39, 34];
-%! if (strcmp ("\a\b\f\n\r\t\v\\\'\"", setstr (x)))
-%! printf_assert ("ok\n");
-%! endif
-%! assert(prog_output_assert("ok"));
-
-%% FIXME
-%% Why do the next two tests fail?
-%% test/octave.test/string/string_fill_char-1.m
-%!#test
-%! sfc = string_fill_char;
-%! string_fill_char = "X";
-%! str = ["these"; "are"; "strings"];
-%! assert(str,["theseXX"; "areXXXX"; "strings"]);
-%! string_fill_char = sfc;
-
-%% test/octave.test/string/string_fill_char-2.m
-%!#test
-%! sfc = string_fill_char;
-%! string_fill_char = " ";
-%! str = ["these"; "are"; "strings"];
-%! assert(str,["these  "; "are    "; "strings"]);
-%! string_fill_char = sfc;
-
-%% test/octave.test/string/ischar-1.m
-%!assert(!(ischar (1)));
-
-%% test/octave.test/string/ischar-2.m
-%!assert(!(ischar ([1, 2])));
-
-%% test/octave.test/string/ischar-3.m
-%!assert(!(ischar ([])));
-
-%% test/octave.test/string/ischar-4.m
-%!assert(!(ischar ([1, 2; 3, 4])));
-
-%% test/octave.test/string/ischar-5.m
-%!assert(ischar (""));
-
-%% test/octave.test/string/ischar-6.m
-%!assert(ischar ("t"));
-
-%% test/octave.test/string/ischar-7.m
-%!assert(ischar ("test"));
-
-%% test/octave.test/string/ischar-8.m
-%!assert(ischar (["test"; "ing"]));
-
-%% test/octave.test/string/ischar-9.m
-%!test
-%! s.a = "test";
-%! assert(!(ischar (s)));
-
-%% test/octave.test/string/ischar-10.m
-%!error <Invalid call to ischar.*> ischar ();
-
-%% test/octave.test/string/ischar-11.m
-%!error <Invalid call to ischar.*> ischar ("test", 1);
-
-
-%% test/octave.test/string/char-1.m
-%!assert(strcmp (char ([65, 83, 67, 73, 73]), "ASCII"));
-
-%% test/octave.test/string/char-2.m
-%!error <Invalid call to char.*> char ();
-
-%% test/octave.test/string/char-3.m
-%!test
-%! x = char ("foo", "bar", "foobar");
-%! assert((strcmp (x(1,:), "foo   ")
-%! && strcmp (x(2,:), "bar   ")
-%! && strcmp (x(3,:), "foobar")));
-
-
-%% test/octave.test/string/strcmp-1.m
-%!assert(strcmp ("foobar", "foobar") && strcmp ("fooba", "foobar") == 0);
-
-%% test/octave.test/string/strcmp-2.m
-%!error <Invalid call to strcmp.*> strcmp ();
-
-%% test/octave.test/string/strcmp-3.m
-%!error <Invalid call to strcmp.*> strcmp ("foo", "bar", 3);
-
-
-
-%% test/octave.test/string/undo_string_escapes-1.m
-%!assert(strcmp (undo_string_escapes ("abc\a\b\n\r\t\v\f123"),
-%! "abc\\a\\b\\n\\r\\t\\v\\f123"));
-
-%% test/octave.test/string/undo_string_escapes-2.m
-%!error <Invalid call to undo_string_escapes.*> undo_string_escapes ();
-
-%% test/octave.test/string/undo_string_escapes-3.m
-%!error <Invalid call to undo_string_escapes.*> undo_string_escapes ("string", 2);
-
-%% test/octave.test/string/toascii-1.m
-%!test
-%! charset = setstr (0:127);
-%! 
-%! result = 0:127;
-%! 
-%! assert(all (toascii (charset) == result));
-
-%% test/octave.test/string/toascii-3.m
-%!error toascii (1, 2);
-
-%% test/octave.test/string/toascii-3.m
-%!error toascii (1, 2);
-
-%% test/octave.test/string/tolower-1.m
-%!test
-%! charset = setstr (0:127);
-%! 
-%! result = charset;
-%! 
-%! result ((toascii("A"):toascii("Z"))+1) \
-%! = result ((toascii("a"):toascii("z"))+1);
-%! 
-%! assert(all (tolower (charset) == result));
-
-%% test/octave.test/string/tolower-3.m
-%!error tolower (1, 2);
-
-%% test/octave.test/string/tolower-3.m
-%!error tolower (1, 2);
-
-%% test/octave.test/string/toupper-1.m
-%!test
-%! charset = setstr (0:127);
-%! 
-%! result = charset;
-%! 
-%! result ((toascii("a"):toascii("z"))+1) \
-%! = result ((toascii("A"):toascii("Z"))+1);
-%! 
-%! assert(all (toupper (charset) == result));
-
-%% test/octave.test/string/toupper-3.m
-%!error toupper (1, 2);
-
-%% test/octave.test/string/toupper-3.m
-%!error toupper (1, 2);
-
-%% test/octave.test/string/isalnum-1.m
-%!test
-%! charset = setstr (0:127);
-%! 
-%! result = zeros (1, 128);
-%! 
-%! result ((toascii("A"):toascii("Z"))+1) = 1;
-%! result ((toascii("0"):toascii("9"))+1) = 1;
-%! result ((toascii("a"):toascii("z"))+1) = 1;
-%! 
-%! assert(all (isalnum (charset) == result));
-
-%% test/octave.test/string/isalnum-2.m
-%!error isalnum (1, 2);
-
-%% test/octave.test/string/isalnum-3.m
-%!error isalnum ();
-
-%% test/octave.test/string/isalpha-1.m
-%!test
-%! charset = setstr (0:127);
-%! 
-%! result = zeros (1, 128);
-%! 
-%! result ((toascii("A"):toascii("Z"))+1) = 1;
-%! result ((toascii("a"):toascii("z"))+1) = 1;
-%! 
-%! assert(all (isalpha (charset) == result));
-
-%% test/octave.test/string/isalpha-2.m
-%!error isalpha (1, 2);
-
-%% test/octave.test/string/isalpha-3.m
-%!error isalpha ();
-
-%% test/octave.test/string/isascii-1.m
-%!test
-%! charset = setstr (0:127);
-%! 
-%! result = ones (1, 128);
-%! 
-%! assert(all (isascii (charset) == result));
-
-%% test/octave.test/string/isascii-2.m
-%!error isascii (1, 2);
-
-%% test/octave.test/string/isascii-3.m
-%!error isascii ();
-
-%% test/octave.test/string/iscntrl-1.m
-%!test
-%! charset = setstr (0:127);
-%! 
-%! result = zeros (1, 128);
-%! 
-%! result (1:32) = 1;
-%! result (128) = 1;
-%! 
-%! assert(all (iscntrl (charset) == result));
-
-%% test/octave.test/string/iscntrl-2.m
-%!error iscntrl (1, 2);
-
-%% test/octave.test/string/iscntrl-3.m
-%!error iscntrl ();
-
-%% test/octave.test/string/isdigit-1.m
-%!test
-%! charset = setstr (0:127);
-%! 
-%! result = zeros (1, 128);
-%! 
-%! result ((toascii("0"):toascii("9"))+1) = 1;
-%! 
-%! assert(all (isdigit (charset) == result));
-
-%% test/octave.test/string/isdigit-2.m
-%!error isdigit (1, 2);
-
-%% test/octave.test/string/isdigit-3.m
-%!error isdigit ();
-
-%% test/octave.test/string/isgraph-1.m
-%!test
-%! charset = setstr (0:127);
-%! 
-%! result = zeros (1, 128);
-%! 
-%! result (34:127) = 1;
-%! 
-%! assert(all (isgraph (charset) == result));
-
-%% test/octave.test/string/isgraph-2.m
-%!error isgraph (1, 2);
-
-%% test/octave.test/string/isgraph-3.m
-%!error isgraph ();
-
-%% test/octave.test/string/islower-1.m
-%!test
-%! charset = setstr (0:127);
-%! 
-%! result = zeros (1, 128);
-%! 
-%! result ((toascii("a"):toascii("z"))+1) = 1;
-%! 
-%! assert(all (islower (charset) == result));
-
-%% test/octave.test/string/islower-2.m
-%!error islower (1, 2);
-
-%% test/octave.test/string/islower-3.m
-%!error islower ();
-
-%% test/octave.test/string/isprint-1.m
-%!test
-%! charset = setstr (0:127);
-%! 
-%! result = zeros (1, 128);
-%! 
-%! result (33:127) = 1;
-%! if (ispc () && ! isunix ())
-%!   result(10) = 1;
-%! endif
-%! 
-%! assert(all (isprint (charset) == result));
-
-%% test/octave.test/string/isprint-2.m
-%!error isprint (1, 2);
-
-%% test/octave.test/string/isprint-3.m
-%!error isprint ();
-
-%% test/octave.test/string/ispunct-1.m
-%!test
-%! charset = setstr (0:127);
-%! 
-%! result = zeros (1, 128);
-%! 
-%! result (34:48) = 1;
-%! result (59:65) = 1;
-%! result (92:97) = 1;
-%! result (124:127) = 1;
-%! 
-%! assert(all (ispunct (charset) == result));
-
-%% test/octave.test/string/ispunct-2.m
-%!error ispunct (1, 2);
-
-%% test/octave.test/string/ispunct-3.m
-%!error ispunct ();
-
-%% test/octave.test/string/isspace-1.m
-%!test
-%! charset = setstr (0:127);
-%! 
-%! result = zeros (1, 128);
-%! 
-%! result (toascii (" \f\n\r\t\v")+1) = 1;
-%! 
-%! assert(all (isspace (charset) == result));
-
-%% test/octave.test/string/isspace-2.m
-%!error isspace (1, 2);
-
-%% test/octave.test/string/isspace-3.m
-%!error isspace ();
-
-%% test/octave.test/string/isupper-1.m
-%!test
-%! charset = setstr (0:127);
-%! 
-%! result = zeros (1, 128);
-%! 
-%! result ((toascii("A"):toascii("Z"))+1) = 1;
-%! 
-%! assert(all (isupper (charset) == result));
-
-%% test/octave.test/string/isupper-2.m
-%!error isupper (1, 2);
-
-%% test/octave.test/string/isupper-3.m
-%!error isupper ();
-
-%% test/octave.test/string/isxdigit-1.m
-%!test
-%! charset = setstr (0:127);
-%! 
-%! result = zeros (1, 128);
-%! 
-%! result ((toascii("A"):toascii("F"))+1) = 1;
-%! result ((toascii("0"):toascii("9"))+1) = 1;
-%! result ((toascii("a"):toascii("f"))+1) = 1;
-%! 
-%! assert(all (isxdigit (charset) == result));
-
-%% test/octave.test/string/isxdigit-2.m
-%!error isxdigit (1, 2);
-
-%% test/octave.test/string/isxdigit-3.m
-%!error isxdigit ();
-
-%% test concatenation with all zero matrices
-%!assert([ '' 65*ones(1,10) ], 'AAAAAAAAAA');
-%!assert([ 65*ones(1,10) '' ], 'AAAAAAAAAA');
-