changeset 17413:9c7d8c93fb6b

Merged with main repo, after updating Latex interpreter.
author Andrej Lojdl <andrej.lojdl@gmail.com>
date Mon, 09 Sep 2013 22:34:43 +0200
parents bdda4992ccf9 (current diff) ed149e891876 (diff)
children 21f67db6ab1b
files configure.ac libinterp/Makefile.am libinterp/corefcn/graphics.cc libinterp/corefcn/graphics.in.h libinterp/corefcn/module.mk
diffstat 42 files changed, 580 insertions(+), 286 deletions(-) [+]
line wrap: on
line diff
--- a/configure.ac
+++ b/configure.ac
@@ -763,6 +763,7 @@
 
 	save_CPPFLAGS="$CPPFLAGS"
 	save_CXXFLAGS="$CXXFLAGS"
+    save_LDFLAGS="$LDFLAGS"
 
 ## Use -isystem if available because we don't want to see warnings in LLVM
 	LLVM_INCLUDE_FLAG=-I
@@ -774,7 +775,11 @@
 	LLVM_CPPFLAGS="$LLVM_INCLUDE_FLAG `$LLVM_CONFIG --includedir`"
 	LLVM_CXXFLAGS=
 	LLVM_LDFLAGS="-L`$LLVM_CONFIG --libdir`"
-	LLVM_LIBS=`$LLVM_CONFIG --libs`
+
+
+    LDFLAGS="$LDFLAGS $LLVM_LDFLAGS"
+    LLVM_SO=LLVM-`$LLVM_CONFIG --version`
+    AC_CHECK_LIB([$LLVM_SO], [LLVMBuildAdd], [LLVM_LIBS="-l$LLVM_SO"], [LLVM_LIBS=`$LLVM_CONFIG --libs`])
 
 	dnl
 	dnl Define some extra flags that LLVM requires in order to include headers.
@@ -795,6 +800,44 @@
 AC_LANG_POP(C++)
 	CPPFLAGS="$save_CPPFLAGS"
 	CXXFLAGS="$save_CXXFLAGS"
+    dnl
+    dnl Define some extra flags that LLVM requires in order to include headers.
+    dnl Ideally we should get these from llvm-config, but llvm-config isn't
+    dnl very helpful.
+    dnl
+    CPPFLAGS="-D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS $LLVM_CPPFLAGS $CPPFLAGS"
+    CXXFLAGS="$LLVM_CXXFLAGS $CXXFLAGS"
+    AC_LANG_PUSH(C++)
+    AC_CHECK_HEADER([llvm/Support/TargetSelect.h], [
+      warn_llvm=
+      XTRA_CXXFLAGS="$XTRA_CXXFLAGS $LLVM_CXXFLAGS $LLVM_CPPFLAGS"])
+
+    have_function_h=no
+    AC_CHECK_HEADERS([llvm/IR/Function.h llvm/Function.h],
+                     [have_function_h=yes; break])
+    if test $have_function_h = no; then
+      warn_llvm="Missing LLVM file Function.h.  JIT compiler is disabled."
+    fi
+    have_irbuilder_h=no
+    AC_CHECK_HEADERS([llvm/Support/IRBuilder.h llvm/IR/IRBuilder.h \
+                      llvm/IRBuilder.h], [have_irbuilder_h=yes; break])
+    if test $have_irbuilder_h = no; then
+      warn_llvm="Missing LLVM file IRBuilder.h.  JIT compiler is disabled."
+    fi
+    have_llvm_data_h=no
+    AC_CHECK_HEADERS([llvm/Target/TargetData.h llvm/IR/DataLayout.h \
+                      llvm/DataLayout.h], [have_llvm_data_h=yes; break])
+    if test $have_llvm_data_h = no; then
+      warn_llvm="Missing LLVM file TargetData.h.  JIT compiler is disabled."
+    fi
+
+    OCTAVE_LLVM_FUNCTION_ADDATTRIBUTE_API
+    OCTAVE_LLVM_FUNCTION_ADDFNATTR_API
+    OCTAVE_LLVM_CALLINST_ADDATTRIBUTE_API
+    AC_LANG_POP(C++)
+    CPPFLAGS="$save_CPPFLAGS"
+    CXXFLAGS="$save_CXXFLAGS"
+    LDFLAGS="$save_LDFLAGS"
 	fi
 
 	if test -z "$warn_llvm"; then
--- a/doc/interpreter/numbers.txi
+++ b/doc/interpreter/numbers.txi
@@ -546,6 +546,8 @@
 
 @DOCSTRING(intmin)
 
+@DOCSTRING(flintmax)
+
 @menu
 * Integer Arithmetic::
 @end menu
@@ -614,7 +616,6 @@
 for bit manipulation, particularly when forming masks, Octave supplies
 the function @code{bitmax}.
 
-@anchor{XREFflintmax}
 @DOCSTRING(bitmax)
 
 This is the double precision version of the function @code{intmax},
--- a/libgui/Makefile.am
+++ b/libgui/Makefile.am
@@ -107,5 +107,6 @@
 	$(LRELEASE) -qm $@ $<
 
 DISTCLEANFILES = \
+  default-qt-settings \
   $(LOCALES)
 
--- a/libinterp/Makefile.am
+++ b/libinterp/Makefile.am
@@ -93,8 +93,6 @@
   Makefile.in \
   DOCSTRINGS \
   config-features.sh \
-  corefcn/oct-tex-lexer.in.ll \
-  corefcn/oct-tex-symbols.in \
   find-defun-files.sh \
   gendoc.pl \
   genprops.awk \
@@ -104,7 +102,6 @@
   mkdefs \
   mkops \
   oct-conf.in.h \
-  parse-tree/oct-parse.in.yy \
   version.in.h \
   $(BUILT_DISTFILES)
 
@@ -132,7 +129,8 @@
   $(OCTAVE_VALUE_SRC) \
   $(PARSE_TREE_SRC) \
   $(PARSER_SRC) \
-  $(COREFCN_SRC)
+  $(COREFCN_SRC) \
+  $(TEX_PARSER_SRC)
 
 noinst_LTLIBRARIES =
 
@@ -183,6 +181,7 @@
   parse-tree/libparse-tree.la \
   parse-tree/libparser.la \
   corefcn/libcorefcn.la \
+  corefcn/libtex_parser.la \
   $(top_builddir)/liboctave/liboctave.la \
   $(LIBOCTINTERP_LINK_DEPS)
 
--- a/libinterp/corefcn/bitfcns.cc
+++ b/libinterp/corefcn/bitfcns.cc
@@ -38,6 +38,7 @@
 #include "ov-int32.h"
 #include "ov-int16.h"
 #include "ov-int8.h"
+#include "ov-float.h"
 #include "ov-scalar.h"
 #include "ov-re-mat.h"
 #include "ov-bool.h"
@@ -138,25 +139,55 @@
   if (nargin == 2)
     {
       if ((args(0).class_name () == octave_scalar::static_class_name ())
+          || (args(0).class_name () == octave_float_scalar::static_class_name ())
           || (args(0).class_name () == octave_bool::static_class_name ())
           || (args(1).class_name () == octave_scalar::static_class_name ())
+          || (args(1).class_name () == octave_float_scalar::static_class_name ())
           || (args(1).class_name () == octave_bool::static_class_name ()))
         {
           bool arg0_is_int = (args(0).class_name () !=
                               octave_scalar::static_class_name () &&
                               args(0).class_name () !=
+                              octave_float_scalar::static_class_name () &&
+                              args(0).class_name () !=
                               octave_bool::static_class_name ());
           bool arg1_is_int = (args(1).class_name () !=
                               octave_scalar::static_class_name () &&
                               args(1).class_name () !=
+                              octave_float_scalar::static_class_name () &&
+                              args(1).class_name () !=
                               octave_bool::static_class_name ());
+          bool arg0_is_float = args(0).class_name () ==
+                               octave_float_scalar::static_class_name ();
+          bool arg1_is_float = args(1).class_name () ==
+                               octave_float_scalar::static_class_name ();
 
           if (! (arg0_is_int || arg1_is_int))
             {
-              uint64NDArray x (args(0).array_value ());
-              uint64NDArray y (args(1).array_value ());
-              if (! error_state)
-                retval = bitopx (fname, x, y).array_value ();
+              if (! (arg0_is_float || arg1_is_float))
+                {
+                  uint64NDArray x (args(0).array_value ());
+                  uint64NDArray y (args(1).array_value ());
+                  if (! error_state)
+                    retval = bitopx (fname, x, y).array_value ();
+                }
+              else if (arg0_is_float && arg1_is_float)
+                {
+                  uint64NDArray x (args(0).float_array_value ());
+                  uint64NDArray y (args(1).float_array_value ());
+                  if (! error_state)
+                    retval = bitopx (fname, x, y).float_array_value ();
+                }
+              else
+                {
+                  int p = (arg0_is_float ? 1 : 0);
+                  int q = (arg0_is_float ? 0 : 1);
+
+                  uint64NDArray x (args(p).array_value ());
+                  uint64NDArray y (args(q).float_array_value ());
+                  if (! error_state)
+                    retval = bitopx (fname, x, y).float_array_value ();
+                }
             }
           else
             {
@@ -344,6 +375,13 @@
   return bitop ("bitxor", args);
 }
 
+template <typename T>
+static int64_t
+max_mantissa_value ()
+{
+  return (static_cast<int64_t> (1) << std::numeric_limits<T>::digits) - 1;
+}
+
 static int64_t
 bitshift (double a, int n, int64_t mask)
 {
@@ -543,16 +581,30 @@
         DO_SBITSHIFT (int64, nbits < 64 ? nbits : 64);
       else if (cname == "double")
         {
-          nbits = (nbits < 53 ? nbits : 53);
-          int64_t mask = 0x1FFFFFFFFFFFFFLL;
-          if (nbits < 53)
-            mask = mask >> (53 - nbits);
+          static const int bits_in_mantissa = std::numeric_limits<double>::digits;
+          nbits = (nbits < bits_in_mantissa ? nbits : bits_in_mantissa);
+          int64_t mask = max_mantissa_value<double> ();
+          if (nbits < bits_in_mantissa)
+            mask = mask >> (bits_in_mantissa - nbits);
           else if (nbits < 1)
             mask = 0;
-          int bits_in_type = 64;
+          int bits_in_type = sizeof (double) * CHAR_BIT;
           NDArray m = m_arg.array_value ();
           DO_BITSHIFT ( );
         }
+      else if (cname == "single")
+        {
+          static const int bits_in_mantissa = std::numeric_limits<float>::digits;
+          nbits = (nbits < bits_in_mantissa ? nbits : bits_in_mantissa);
+          int64_t mask = max_mantissa_value<float> ();
+          if (nbits < bits_in_mantissa)
+            mask = mask >> (bits_in_mantissa - nbits);
+          else if (nbits < 1)
+            mask = 0;
+          int bits_in_type = sizeof (float) * CHAR_BIT;
+          FloatNDArray m = m_arg.float_array_value ();
+          DO_BITSHIFT (Float);
+        }
       else
         error ("bitshift: not defined for %s objects", cname.c_str ());
     }
@@ -567,16 +619,12 @@
 @deftypefn  {Built-in Function} {} bitmax ()\n\
 @deftypefnx {Built-in Function} {} bitmax (\"double\")\n\
 @deftypefnx {Built-in Function} {} bitmax (\"single\")\n\
-@deftypefnx {Built-in Function} {} flintmax (@dots{})\n\
 Return the largest integer that can be represented within a floating point\n\
 value.  The default class is @qcode{\"double\"}, but @qcode{\"single\"} is a\n\
 valid option.  On IEEE-754 compatible systems, @code{bitmax} is\n\
 @w{@math{2^{53} - 1}} for @qcode{\"double\"} and @w{@math{2^{24} -1}} for\n\
 @qcode{\"single\"}.\n\
-\n\
-@code{flintmax} for FLoating point INTeger MAXimum is an alias for\n\
-@code{bitmax}.\n\
-@seealso{intmax, realmax, realmin}\n\
+@seealso{flintmax, intmax, realmax, realmin}\n\
 @end deftypefn")
 {
   octave_value retval;
@@ -592,16 +640,48 @@
     }
 
   if (cname == "double")
-    retval = (static_cast<double> (0x1FFFFFFFFFFFFFLL));
+    retval = (static_cast<double> (max_mantissa_value<double> ()));
   else if (cname == "single")
-    retval = (static_cast<double> (0xFFFFFFL));
+    retval = (static_cast<float> (max_mantissa_value<float> ()));
   else
     error ("bitmax: not defined for class '%s'", cname.c_str ());
 
   return retval;
 }
 
-DEFALIAS(flintmax, bitmax)
+DEFUN (flintmax, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn  {Built-in Function} {} flintmax ()\n\
+@deftypefnx {Built-in Function} {} flintmax (\"double\")\n\
+@deftypefnx {Built-in Function} {} flintmax (\"single\")\n\
+Return the largest integer that can be represented consecutively in a\n\
+floating point value.  The default class is @qcode{\"double\"}, but @qcode{\"single\"}\n\
+is a valid option.  On IEEE-754 compatible systems, @code{flintmax} is @w{@math{2^53}}\n\
+for @qcode{\"double\"} and @w{@math{2^24}} for @qcode{\"single\"}.\n\
+@seealso{bitmax, intmax, realmax, realmin}\n\
+@end deftypefn")
+{
+  octave_value retval;
+  std::string cname = "double";
+  int nargin = args.length ();
+
+  if (nargin == 1 && args(0).is_string ())
+    cname = args(0).string_value ();
+  else if (nargin != 0)
+    {
+      print_usage ();
+      return retval;
+    }
+
+  if (cname == "double")
+    retval = (static_cast<double> (max_mantissa_value<double> () + 1));
+  else if (cname == "single")
+    retval = (static_cast<float> (max_mantissa_value<float> () + 1));
+  else
+    error ("flintmax: not defined for class '%s'", cname.c_str ());
+
+  return retval;
+}
 
 DEFUN (intmax, args, ,
   "-*- texinfo -*-\n\
@@ -636,7 +716,7 @@
 @end table\n\
 \n\
 The default for @var{type} is @code{uint32}.\n\
-@seealso{intmin, bitmax}\n\
+@seealso{intmin, flintmax, bitmax}\n\
 @end deftypefn")
 {
   octave_value retval;
@@ -706,7 +786,7 @@
 @end table\n\
 \n\
 The default for @var{type} is @code{uint32}.\n\
-@seealso{intmax, bitmax}\n\
+@seealso{intmax, flintmax, bitmax}\n\
 @end deftypefn")
 {
   octave_value retval;
--- a/libinterp/corefcn/graphics.cc
+++ b/libinterp/corefcn/graphics.cc
@@ -5783,6 +5783,56 @@
     }
 }
 
+// Almost identical to convert_ticklabel_string but it only accepts
+// cellstr or string, not numeric input.
+static octave_value
+convert_linestyleorder_string (const octave_value& val)
+{
+  octave_value retval = val;
+
+  if (val.is_cellstr ())
+    {
+      // Always return a column vector for Matlab Compatibility
+      if (val.columns () > 1)
+        retval = val.reshape (dim_vector (val.numel (), 1));
+    }
+  else
+    {
+      string_vector sv;
+      if (val.is_string () && val.rows () == 1)
+        {
+          std::string valstr = val.string_value ();
+          std::istringstream iss (valstr);
+          std::string tmpstr;
+
+          // Split string with delimiter '|'
+          while (std::getline (iss, tmpstr, '|'))
+            sv.append (tmpstr);
+          
+          // If string ends with '|' Matlab appends a null string
+          if (*valstr.rbegin () == '|')
+            sv.append (std::string (""));
+        }
+      else
+        return retval;
+
+      charMatrix chmat (sv, ' ');
+
+      retval = octave_value (chmat);
+    }
+
+  return retval;
+}
+
+void
+axes::properties::set_linestyleorder (const octave_value& v)
+{
+  if (!error_state)
+    {
+      linestyleorder.set (convert_linestyleorder_string (v), false);
+    }
+}
+
 void
 axes::properties::set_units (const octave_value& v)
 {
--- a/libinterp/corefcn/graphics.in.h
+++ b/libinterp/corefcn/graphics.in.h
@@ -3812,7 +3812,8 @@
     //       more sense to have it so that axis ticklabels can use it.
     radio_property interpreter , "tex|{none}|latex"
     radio_property layer u , "{bottom}|top"
-    string_array_property linestyleorder , "-"
+      // FIXME: should be kind of string array.
+      any_property linestyleorder S , "-"
     double_property linewidth , 0.5
     radio_property minorgridlinestyle , "-|--|{:}|-.|none"
     radio_property nextplot , "add|replacechildren|{replace}"
--- a/libinterp/corefcn/module.mk
+++ b/libinterp/corefcn/module.mk
@@ -4,7 +4,9 @@
   corefcn/gl2ps.c \
   corefcn/graphics.in.h \
   corefcn/mxarray.in.h \
-  corefcn/oct-errno.in.cc
+  corefcn/oct-errno.in.cc \
+  corefcn/oct-tex-lexer.in.ll \
+  corefcn/oct-tex-symbols.in
 
 ## Options functions for Fortran packages like LSODE, DASPK.
 ## These are generated automagically by configure and Perl.
@@ -35,6 +37,9 @@
   corefcn/jit-ir.h \
   corefcn/pt-jit.h
 
+TEX_PARSER_INC = \
+  corefcn/oct-tex-parser.h
+
 COREFCN_INC = \
   corefcn/Cell.h \
   corefcn/action-container.h \
@@ -110,7 +115,8 @@
   corefcn/xnorm.h \
   corefcn/xpow.h \
   corefcn/zfstream.h \
-  $(JIT_INC)
+  $(JIT_INC) \
+  $(TEX_PARSER_INC)
 
 JIT_SRC = \
   corefcn/jit-util.cc \
@@ -118,6 +124,10 @@
   corefcn/jit-ir.cc \
   corefcn/pt-jit.cc
 
+TEX_PARSER_SRC = \
+  corefcn/oct-tex-lexer.ll \
+  corefcn/oct-tex-parser.yy
+
 C_COREFCN_SRC = \
   corefcn/cutils.c \
   corefcn/matherr.c \
@@ -211,8 +221,6 @@
   corefcn/oct-procbuf.cc \
   corefcn/oct-stream.cc \
   corefcn/oct-strstrm.cc \
-  corefcn/oct-tex-lexer.ll \
-  corefcn/oct-tex-parser.yy \
   corefcn/octave-link.cc \
   corefcn/pager.cc \
   corefcn/pinv.cc \
@@ -297,14 +305,6 @@
 	  -e "s|%OCTAVE_IDX_TYPE%|${OCTAVE_IDX_TYPE}|" > $@-t
 	mv $@-t $@
 
-noinst_LTLIBRARIES += corefcn/libcorefcn.la
-
-corefcn_libcorefcn_la_SOURCES = $(COREFCN_SRC)
-corefcn_libcorefcn_la_CPPFLAGS = $(liboctinterp_la_CPPFLAGS) $(FFTW_XCPPFLAGS)
-
-corefcn/oct-tex-lexer.cc: LEX_OUTPUT_ROOT := lex.octave_tex_
-corefcn/oct-tex-parser.h: corefcn/oct-tex-parser.yy
-
 corefcn/oct-tex-lexer.ll: corefcn/oct-tex-lexer.in.ll corefcn/oct-tex-symbols.in Makefile.am
 	$(AWK) 'BEGIN { print "/* DO NOT EDIT. AUTOMATICALLY GENERATED FROM oct-tex-lexer.in.ll and oct-tex-symbols.in. */"; } /^@SYMBOL_RULES@$$/ { count = 0; while (getline < "$(srcdir)/corefcn/oct-tex-symbols.in") { if ($$0 !~ /^#.*/ && NF == 3) { printf("\"\\\\%s\" { yylval->sym = %d; return SYM; }\n", $$1, count); count++; } } getline } ! /^@SYMBOL_RULES@$$/ { print }' $< > $@-t
 	mv $@-t $@
@@ -314,3 +314,19 @@
 	mv $@-t $@
 
 corefcn/txt-eng.cc: corefcn/oct-tex-symbols.cc
+corefcn/oct-tex-lexer.cc: LEX_OUTPUT_ROOT := lex.octave_tex_
+corefcn/oct-tex-parser.h: corefcn/oct-tex-parser.yy
+
+
+noinst_LTLIBRARIES += \
+  corefcn/libcorefcn.la \
+  corefcn/libtex_parser.la
+
+corefcn_libcorefcn_la_SOURCES = $(COREFCN_SRC)
+corefcn_libcorefcn_la_CPPFLAGS = $(liboctinterp_la_CPPFLAGS) $(FFTW_XCPPFLAGS)
+
+corefcn_libtex_parser_la_SOURCES = $(TEX_PARSER_SRC)
+corefcn_libtex_parser_la_CPPFLAGS = $(liboctinterp_la_CPPFLAGS)
+corefcn_libtex_parser_la_CXXFLAGS = \
+  $(filter-out -Wold-style-cast, $(AM_CXXFLAGS))
+
--- a/libinterp/corefcn/str2double.cc
+++ b/libinterp/corefcn/str2double.cc
@@ -42,9 +42,11 @@
 is_imag_unit (int c)
 { return c == 'i' || c == 'j'; }
 
-static std::istringstream&
-single_num (std::istringstream& is, double& num)
+static double
+single_num (std::istringstream& is)
 {
+  double num;
+
   char c = is.peek ();
 
   // Skip spaces.
@@ -92,7 +94,7 @@
   else
     is >> num;
 
-  return is;
+  return num;
 }
 
 static std::istringstream&
@@ -114,10 +116,10 @@
   // Accept leading sign.
   if (c == '+' || c == '-')
     {
+      have_sign = true;
       negative = c == '-';
       is.get ();
       c = is.peek ();
-      have_sign = true;
     }
 
   // Skip spaces after sign.
@@ -138,13 +140,11 @@
         {
           // just 'i' and string is finished.  Return immediately.
           imag = true;
-          num = 1.0;
-          if (negative)
-            num = -num;
+          num = negative ? -1.0 : 1.0;
           return is;
         }
       else
-        { 
+        {
           if (std::tolower (c) != 'n')
             imag = true;
           is.unget ();
@@ -152,7 +152,7 @@
     }
   else if (c == 'j')
     imag = true;
-    
+
   // It's i*num or just i
   if (imag)
     {
@@ -169,7 +169,7 @@
         {
           // Multiplier follows, we extract it as a number.
           is.get ();
-          single_num (is, num);
+          num = single_num (is);
           if (is.good ())
             c = is.peek ();
         }
@@ -179,7 +179,7 @@
   else
     {
       // It's num, num*i, or numi.
-      single_num (is, num);
+      num = single_num (is);
       if (is.good ())
         {
           c = is.peek ();
@@ -265,10 +265,9 @@
 
   std::string str = str_arg;
 
-  // FIXME -- removing all commas does too much...
-  std::string::iterator se = str.end ();
-  se = std::remove (str.begin (), se, ',');
-  str.erase (se, str.end ());
+  // FIXME: removing all commas doesn't allow actual parsing.
+  //        Example: "1,23.45" is wrong, but passes Octave.
+  str.erase (std::remove (str.begin (), str.end(), ','), str.end ());
   std::istringstream is (str);
 
   double num;
@@ -377,7 +376,6 @@
 %!assert (str2double ("1"), 1)
 %!assert (str2double ("-.1e-5"), -1e-6)
 %!assert (str2double (char ("1", "2 3", "4i")), [1; NaN; 4i])
-%!assert (str2double ("-.1e-5"), -1e-6)
 %!assert (str2double ("1,222.5"), 1222.5)
 %!assert (str2double ("i"), i)
 %!assert (str2double ("2j"), 2i)
--- a/libinterp/parse-tree/module.mk
+++ b/libinterp/parse-tree/module.mk
@@ -1,5 +1,6 @@
 EXTRA_DIST += \
   parse-tree/module.mk \
+  parse-tree/oct-parse.in.yy \
   parse-tree/octave.gperf
 
 PARSER_INC = \
--- a/scripts/general/bitcmp.m
+++ b/scripts/general/bitcmp.m
@@ -49,6 +49,9 @@
   if (isa (A, "double"))
     bmax = bitmax;
     amax = ceil (log2 (bmax));
+  elseif (isa (A, "single"))
+    bmax = bitmax ("single");
+    amax = ceil (log2 (bmax));
   else
     if (isa (A, "uint8"))
       amax = 8;
@@ -93,6 +96,13 @@
 %! assert (bitcmp (A,Amax-1), bitshift (1,Amax-2));
 %! assert (bitcmp (A,Amax-2), 0);
 %!test
+%! Amax = 24;
+%! Bmax = bitmax ("single");
+%! A = bitshift (Bmax,-2);
+%! assert (bitcmp (A,Amax),bitor (bitshift (single (1),Amax-1), bitshift (single (1),Amax-2)));
+%! assert (bitcmp (A,Amax-1), bitshift (single (1),Amax-2));
+%! assert (bitcmp (A,Amax-2), single (0));
+%!test
 %! Amax = 8;
 %! Bmax = intmax ("uint8");
 %! A = bitshift (Bmax,-2);
--- a/scripts/general/bitget.m
+++ b/scripts/general/bitget.m
@@ -39,8 +39,11 @@
   endif
 
   if (isa (A, "double"))
-    Amax = log2 (bitmax) + 1;
+    Amax = ceil (log2 (bitmax));
     _conv = @double;
+  elseif (isa (A, "single"))
+    Amax = ceil (log2 (bitmax ("single")));
+    _conv = @single;
   else
     if (isa (A, "uint8"))
       Amax = 8;
@@ -83,6 +86,7 @@
 
 %!test
 %! assert (bitget ([4, 14], [3, 3]), logical ([1, 1]));
+%! assert (bitget (single ([4, 14]), [3, 3]), logical ([1, 1]));
 %! pfx = {"", "u"};
 %! for i = 1:2
 %!   for prec = [8, 16, 32, 64]
@@ -94,6 +98,9 @@
 %!error bitget (0, 0)
 %!error bitget (0, 55)
 
+%!error bitget (single (0), 0)
+%!error bitget (single (0), 26)
+
 %!error bitget (int8 (0), 9)
 %!error bitget (uint8 (0), 9)
 
--- a/scripts/general/bitset.m
+++ b/scripts/general/bitset.m
@@ -54,10 +54,10 @@
 
   if (isfloat (A) && isreal (A))
     Bmax = bitmax (cl);
-    Amax = log2 (Bmax);
+    Amax = ceil (log2 (Bmax));
   elseif (isinteger (A))
     Bmax = intmax (cl);
-    Amax = round (log2 (Bmax));
+    Amax = ceil (log2 (Bmax));
   else
     error ("bitset: invalid class %s", cl);
   endif
@@ -91,6 +91,7 @@
 
 %!test
 %! assert (bitset ([0, 10], [3, 3]), [4, 14]);
+%! assert (bitset (single ([0, 10]), [3, 3]), single ([4, 14]));
 %! pfx = {"", "u"};
 %! for i = 1:2
 %!   for prec = [8, 16, 32, 64]
@@ -108,6 +109,8 @@
 %!error <invalid class char> bitset ("1", 2)
 %!error <N must be in the range \[1,53\]> bitset (0, 0)
 %!error <N must be in the range \[1,53\]> bitset (0, 55)
+%!error <N must be in the range \[1,24\]> bitset (single (0), 0)
+%!error <N must be in the range \[1,24\]> bitset (single (0), 26)
 %!error <N must be in the range \[1,8\]> bitset (uint8 (0), 0)
 %!error <N must be in the range \[1,8\]> bitset (uint8 (0), 9)
 %!error <N must be in the range \[1,7\]> bitset (int8 (0), 9)
--- a/scripts/general/fieldnames.m
+++ b/scripts/general/fieldnames.m
@@ -31,7 +31,7 @@
 ## properties of the object.
 ##
 ## When the input is a Java object @var{javaobj} or Java classname
-## @var{jclassname}) the name are the public data elements of the object or
+## @var{jclassname} the name are the public data elements of the object or
 ## class.
 ## @seealso{struct, methods}
 ## @end deftypefn
--- a/scripts/help/doc_cache_create.m
+++ b/scripts/help/doc_cache_create.m
@@ -42,7 +42,7 @@
   if (isempty (directory))
     cache = gen_builtin_cache ();
   elseif (iscell (directory))
-    if (all (cellfun (@ischar, directory)))
+    if (all (cellfun ("isclass", directory, "char")))
       cache = gen_doc_cache_in_dir (directory);
     else
       error ("doc_cache_create: cell must contain only strings");
@@ -95,7 +95,7 @@
 
   ## For each function:
   for n = 1:length (list)
-    f = list {n};
+    f = list{n};
 
     ## Get help text
     [text, format] = get_help_text (f);
@@ -108,9 +108,9 @@
     endif
 
     ## Store the help text
-    cache (1, end+1) = f;
-    cache (2, end) = text;
-    cache (3, end) = first_sentence;
+    cache(1, end+1) = f;
+    cache(2, end) = text;
+    cache(3, end) = first_sentence;
   endfor
 endfunction
 
@@ -127,19 +127,19 @@
 
   ## add them
   if (! isempty (dirs_notpath))
-    cellfun (@addpath, dirs_notpath);
+    addpath (dirs_notpath{:});
   endif
 
   ## create cache
   func = @(s_) create_cache (__list_functions__ (s_));
-  cache = cellfun (func, directory, 'UniformOutput', false);
+  cache = cellfun (func, directory, "UniformOutput", false);
 
   ## concatenate results
   cache = [cache{:}];
 
   ## remove dirs form path
   if (! isempty (dirs_notpath))
-    cellfun (@rmpath, dirs_notpath);
+    rmpath (dirs_notpath{:});
   endif
 
 endfunction
--- a/scripts/image/imformats.m
+++ b/scripts/image/imformats.m
@@ -260,7 +260,7 @@
   ## the minimal list of fields required in the structure. We don't
   ## require multipage because it doesn't exist in matlab
   min_fields  = {"ext", "read", "isa", "write", "info", "alpha", "description"};
-  fields_mask = cellfun (@(x) isfield (format, x), min_fields);
+  fields_mask = isfield (format, min_fields);
   if (! all (fields_mask))
     error ("imformats: structure has missing field `%s'.", min_fields(! fields_mask){1});
   endif
--- a/scripts/image/private/__imread__.m
+++ b/scripts/image/private/__imread__.m
@@ -79,9 +79,9 @@
   endif
 
   ## Check key/value options.
-  indexes = find (cellfun (@(x) ischar (x) ...
-                                && any (strcmpi (x, {"frames", "index"})),
-                           varargin));
+  indexes = cellfun ("isclass", varargin, "char");
+  indexes(indexes) &= ismember (varargin(indexes), {"frames", "index"});
+  indexes = find (indexes);
   if (indexes)
     options.index = varargin{indexes+1};
     if (! (is_valid_index_option (options.index)) &&
--- a/scripts/image/rgb2ind.m
+++ b/scripts/image/rgb2ind.m
@@ -37,16 +37,14 @@
 ##
 ## The input image @var{rgb} must be an N-dimensional RGB image
 ## (@nospell{MxNxO}@dots{}x3 array) where M,N,O@dots{} are the image
-## dimensions, and the
-## final dimension contains the values in the red, green and blue
-## channels.  Alternatively, the red, green and blue color channels can
-## be input as separate arrays @var{R}, @var{G} and  @var{B}.
+## dimensions, and the final dimension contains the values in the red, green
+## and blue channels.  Alternatively, the red, green and blue color channels
+## can be input as separate arrays @var{R}, @var{G}, and @var{B}.
 ##
-## The input @var{map} defines the colormap to be used.  Alternatively,
-## @var{n} or @var{tol} may be used to define the maximum number of
-## colors to use in an automatically generated colormap.  @var{n} is
-## related to @var{tol} by:  @var{n} = (floor (1/@var{tol}) + 1)^3;
-## @var{tol} must be >0 and @leq{}1.
+## The input @var{map} defines the colormap to be used.  Alternatively, @var{n}
+## or @var{tol} may be used to define the maximum number of colors to use in an
+## automatically generated colormap.  @var{n} is related to @var{tol} by:
+## @var{n} = (floor (1/@var{tol}) + 1)^3; where 0 < @var{tol} @leq{} 1.
 ##
 ## @var{dither_option} is a string which enables or disables dithering:
 ## @qcode{"dither"} (default) or @qcode{"nodither"}.
--- a/scripts/miscellaneous/copyfile.m
+++ b/scripts/miscellaneous/copyfile.m
@@ -19,27 +19,33 @@
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {[@var{status}, @var{msg}, @var{msgid}] =} copyfile (@var{f1}, @var{f2})
 ## @deftypefnx {Function File} {[@var{status}, @var{msg}, @var{msgid}] =} copyfile (@var{f1}, @var{f2}, 'f')
-## Copy the file @var{f1} to the new name @var{f2}.  The name @var{f1}
-## may contain globbing patterns.  If @var{f1} expands to multiple file
-## names, @var{f2} must be a directory.  If the force flag @qcode{'f'} is
-## given then existing destination files will be overwritten without
-## prompting.
+## Copy the file @var{f1} to the destination @var{f2}.
+##
+## The name @var{f1} may contain globbing patterns.  If @var{f1} expands to
+## multiple file names, @var{f2} must be a directory.
+## when the force flag @qcode{'f'} is given any existing files will be
+## overwritten without prompting.
 ##
-## If successful, @var{status} is 1, with @var{msg} and @var{msgid} empty
-## character strings.  Otherwise, @var{status} is 0, @var{msg} contains a
-## system-dependent error message, and @var{msgid} contains a unique
-## message identifier.
-## @seealso{movefile}
+## If successful, @var{status} is 1, and @var{msg}, @var{msgid} are empty
+## character strings ("").  Otherwise, @var{status} is 0, @var{msg} contains a
+## system-dependent error message, and @var{msgid} contains a unique message
+## identifier.  Note that the status code is exacly opposite that of the
+## @code{system} command.
+## @seealso{movefile, glob}
 ## @end deftypefn
 
 function [status, msg, msgid] = copyfile (f1, f2, force)
 
+  if (nargin < 2 || nargin > 3)
+    print_usage ();
+  endif
+
   max_cmd_line = 1024;
   status = true;
   msg = "";
   msgid = "";
 
-  ## FIXME -- maybe use the same method as in ls to allow users control
+  ## FIXME: maybe use the same method as in ls to allow users control
   ## over the command that is executed.
 
   if (ispc () && ! isunix ()
@@ -52,80 +58,76 @@
     cmd_force_flag = "-f";
   endif
 
-  if (nargin == 2 || nargin == 3)
-    ## Input type check.
-    if (! (ischar (f1) || iscellstr (f1)))
-      error ("copyfile: first argument must be a character string or a cell array of character strings");
-    endif
+  ## Input type check.
+  if (! (ischar (f1) || iscellstr (f1)))
+    error ("copyfile: F1 must be a character string or a cell array of character strings");
+  endif
 
-    if (! ischar (f2))
-      error ("copyfile: second argument must be a character string");
-    endif
+  if (! ischar (f2))
+    error ("copyfile: F2 must be a character string");
+  endif
 
-    if (nargin == 3 && strcmp (force, "f"))
-      cmd = [cmd " " cmd_force_flag];
-    endif
+  if (nargin == 3 && strcmp (force, "f"))
+    cmd = [cmd " " cmd_force_flag];
+  endif
 
-    ## If f1 isn't a cellstr convert it to one.
-    if (ischar (f1))
-      f1 = cellstr (f1);
-    endif
-
-    ## If f1 has more than 1 element f2 must be a directory
-    isdir = (exist (f2, "dir") != 0);
-    if (length (f1) > 1 && ! isdir)
-      error ("copyfile: when copying multiple files, second argument must be a directory");
-    endif
+  ## If f1 isn't a cellstr convert it to one.
+  if (ischar (f1))
+    f1 = cellstr (f1);
+  endif
 
-    ## Protect the file name(s).
-    f1 = glob (f1);
-    if (isempty (f1))
-      error ("copyfile: no files to move");
-    endif
-    p1 = sprintf ("\"%s\" ", f1{:});
-    p2 = tilde_expand (f2);
+  ## If f1 has more than 1 element f2 must be a directory
+  isdir = (exist (f2, "dir") != 0);
+  if (length (f1) > 1 && ! isdir)
+    error ("copyfile: when copying multiple files, F2 must be a directory");
+  endif
 
-    if (isdir && length (p1) > max_cmd_line)
-      l2 = length (p2) + length (cmd) + 6;
-      while (! isempty (f1))
-        p1 = sprintf ("\"%s\" ", f1{1});
+  ## Protect the file name(s).
+  f1 = glob (f1);
+  if (isempty (f1))
+    error ("copyfile: no files to move");
+  endif
+  p1 = sprintf ('"%s" ', f1{:});
+  p2 = tilde_expand (f2);
+
+  if (isdir && length (p1) > max_cmd_line)
+    l2 = length (p2) + length (cmd) + 6;
+    while (! isempty (f1))
+      p1 = sprintf ('"%s" ', f1{1});
+      f1(1) = [];
+      while (! isempty (f1)
+             && (length (p1) + length (f1{1}) + l2 < max_cmd_line))
+        p1 = sprintf ('%s"%s" ', p1, f1{1});
         f1(1) = [];
-        while (!isempty (f1) && (length (p1) + length (f1{1}) + l2 <
-                                 max_cmd_line))
-          p1 = sprintf ("%s\"%s\" ", p1, f1{1});
-          f1(1) = [];
-        endwhile
+      endwhile
 
-        if (ispc () && ! isunix ()
-            && ! isempty (file_in_path (getenv ("PATH"), "cp.exe")))
-          p1 = strrep (p1, "\\", "/");
-          p2 = strrep (p2, "\\", "/");
-        endif
-
-        ## Copy the files.
-        [err, msg] = system (sprintf ("%s %s\"%s\"", cmd, p1, p2));
-        if (err < 0)
-          status = false;
-          msgid = "copyfile";
-          break;
-        endif
-      endwhile
-    else
       if (ispc () && ! isunix ()
           && ! isempty (file_in_path (getenv ("PATH"), "cp.exe")))
-        p1 = strrep (p1, "\\", "/");
-        p2 = strrep (p2, "\\", "/");
+        p1 = strrep (p1, '\', '/');
+        p2 = strrep (p2, '\', '/');
       endif
 
       ## Copy the files.
-      [err, msg] = system (sprintf ("%s %s\"%s\"", cmd, p1, p2));
-      if (err < 0)
+      [err, msg] = system (sprintf ('%s %s"%s"', cmd, p1, p2));
+      if (err != 0)
         status = false;
         msgid = "copyfile";
+        break;
       endif
+    endwhile
+  else
+    if (ispc () && ! isunix ()
+        && ! isempty (file_in_path (getenv ("PATH"), "cp.exe")))
+      p1 = strrep (p1, '\', '/');
+      p2 = strrep (p2, '\', '/');
     endif
-  else
-    print_usage ();
+
+    ## Copy the files.
+    [err, msg] = system (sprintf ('%s %s"%s"', cmd, p1, p2));
+    if (err != 0)
+      status = false;
+      msgid = "copyfile";
+    endif
   endif
 
 endfunction
--- a/scripts/miscellaneous/edit.m
+++ b/scripts/miscellaneous/edit.m
@@ -375,7 +375,7 @@
         host = getenv ("COMPUTERNAME");
       endif
       if (isempty (host))
-        [status, host] = system ("uname -n");
+        [~, host] = system ("uname -n");
         ## trim newline from end of hostname
         if (! isempty (host))
           host = host(1:end-1);
--- a/scripts/miscellaneous/movefile.m
+++ b/scripts/miscellaneous/movefile.m
@@ -17,28 +17,39 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {[@var{status}, @var{msg}, @var{msgid}] =} movefile (@var{f1}, @var{f2})
-## @deftypefnx {Function File} {[@var{status}, @var{msg}, @var{msgid}] =} movefile (@var{f1}, @var{f2}, 'f')
-## Move the file @var{f1} to the new name @var{f2}.  The name @var{f1}
-## may contain globbing patterns.  If @var{f1} expands to multiple file
-## names, @var{f2} must be a directory.  If the force flag @qcode{'f'} is given
-## then any existing files will be overwritten without prompting.
+## @deftypefn  {Function File} {} movefile (@var{f1})
+## @deftypefnx {Function File} {} movefile (@var{f1}, @var{f2})
+## @deftypefnx {Function File} {} movefile (@var{f1}, @var{f2}, 'f')
+## @deftypefnx {Function File} {[@var{status}, @var{msg}, @var{msgid}] =} movefile (@dots{})
+## Move the file @var{f1} to the destination @var{f2}.
 ##
-## If successful, @var{status} is 1, with @var{msg} and @var{msgid} empty
-## character strings.  Otherwise, @var{status} is 0, @var{msg} contains a
-## system-dependent error message, and @var{msgid} contains a unique
-## message identifier.
-## @seealso{rename, copyfile}
+## The name @var{f1} may contain globbing patterns.  If @var{f1} expands to
+## multiple file names, @var{f2} must be a directory.  If no destination
+## @var{f2} is specified then the destination is the present working directory.
+## If @var{f2} is a file name then @var{f1} is renamed to @var{f2}.
+## When the force flag @qcode{'f'} is given any existing files will be
+## overwritten without prompting.
+##
+## If successful, @var{status} is 1, and @var{msg}, @var{msgid} are empty
+## character strings ("").  Otherwise, @var{status} is 0, @var{msg} contains a
+## system-dependent error message, and @var{msgid} contains a unique message
+## identifier.  Note that the status code is exacly opposite that of the
+## @code{system} command.
+## @seealso{rename, copyfile, glob}
 ## @end deftypefn
 
 function [status, msg, msgid] = movefile (f1, f2, force)
 
+  if (nargin < 1 || nargin > 3)
+    print_usage ();
+  endif
+
   max_cmd_line = 1024;
   status = true;
   msg = "";
   msgid = "";
 
-  ## FIXME -- maybe use the same method as in ls to allow users control
+  ## FIXME: maybe use the same method as in ls to allow users control
   ## over the command that is executed.
 
   if (ispc () && ! isunix ()
@@ -51,79 +62,78 @@
     cmd_force_flag = "-f";
   endif
 
-  if (nargin == 2 || nargin == 3)
-    ## Input type check.
-    if (! (ischar (f1) || iscellstr (f1)))
-      error ("movefile: first argument must be a character string or a cell array of character strings");
-    endif
-
-    if (! ischar (f2))
-      error ("movefile: second argument must be a character string");
-    endif
+  ## Input type check.
+  if (! (ischar (f1) || iscellstr (f1)))
+    error ("movefile: F1 must be a character string or a cell array of character strings");
+  endif
 
-    if (nargin == 3 && strcmp (force, "f"))
-      cmd = [cmd " " cmd_force_flag];
-    endif
+  if (nargin == 1)
+    f2 = pwd ();
+  elseif (! ischar (f2))
+    error ("movefile: F2 must be a character string");
+  endif
 
-    ## If f1 isn't a cellstr convert it to one.
-    if (ischar (f1))
-      f1 = cellstr (f1);
-    endif
+  if (nargin == 3 && strcmp (force, "f"))
+    cmd = [cmd " " cmd_force_flag];
+  endif
 
-    ## If f1 has more than 1 element f2 must be a directory
-    isdir = (exist (f2, "dir") != 0);
-    if (length (f1) > 1 && ! isdir)
-      error ("movefile: when moving multiple files, second argument must be a directory");
-    endif
+  ## If f1 isn't a cellstr convert it to one.
+  if (ischar (f1))
+    f1 = cellstr (f1);
+  endif
 
-    ## Protect the file name(s).
-    f1 = glob (f1);
-    if (isempty (f1))
-      error ("movefile: no files to move");
-    endif
-    p1 = sprintf ("\"%s\" ", f1{:});
-    p2 = tilde_expand (f2);
+  ## If f1 has more than 1 element f2 must be a directory
+  isdir = (exist (f2, "dir") != 0);
+  if (length (f1) > 1 && ! isdir)
+    error ("movefile: when moving multiple files, F2 must be a directory");
+  endif
 
-    if (isdir && length (p1) > max_cmd_line)
-      l2 = length (p2) + length (cmd) + 6;
-      while (! isempty (f1))
-        p1 = sprintf ("\"%s\" ", f1{1});
+  ## Protect the file name(s).
+  f1 = glob (f1);
+  if (isempty (f1))
+    error ("movefile: no files to move");
+  endif
+  p1 = sprintf ('"%s" ', f1{:});
+  p2 = tilde_expand (f2);
+
+  if (isdir && length (p1) > max_cmd_line)
+    l2 = length (p2) + length (cmd) + 6;
+    while (! isempty (f1))
+      p1 = sprintf ('"%s" ', f1{1});
+      f1(1) = [];
+      while (! isempty (f1)
+             && (length (p1) + length (f1{1}) + l2 < max_cmd_line))
+        p1 = sprintf ('%s"%s" ', p1, f1{1});
         f1(1) = [];
-        while (!isempty (f1) && (length (p1) + length (f1{1}) + l2 <
-                                 max_cmd_line))
-          p1 = sprintf ("%s\"%s\" ", p1, f1{1});
-          f1(1) = [];
-        endwhile
+      endwhile
 
-        if (ispc () && ! isunix ()
-            && ! isempty (file_in_path (getenv ("PATH"), "cp.exe")))
-          p1 = strrep (p1, "\\", "/");
-          p2 = strrep (p2, "\\", "/");
-        endif
-
-        ## Move the file(s).
-        [err, msg] = system (sprintf ("%s %s \"%s\"", cmd, p1, p2));
-        if (err < 0)
-          status = false;
-          msgid = "movefile";
-        endif
-      endwhile
-    else
       if (ispc () && ! isunix ()
           && ! isempty (file_in_path (getenv ("PATH"), "cp.exe")))
-        p1 = strrep (p1, "\\", "/");
-        p2 = strrep (p2, "\\", "/");
+        p1 = strrep (p1, '\', '/');
+        p2 = strrep (p2, '\', '/');
       endif
 
       ## Move the file(s).
-      [err, msg] = system (sprintf ("%s %s \"%s\"", cmd, p1, p2));
-      if (err < 0)
+      [err, msg] = system (sprintf ('%s %s "%s"', cmd, p1, p2));
+      if (err != 0)
         status = false;
         msgid = "movefile";
       endif
-    endif
+    endwhile
   else
-    print_usage ();
+    if (ispc () && ! isunix ()
+        && ! isempty (file_in_path (getenv ("PATH"), "cp.exe")))
+      p1 = strrep (p1, '\', '/');
+      p2 = strrep (p2, '\', '/');
+    endif
+
+    ## Move the file(s).
+    [err, msg] = system (sprintf ('%s %s "%s"', cmd, p1, p2));
+    if (err != 0)
+      status = false;
+      msgid = "movefile";
+    endif
   endif
+
 endfunction
 
--- a/scripts/miscellaneous/what.m
+++ b/scripts/miscellaneous/what.m
@@ -63,13 +63,13 @@
       [dummy, f, e] = fileparts (n);
       if (strcmp (e, ".m"))
         w.m{end+1} = n;
-      elseif (strcmp (e, mexext ()))
-        w.mex{end+1} = n;
       elseif (strcmp (e, ".oct"))
         w.oct{end+1} = n;
+      elseif (strcmp (e, mexext ()))
+        w.mex{end+1} = n;
       elseif (strcmp (e, ".mat"))
         w.mat{end+1} = n;
-      elseif(strcmp (n(1), "@"))
+      elseif (strcmp (n(1), "@"))
         w.classes{end+1} = n;
       endif
     endif
--- a/scripts/pkg/private/rebuild.m
+++ b/scripts/pkg/private/rebuild.m
@@ -35,7 +35,7 @@
     wd = pwd ();
     unwind_protect
       cd (prefix);
-      dirlist = glob (cellfun(@(x) [x '-*'], files, 'uniformoutput', 0));
+      dirlist = glob (strcat (files, '-*'));
     unwind_protect_cleanup
       cd (wd);
     end_unwind_protect
--- a/scripts/plot/axis.m
+++ b/scripts/plot/axis.m
@@ -339,8 +339,8 @@
     data = cellfun (@(x) x(isfinite (x)), data, "uniformoutput", false);
     data = data(! cellfun ("isempty", data));
     if (! isempty (data))
-      lims_min = min (cellfun (@(x) min (x(:)), data(:)));
-      lims_max = max (cellfun (@(x) max (x(:)), data(:)));
+      lims_min = min ([data{:}](:));
+      lims_max = max ([data{:}](:));
       lims = [lims_min, lims_max];
     else
       lims = [0, 1];
--- a/scripts/plot/pareto.m
+++ b/scripts/plot/pareto.m
@@ -70,19 +70,18 @@
     print_usage ();
   endif
 
-  x = varargin {1}(:).';
+  x = varargin{1}(:).';
   if (nargin == 2)
-    y = varargin {2}(:).';
+    y = varargin{2}(:).';
     if (! iscell (y))
       if (ischar (y))
         y = cellstr (y);
       else
-        y = cellfun ("num2str", num2cell (y), "uniformoutput", false);
+        y = cellstr (num2str (y(:)));
       endif
     endif
   else
-    y = cellfun ("int2str", num2cell (1 : numel (x)),
-                 "uniformoutput", false);
+    y = cellstr (int2str ([1:numel(x)]'));
   endif
 
   [x, idx] = sort (x, "descend");
--- a/scripts/plot/plot.m
+++ b/scripts/plot/plot.m
@@ -69,6 +69,10 @@
 ##
 ## @item
 ## If @var{x} and @var{y} are scalars, a single point is plotted.
+##
+## @item
+## @code{squeeze()} is applied to arguments with more than two dimensions,
+## but no more than two singleton dimensions.
 ## 
 ## @item
 ## If both arguments are vectors, the elements of @var{y} are plotted versus
@@ -245,3 +249,37 @@
 %! title ({'plot() of blue circles ascending and red squares descending';
 %!         'connecting lines drawn'}); 
 
+%!demo
+%! x = 0:10;
+%! plot (x, rand (numel (x), 3))
+%! axis ([0 10 0 1])
+%! title ({'Three random variables', 'x[1x11], y[11x3]'})
+
+%!demo
+%! x = 0:10;
+%! plot (x, rand (3, numel (x)))
+%! axis ([0 10 0 1])
+%! title ({'Three random variables', 'x[1x11], y[3x11]'})
+
+%!demo
+%! x = 0:10;
+%! plot (repmat (x, 2, 1), rand (2, numel (x)), '-s')
+%! axis ([0 10 0 1])
+%! title ({'Vertical lines with random height and lenths', ...
+%!         'x[2x11], y[2,11]'})
+
+%!demo
+%! x = 0:10;
+%! plot (repmat (x(:), 1, 2), rand (numel (x), 2))
+%! axis ([0 10 0 1])
+%! title ({'Two random variables', 'x[11x2], y[11x2]'})
+
+%!demo
+%! x = 0:10;
+%! shape = [1, 1, numel(x), 2];
+%! x = reshape (repmat (x(:), 1, 2), shape);
+%! y = rand (shape);
+%! plot (x, y)
+%! axis ([0 10 0 1])
+%! title ({'Two random variables', 'squeezed from 4-d arrays'})
+
--- a/scripts/plot/private/__gnuplot_print__.m
+++ b/scripts/plot/private/__gnuplot_print__.m
@@ -171,7 +171,7 @@
 function eps_drawnow (opts, epsfile, gp_opts)
   [h, fontsize] = get_figure_text_objs (opts);
   unwind_protect
-    fontsize_2x = cellfun (@(x) 2*x, fontsize, "uniformoutput", false);
+    fontsize_2x = cellfun (@times, {2}, fontsize, "uniformoutput", false);
     set (h, {"fontsize"}, fontsize_2x);
     local_drawnow (["postscript eps " gp_opts], epsfile, opts);
   unwind_protect_cleanup
--- a/scripts/plot/private/__line__.m
+++ b/scripts/plot/private/__line__.m
@@ -113,7 +113,6 @@
         || (nvecpts != 0 && any (nvecpts != cellfun ("size", tmp, 1))))
       error ("line: data size_mismatch");
     endif
-
     data_args(mask) = cellfun (@(x) x(:,i), data(ismat),
                                "uniformoutput", false);
 
--- a/scripts/plot/private/__patch__.m
+++ b/scripts/plot/private/__patch__.m
@@ -210,13 +210,14 @@
 endfunction
 
 function args = delfields (args, flds)
-  idx = cellfun (@(x) any (strcmpi (x, flds)), args);
+  idx = cellfun ("isclass", args, "char");
+  idx(idx) = ismember (args(idx), flds);
   if (rows (idx) == 1)
-    idx = idx | [false, idx(1:end-1)];
+    idx |= [false, idx(1:end-1)];
   else
-    idx = idx | [false; idx(1:end-1)];
+    idx |= [false; idx(1:end-1)];
   endif
-  args (idx) = [];
+  args(idx) = [];
 endfunction
 
 function args = setdata (args)
--- a/scripts/plot/private/__plt__.m
+++ b/scripts/plot/private/__plt__.m
@@ -25,6 +25,7 @@
 
 function retval = __plt__ (caller, h, varargin)
 
+  persistent warned_callers = {};
   nargs = nargin - 2;
 
   if (nargs > 0)
@@ -72,6 +73,19 @@
         next_arg = varargin{k++};
       endif
 
+      if (isnumeric (next_arg) && ndims (next_arg) > 2
+          && any (size (next_arg) == 1))
+        next_arg = squeeze (next_arg);
+        if (! any (strcmp (caller, warned_callers)) && ndims (next_arg) < 3)
+          warning (["%s: N-d inputs have been squeezed to less than " ...
+                    "three dimensions"], caller)
+          warned_callers(end+1) = caller;
+        endif
+      endif
+      if (isnumeric (next_arg) && ndims (next_arg) > 2)
+        error ("%s: plot arrays must have less than 2 dimensions", caller)
+      endif
+
       nargs--;
 
       if (ischar (next_arg) || iscellstr (next_arg))
--- a/scripts/plot/private/__print_parse_opts__.m
+++ b/scripts/plot/private/__print_parse_opts__.m
@@ -327,6 +327,22 @@
     arg_st.ghostscript.epscrop = ! arg_st.loose;
   endif
 
+  if (arg_st.send_to_printer)
+    if (isempty (arg_st.name))
+      ## Pipe the ghostscript output 
+      arg_st.name = "-";
+    else
+      error ("print: a file name may not specified when spooling to a printer")
+    endif
+    if (! any (strcmp (arg_st.devopt, gs_device_list))
+      || ! any (strcmp (arg_st.devopt, {"pswrite", "ps2write"})))
+      ## Only postscript and supported ghostscript devices
+      error ("print: invalid format for spooling to a printer")
+    endif
+  elseif (isempty (arg_st.name))
+    error ("print: an output file name must be specified")
+  endif
+
   if (isempty (arg_st.canvas_size))
     if (isfigure (arg_st.figure))
       [arg_st.ghostscript.papersize, paperposition] = ...
--- a/scripts/plot/scatter.m
+++ b/scripts/plot/scatter.m
@@ -28,7 +28,7 @@
 ## Draw a 2-D scatter plot.
 ##
 ## A marker is plotted at each point defined by the coordinates in the vectors
-## @var{x} and  @var{y}.
+## @var{x} and @var{y}.
 ##
 ## The size of the markers is determined by @var{s}, which can be a scalar
 ## or a vector of the same length as @var{x} and @var{y}.  If @var{s}
--- a/scripts/plot/specular.m
+++ b/scripts/plot/specular.m
@@ -23,7 +23,7 @@
 ## vector elements @var{sx}, @var{sy}, @var{sz} using Phong's approximation.
 ##
 ## The light source location and viewer location vectors can be specified using
-## parameter @var{lv} and  @var{vv} respectively.  The location vectors can
+## parameter @var{lv} and @var{vv} respectively.  The location vectors can
 ## given as 2-element vectors [azimuth, elevation] in degrees or as 3-element
 ## vectors [x, y, z].
 ##
--- a/scripts/plot/struct2hdl.m
+++ b/scripts/plot/struct2hdl.m
@@ -93,7 +93,7 @@
     p = p(1:2, 1:(tst(end)-1));
   endif
 
-  ## Place the "*mode" properties as the end to avoid having the updaters
+  ## Place the "*mode" properties at the end to avoid having the updaters
   ## change the mode to "manual" when the value is "auto".
   names = fieldnames (s.properties);
   n = strncmp (cellfun (@fliplr, names, "uniformoutput", false), "edom", 4);
@@ -191,7 +191,7 @@
       plty = s.properties.__plotyy_axes__;
       addproperty ("__plotyy_axes__", h, "any");
       tmp = [p [s.handle; h]];
-      tst = arrayfun (@(x) any (plty == x), tmp(1:2:end));
+      tst = ismember (tmp(1:2:end), plty);
       if (sum (tst) == numel (plty))
         for ii = 1:numel (plty)
           plty(ii) = tmp(find (tmp == plty(ii)) + 1);
@@ -453,7 +453,8 @@
     bargroup = s.properties.bargroup;
     oldh = s.handle;
 
-    temp = arrayfun (@(x) any(x == bargroup), [p(1:2:end) oldh]);
+    temp = ismember ([p(1:2:end) oldh], bargroup);
+
     tst = sum (temp) == length (bargroup);
 
     if (isscalar (bargroup) || !tst)
@@ -547,7 +548,11 @@
   more off;
   if (strcmpi (s.properties.tag, ""))
     specs = s.children(s.special);
-    hdls = arrayfun (@(x) x.handle, specs);
+    if (isempty (specs))
+      hdls = [];
+    else
+      hdls = [specs.handle];
+    endif
     nh = length (hdls);
     msg = "";
     if (! nh)
@@ -625,7 +630,7 @@
   hid = {"autopos_tag", "looseinset"};
   oldfields = fieldnames (props);
   curfields = fieldnames (get (h));
-  missing = cellfun (@(x) !any (strcmp (x, curfields)), oldfields);
+  missing = ! ismember (oldfields, curfields);
   idx = find (missing);
   for ii = 1:length (idx)
     prop = oldfields{idx(ii)};
--- a/scripts/polynomial/splinefit.m
+++ b/scripts/polynomial/splinefit.m
@@ -94,7 +94,7 @@
 
 function pp = splinefit (x, y, breaks, varargin)
   if (nargin > 3)
-    n = cellfun (@ischar, varargin, "uniformoutput", true);
+    n = cellfun ("isclass", varargin, "char");
     varargin(n) = lower (varargin(n));
     try
       props = struct (varargin{:});
--- a/scripts/special-matrix/gallery.m
+++ b/scripts/special-matrix/gallery.m
@@ -2464,7 +2464,7 @@
     error ("gallery: 1 to 6 arguments are required for toeppen matrix.");
   elseif (! isnumeric (n) || ! isscalar (n) || fix (n) != n)
     error ("gallery: N must be a numeric integer for toeppen matrix.");
-  elseif (any (cellfun (@(x) ! isnumeric (x) || ! isscalar (x), {a b c d e})))
+  elseif (any (! cellfun ("isnumeric", {a b c d e})) || any (cellfun ("numel", {a b c d e}) != 1))
     error ("gallery: A, B, C, D and E must be numeric scalars for toeppen matrix.");
   endif
 
--- a/scripts/strings/strcat.m
+++ b/scripts/strings/strcat.m
@@ -20,19 +20,20 @@
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} strcat (@var{s1}, @var{s2}, @dots{})
 ## Return a string containing all the arguments concatenated
-## horizontally.  If the arguments are cells strings,  @code{strcat}
+## horizontally.  If the arguments are cell strings, @code{strcat}
 ## returns a cell string with the individual cells concatenated.
 ## For numerical input, each element is converted to the
-## corresponding ASCII character.  Trailing white space for each of
-## the inputs (@var{s1}, @var{s2}, @dots{}) is eliminated before they
-## are concatenated.
+## corresponding ASCII character.  Trailing white space for any
+## character string input is eliminated before the strings are
+## concatenated.  Note that cell string values do @strong{not} have
+## whitespace trimmed.
 ##
 ## For example:
 ##
 ## @example
 ## @group
 ## strcat ("|", " leading space is preserved", "|")
-##     @result{} | leading space is perserved|
+##     @result{} | leading space is preserved|
 ## @end group
 ## @end example
 ##
@@ -62,12 +63,12 @@
 ##
 ## @example
 ## @group
-## s = @{ "ab"; "cde" @};
+## s = @{ "ab"; "cd " @};
 ## strcat (s, s, s)
 ##     @result{}
 ##         @{
 ##           [1,1] = ababab
-##           [2,1] = cdecdecde
+##           [2,1] = cd cd cd 
 ##         @}
 ## @end group
 ## @end example
@@ -79,41 +80,41 @@
 
 function st = strcat (varargin)
 
-  if (nargin > 0)
-    if (nargin == 1)
-      st = varargin{1};
-    elseif (nargin > 1)
-      ## Convert to cells of strings
-      uo = "uniformoutput";
-      reals = cellfun ("isreal", varargin);
-      if (any (reals))
-        varargin(reals) = cellfun ("char", varargin(reals), uo, false);
-      endif
-      chars = cellfun ("isclass", varargin, "char");
-      allchar = all (chars);
-      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
+  if (nargin == 0)
+    print_usage ();
+  endif
 
-      ## We don't actually need to bring all cells to common size, because
-      ## cellfun can now expand scalar cells.
-      err = common_size (varargin{:});
-
-      if (err)
-        error ("strcat: arguments must be the same size, or be scalars");
-      endif
+  if (nargin == 1)
+    st = varargin{1};
+  else
+    ## Convert to cells of strings
+    uo = "uniformoutput";
+    reals = cellfun ("isreal", varargin);
+    if (any (reals))
+      varargin(reals) = cellfun ("char", varargin(reals), uo, false);
+    endif
+    chars = cellfun ("isclass", varargin, "char");
+    allchar = all (chars);
+    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
 
-      ## Cellfun handles everything for us.
-      st = cellfun ("horzcat", varargin{:}, uo, false);
+    ## We don't actually need to bring all cells to common size, because
+    ## cellfun can now expand scalar cells.
+    err = common_size (varargin{:});
+
+    if (err)
+      error ("strcat: arguments must be the same size, or be scalars");
+    endif
 
-      if (allchar)
-        ## If all inputs were strings, return strings.
-        st = char (st);
-      endif
+    ## Cellfun handles everything for us.
+    st = cellfun ("horzcat", varargin{:}, uo, false);
+
+    if (allchar)
+      ## If all inputs were strings, return strings.
+      st = char (st);
     endif
-  else
-    print_usage ();
   endif
 
 endfunction
--- a/scripts/strings/strsplit.m
+++ b/scripts/strings/strsplit.m
@@ -187,7 +187,7 @@
     else
       del = do_string_escapes (del);
     endif
-    % This is clumsy, but needed for multi-row strings
+    ## This is clumsy, but needed for multi-row strings
     del = regexprep (del, '([^\w])', '\\$1');
   endif
 
--- a/scripts/strings/untabify.m
+++ b/scripts/strings/untabify.m
@@ -61,7 +61,7 @@
   if (ischar (t))
     s = replace_tabs (t, tw);
   else
-    s = cellfun (@(str) replace_tabs (str, tw), t, "uniformoutput", false);
+    s = cellfun (@replace_tabs, t, {tw}, "uniformoutput", false);
   endif
 
   if (dblank)
--- a/scripts/testfun/__run_test_suite__.m
+++ b/scripts/testfun/__run_test_suite__.m
@@ -257,7 +257,7 @@
 endfunction
 
 function n = num_elts_matching_pattern (lst, pat)
-  n = sum (cellfun (@(x) !isempty (x), regexp (lst, pat, 'once')));
+  n = sum (! cellfun ("isempty", regexp (lst, pat, 'once')));
 endfunction
 
 function report_files_with_no_tests (with, without, typ)
--- a/scripts/ui/inputdlg.m
+++ b/scripts/ui/inputdlg.m
@@ -66,7 +66,7 @@
 
   if (iscell (prompt))
     ## Silently extract only char elements
-    prompt = prompt(cellfun ("ischar", prompt));
+    prompt = prompt(cellfun ("isclass", prompt, "char"));
   elseif (ischar (prompt))
     prompt = {prompt};
   else
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -98,6 +98,7 @@
   $(GENERATED_BC_OVERLOADS_FILES)
 
 DISTCLEANFILES = \
+  .gdbinit \
   fntests.log
 
 fixedtestsdir := $(octtestsdir)/fixed