changeset 28541:5f4e8dddf05f

maint: merge stable to default.
author John W. Eaton <jwe@octave.org>
date Tue, 07 Jul 2020 19:40:20 -0400
parents 3e60f505f038 (diff) ea5a632b2553 (current diff)
children 1c0a4e1b973e
files libinterp/parse-tree/pt-eval.cc libinterp/parse-tree/pt-eval.h
diffstat 290 files changed, 14731 insertions(+), 5555 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Tue Jul 07 18:34:23 2020 -0400
+++ b/NEWS	Tue Jul 07 19:40:20 2020 -0400
@@ -1,257 +1,128 @@
-Summary of important user-visible changes for version 6 (yyyy-mm-dd):
+Summary of important user-visible changes for version 7 (yyyy-mm-dd):
 ----------------------------------------------------------------------
 
 ### General improvements
 
-- The `intersect`, `setdiff`, `setxor`, `union`, and `unique` functions
-  accept a new sorting option `"stable"` which will return output values
-  in the same order as the input, rather than in ascending order.
-
-- Complex RESTful web services can now be accessed by the `webread` and
-  `webwrite` functions alongside with the `weboptions` structure.  One
-  major feature is the support for cookies to enable RESTful
-  communication with the web service.
-
-  Additionally, the system web browser can be opened by the `web` function.
-
-- The `linspace` function now produces symmetrical sequences when the
-  endpoints are symmetric.  This is more intuitive and also compatible
-  with recent changes made in Matlab R2019b.
+- Many functions in Octave can be called in a command form---no
+parentheses for invocation and no return argument assignment---or in a
+functional form---parentheses and '=' for assignment of return values.
 
-- The underlying algorithm of the `rand` function has been changed.
-  For single precision outputs, the algorithm has been fixed so that it
-  produces values strictly in the range (0, 1).  Previously, it could
-  occasionally generate the right endpoint value of 1 (See bug #41742).
-  In addition, the new implementation uses a uniform interval between
-  floating point values in the range (0, 1) rather than targeting a
-  uniform density (# of random integers / length along real number
-  line).
+    Command Form Example
 
-- Numerical integration has been improved.  The `quadv` function has
-  been re-written so that it can compute integrands of periodic
-  functions.  At the same time, performance is better with ~3.5X fewer
-  function evaluations required.  A bug in `quadgk` that caused complex
-  path integrals specified with `"Waypoints"` to occasionally be
-  calculated in the opposite direction was fixed.
+    `mkdir new_directory`
 
-- The `edit` function option `"editinplace"` now defaults to `true` and
-  the option `"home"` now defaults to the empty matrix `[]`.  Files will
-  no longer be copied to the user's HOME directory for editing.  The old
-  behavior can be restored by setting `"editinplace"` to `false` and
-  `"home"` to `"~/octave"`.
+    Function Form Example
 
-- The `format` command supports two new options: `uppercase` and
-  `lowercase` (default).  With the default, print a lowercase 'e' for
-  the exponent character in scientific notation and lowercase 'a-f' for
-  the hex digits representing 10-15.  With `uppercase`, print 'E' and
-  'A-F' instead.  The previous uppercase formats, `E` and `G`, no longer
-  control the case of the output.
-
-  Additionally, the `format` command can be called with multiple options
-  for controlling the format, spacing, and case in arbitrary order.
-  For example:
-
-        format long e uppercase loose
+    `status = mkdir ("new_directory")`
 
-  Note, in the case of multiple competing format options the rightmost
-  one is used, and, in case of an error, the previous format remains
-  unchanged.
-
-- L-value references (e.g., increment (++), decrement (--), and all
-  in-place assignment operators (+=, -=, *=, /=, etc.)) are no longer
-  allowed in anonymous functions.
-
-- New warnings have been added about questionable uses of the colon ':'
-  range operator.  Each has a new warning ID so that it can be disabled
-  if desired.
-
-  >  `Octave:colon-complex-argument`   : when any arg is complex  
-  >  `Octave:colon-nonscalar-argument` : when any arg is non-scalar
-
-- The `regexp` and related functions now correctly handle and *require*
-  strings in UTF-8 encoding.  As with any other function that requires
-  strings to be encoded in Octave's native encoding, you can use
-  `native2unicode` to convert from your preferred locale.  For example,
-  the copyright symbol in UTF-8 is `native2unicode (169, "latin1")`.
+    Octave now handles errors that occur in a consistent manner.  If
+    called in command form and there is a failure, an error is thrown
+    and a message printed.  If called in functional form, no error or
+    message is printed and the failure is communicated to the programmer
+    via the output status variable.
 
-- The startup file `octaverc` now can be located in the platform
-  dependent location for user local configuration files (e.g.
-  ${XDG_CONFIG_HOME}/octave/octaverc on Unix-like operating systems or
-  %APPDATA%\octave\octaverc on Windows).
-
-- `pkg describe` now lists dependencies and inverse dependencies
-  (i.e., other installed packages that depend on the package in
-  question).
-
-- When unloading a package, `pkg` now checks if any remaining loaded
-  packages depend on the one to be removed.  If this is the case `pkg`
-  aborts with an explanatory error message.  This behavior can be
-  overridden with the `-nodeps` option.
-
-- The command
-
-    dbstop in CLASS at METHOD
-
-  now works to set breakpoints in classdef constructors and methods.
-
-#### Graphics backend
-
-- The use of Qt4 for graphics and the GUI is deprecated in Octave
-  version 6 and no further bug fixes will be made.  Qt4 support will be
-  removed completely in Octave version 7.
-
-- The `legend` function has been entirely rewritten.  This fixes a
-  number of historical bugs, but also implements new properties such as
-  `"AutoUpdate"` and `"NumColumns"`.  The gnuplot toolkit---which is no
-  longer actively maintained---still uses the old legend function.
-
-- The `axis` function was updated which resolved 10 bugs affecting
-  axes to which `"equal"` had been applied.
+    The following list of functions have been modified.
 
-- Graphic primitives now accept a color property value of `"none"`
-  which is useful when a particular primitive needs to be hidden
-  (for example, the Y-axis of an axes object with `"ycolor" = "none"`)
-  without hiding the entire primitive `"visibility" = "off"`.
-
-- A new property `"FontSmoothing"` has been added to text and axes
-  objects that controls whether anti-aliasing is used during the
-  rendering of characters.  The default is `"on"` which produces smooth,
-  more visually appealing text.
-
-- The figure property `"windowscrollwheelfcn"`is now implemented.
-  This makes it possible to provide a callback function to be executed
-  when users manipulate the mouse wheel on a given figure.
-
-- The figure properties `"pointer"`, `"pointershapecdata"`, and
-  `"pointershapehotspot"` are now implemented.  This makes it possible
-  to change the shape of the cursor (pointer in Matlab-speak) displayed
-  in a plot window.
+    * `copyfile`
+    * `fcntl`
+    * `fileattrib`
+    * `kill`
+    * `link`
+    * `mkfifo`
+    * `movefile`
+    * `rename`
+    * `rmdir`
+    * `symlink`
+    * `unlink`
 
-- The figure property `"paperpositionmode"` now has the default `"auto"`
-  rather than `"manual"`.  This change is more intuitive and is
-  Matlab compatible.
-
-- The appearance of patterned lines `"LineStyle" = ":"|"--"|"-."` has
-  been improved for small widths (`"LineWidth"` less than 1.5 pixels)
-  which is a common scenario.
+### Graphics backend
 
-- Printing to EPS files now uses a tight bounding box (`"-tight"`
-  argument to print) by default.  This makes more sense for EPS
-  files which are normally embedded within other documents, and is
-  Matlab compatible.  If necessary use the `"-loose"` option to
-  reproduce figures as they appeared in previous versions of Octave.
-
-- The following print devices are no longer officially supported: cdr,
-  corel, aifm, ill, cgm, hpgl, mf and dxf.  A warning will be thrown
-  when using those devices, and the code for supporting those formats
-  will eventually be removed from a future version of Octave.
-
-- The placement of text subscripts and superscripts has been
-re-engineered and now produces visually attractive results similar to
-Latex.
+- Support for Qt4 for graphics and the GUI has been removed.
 
 ### Matlab compatibility
 
-- The function `unique` now returns column index vectors for the second
-  and third outputs.  When duplicate values are present, the default
-  index to return is now the `"first"` occurrence.  The previous Octave
-  behavior, or Matlab behavior from releases prior to R2012b, can be
-  obtained by using the `"legacy"` flag.
+- The function `griddata` now implements the "v4" Biharmonic Spline
+Interpolation method.  In adddition, the function now accepts 3-D inputs
+by passing the data to `griddata3`.
 
-- The function `setdiff` with the `"rows"` argument now returns Matlab
-  compatible results.  The previous Octave behavior, or Matlab behavior
-  from releases prior to R2012b, can be obtained by using the `"legacy"`
-  flag.
+- Coordinate transformation functions `cart2sph`, `sph2cart`,
+`cart2pol`, and `pol2cart` can now accept either row or column vectors
+for coordinate inputs.  A single coordinate matrix with one variable per
+column can still be used as function input, but a single output variable
+will now contain just the first output coordinate, and will no longer
+return the full output coordinate matrix.  Output size matches the
+size of input vectors, or in the case of an input matrix will be column
+vectors with rows corresponding to the input coordinate matrix.
 
-- The functions `intersect`, `setxor`, and `union` now accept a
-  `"legacy"` flag which changes the index values (second and third
-  outputs) as well as the orientation of all outputs to match Matlab
-  releases prior to R2012b.
+- The function `dec2bin` and `dec2hex` now support negative numbers.
 
-- The function `streamtube` is Matlab compatible and plots tubes along
-  streamlines which are scaled by the vector field divergence. The
-  Octave-only extension `ostreamtube` can be used to visualize the flow
-  expansion and contraction of the vector field due to the local
-  crossflow divergence.
-
-- The interpreter now supports handles to nested functions.
-
-- The graphics properties `"LineWidth"` and `"MarkerSize"` are now
-  measured in points, *not* pixels.  Compared to previous versions
-  of Octave, some lines and markers will appear 4/3 larger.
+- The function `importdata` now produces more compatible results when
+the file contains a 2-D text matrix.
 
-- The meta.class property "SuperClassList" has been renamed
-  "Superclasslist" for Matlab compatibility.  The original name will
-  exist as an alias until Octave version 8.1.
+- `uicontrol` objects now fully implement the "Off" and "Inactive"
+values of the "Enable" property.  When the value is "Off", no
+interaction with the object occurs and the `uicontrol` changes color
+(typically to gray) to indicate it is disabled.  When the value is
+"Inactive", the object appears normally (no change in color), but it is
+not possible to change the value of the object (such as modifying text
+in an `Edit` box or clicking on a `RadioButton`).
 
-- The function `javaaddpath` now prepends new directories to the
-  existing dynamic classpath by default.  To append them instead, use
-  the new `"-end"` argument.  Multiple directories may now be specified
-  in a cell array of strings.
+- The functions `scatter` and `scatter3` now return a handle to a scatter
+graphics object.  For compatibility, they return a hg group of patch
+graphics objects when the "gnuplot" graphics toolkit is used.  In
+previous versions of Octave, these functions returned a hg group of patch
+graphics objects for all graphics toolkits.
 
-- An undocumented function `gui_mainfcn` has been added, for compatibility
-  with figures created with Matlab's GUIDE.
-
-- Several validator functions of type `mustBe*` have been added.  See
-  the list of new functions below.
+- The function `saveas` now defaults to saving in Octave figure format
+(.ofig) rather than PDF (.pdf).
 
-### Alphabetical list of new functions added in Octave 6
+- The additional property "contextmenu" has been added to all graphics
+objects.  It is equivalent to the previously used "uicontextmenu"
+property which is hidden now.
+
+- A new warning ID (Octave:unimplemented-matlab-functionality) has been
+added which prints a warning when Octave's parser recognizes valid
+Matlab code, but for which Octave does not yet implement the
+functionality.  By default, this warning is enabled.
 
-* `commandhistory`
-* `commandwindow`
-* `filebrowser`
-* `is_same_file`
-* `lightangle`
-* `mustBeFinite`
-* `mustBeGreaterThan`
-* `mustBeGreaterThanOrEqual`
-* `mustBeInteger`
-* `mustBeLessThan`
-* `mustBeLessThanOrEqual`
-* `mustBeMember`
-* `mustBeNegative`
-* `mustBeNonempty`
-* `mustBeNonNan`
-* `mustBeNonnegative`
-* `mustBeNonpositive`
-* `mustBeNonsparse`
-* `mustBeNonzero`
-* `mustBeNumeric`
-* `mustBeNumericOrLogical`
-* `mustBePositive`
-* `mustBeReal`
-* `namedargs2cell`
-* `newline`
-* `ode23s`
-* `ostreamtube`
-* `rescale`
-* `rotx`
-* `roty`
-* `rotz`
-* `stream2`
-* `stream3`
-* `streamline`
-* `streamtube`
-* `uisetfont`
-* `verLessThan`
-* `web`
-* `weboptions`
-* `webread`
-* `webwrite`
-* `workspace`
+- Additional properties have been added for the `axes` graphics object:
+    * "alphamap" (not yet implemented)
+    * "alphascale" (not yet implemented)
+    * "colorscale" (not yet implemented)
+    * "fontsizemode" (not yet implemented)
+    * "innerposition" (equivalent to "position")
+    * "interactions" (not yet implemented)
+    * "layout" (not yet implemented)
+    * "legend" (not yet implemented)
+    * "nextseriesindex" (read-only, used by `scatter` graphics objects)
+    * "positionconstraint" (replacement for "activepositionproperty"
+      which is now a hidden property.  No plans for removal.)
+    * "toolbar" (not yet implemented)
+    * "xaxis" (not yet implemented)
+    * "yaxis" (not yet implemented)
+    * "zaxis" (not yet implemented)
 
+### Alphabetical list of new functions added in Octave 7
+
+* `getpixelposition`
+* `endsWith`
+* `listfonts`
+* `memory`
+* `rng`
+* `startsWith`
+* `streamribbon`
 
 ### Deprecated functions and properties
 
-The following functions and properties have been deprecated in Octave 6
-and will be removed from Octave 8 (or whatever version is the second
-major release after 6):
+The following functions and properties have been deprecated in Octave 7
+and will be removed from Octave 9 (or whatever version is the second
+major release after 7):
 
 - Functions
 
   Function               | Replacement
   -----------------------|------------------
-  `runtests`             | `oruntests`
+                         |
 
 - Properties
 
@@ -259,47 +130,31 @@
   -----------------|---------------|------------
                    |               |
 
-
 ### Removed functions and properties
 
-The following functions and properties were deprecated in Octave 4.4
-and have been removed from Octave 6.
+The following functions and properties were deprecated in Octave 5
+and have been removed from Octave 7.
 
 - Functions
 
-  Function             | Replacement
-  ---------------------|------------------
-  `chop`               | `sprintf` for visual results
-  `desktop`            | `isguirunning`
-  `tmpnam`             | `tempname`
-  `toascii`            | `double`
-  `java2mat`           | `__java2mat__`
+  Function                 | Replacement
+  -------------------------|------------------
+  `output_max_field_width` | `output_precision`
+  `is_keyword`             | `iskeyword`
 
 - Properties
 
-  Object               | Property                  | Value
-  ---------------------|---------------------------|-----------------------
-  `annotation`         | `edgecolor ("rectangle")` |
-  `axes`               | `drawmode`                |
-  `figure`             | `doublebuffer`            |
-                       | `mincolormap`             |
-                       | `wvisual`                 |
-                       | `wvisualmode`             |
-                       | `xdisplay`                |
-                       | `xvisual`                 |
-                       | `xvisualmode`             |
-  `line`               | `interpreter`             |
-  `patch`              | `interpreter`             |
-  `surface`            | `interpreter`             |
-  `text`               | `fontweight`              | `"demi"` and `"light"`
-  `uibuttongroup`      | `fontweight`              | `"demi"` and `"light"`
-  `uicontrol`          | `fontweight`              | `"demi"` and `"light"`
-  `uipanel`            | `fontweight`              | `"demi"` and `"light"`
-  `uitable`            | `fontweight`              | `"demi"` and `"light"`
-
+  Object           | Property      | Value
+  -----------------|---------------|------------
+  `text`           | `fontangle`   | `"oblique"`
+  `uibuttongroup`  | `fontangle`   | `"oblique"`
+  `uicontrol`      | `fontangle`   | `"oblique"`
+  `uipanel`        | `fontangle`   | `"oblique"`
+  `uitable`        | `fontangle`   | `"oblique"`
 
 ### Old release news
 
+- [Octave 6.x](etc/NEWS.6)
 - [Octave 5.x](etc/NEWS.5)
 - [Octave 4.x](etc/NEWS.4)
 - [Octave 3.x](etc/NEWS.3)
--- a/bootstrap.conf	Tue Jul 07 18:34:23 2020 -0400
+++ b/bootstrap.conf	Tue Jul 07 19:40:20 2020 -0400
@@ -117,9 +117,12 @@
   unictype/ctype-upper
   unictype/ctype-xdigit
   unistd
+  unistr/u16-to-u8
+  unistr/u32-to-u8
   unistr/u8-check
   unistr/u8-strmblen
   unistr/u8-strmbtouc
+  unistr/u8-to-u16
   unistr/u8-to-u32
   unlink
   unsetenv
--- a/configure.ac	Tue Jul 07 18:34:23 2020 -0400
+++ b/configure.ac	Tue Jul 07 19:40:20 2020 -0400
@@ -27,7 +27,7 @@
 
 ### Initialize Autoconf
 AC_PREREQ([2.65])
-AC_INIT([GNU Octave], [6.0.1], [https://octave.org/bugs.html], [octave],
+AC_INIT([GNU Octave], [7.0.0], [https://octave.org/bugs.html], [octave],
         [https://www.gnu.org/software/octave/])
 
 ### Declare version numbers
@@ -39,9 +39,9 @@
 ## explains how to update these numbers for release and development
 ## versions.
 
-OCTAVE_MAJOR_VERSION=6
+OCTAVE_MAJOR_VERSION=7
 OCTAVE_MINOR_VERSION=0
-OCTAVE_PATCH_VERSION=1
+OCTAVE_PATCH_VERSION=0
 
 dnl PACKAGE_VERSION is set by the AC_INIT VERSION argument.
 OCTAVE_VERSION="$PACKAGE_VERSION"
@@ -63,7 +63,7 @@
 dnl FIXME: Since we also set libtool versions for liboctave and libinterp,
 dnl perhaps we should be computing the "api version" from those versions numbers
 dnl in some way instead of setting it independently here.
-OCTAVE_API_VERSION="api-v54"
+OCTAVE_API_VERSION="api-v54+"
 
 AC_SUBST(OCTAVE_MAJOR_VERSION)
 AC_SUBST(OCTAVE_MINOR_VERSION)
@@ -536,20 +536,6 @@
 AC_DEFINE_UNQUOTED(OCTAVE_IDX_TYPE, [$OCTAVE_IDX_TYPE],
   [Define to the type of octave_idx_type (64 or 32 bit signed integer).])
 
-### Enable bounds checking on element references within Octave's array and
-### matrix classes.
-dnl This slows down some operations a bit, so it is turned off by default.
-
-ENABLE_BOUNDS_CHECK=no
-AC_ARG_ENABLE([bounds-check],
-  [AS_HELP_STRING([--enable-bounds-check],
-    [OBSOLETE: use --enable-address-sanitizer-flags instead])],
-  [if test "$enableval" = yes; then ENABLE_BOUNDS_CHECK=yes; fi], [])
-if test $ENABLE_BOUNDS_CHECK = yes; then
-  warn_bounds_check="--enable-bounds-check is obsolete; use --enable-address-sanitizer-flags instead"
-  OCTAVE_CONFIGURE_WARNING([warn_bounds_check])
-fi
-
 ### Check for pthread library
 
 AX_PTHREAD
@@ -1371,7 +1357,7 @@
   [zlib.h], [gzclearerr])
 
 ## Also define HAVE_ZLIB if libz is found.
-if test -z "$warn_z"; then
+if test -n "$Z_LIBS"; then
   AC_DEFINE(HAVE_ZLIB, 1, [Define to 1 if ZLIB is available.])
 fi
 
@@ -1610,7 +1596,7 @@
 OCTAVE_CHECK_LIB(curl, cURL,
   [cURL library not found.  The ftp objects, urlread, and urlwrite functions will be disabled.],
   [curl/curl.h], [curl_easy_escape])
-if test -z "$warn_curl"; then
+if test -n "$CURL_LIBS"; then
   ## Additional check on cURL library that was found
   AC_CACHE_CHECK([for CURLOPT_DIRLISTONLY in curl/curl.h],
     [octave_cv_curl_has_curlopt_dirlistonly],
@@ -1658,8 +1644,6 @@
     [select library to use for image I/O (options: GraphicsMagick(default) or ImageMagick)])],
   [if test x"$withval" = xno; then
      check_magick=no
-     warn_magick_disabled="--without-magick specified.  The imread, imwrite, and imfinfo functions for reading and writing image files will not be fully functional."
-     OCTAVE_CONFIGURE_WARNING([warn_magick_disabled])
    else
      magick="$withval"
    fi], [magick="GraphicsMagick"])
@@ -1771,8 +1755,6 @@
     [don't use OpenGL libraries, disable OpenGL graphics])],
   [if test x"$withval" = xno; then
      check_opengl=no
-     warn_opengl_disabled="--without-opengl specified.  OpenGL graphics will be disabled."
-     OCTAVE_CONFIGURE_WARNING([warn_opengl_disabled])
    fi])
 
 ## Check for OpenGL library
@@ -1793,7 +1775,6 @@
     [don't use FreeType library, OpenGL graphics will not be fully functional])],
   [if test x"$withval" = xno; then
      check_freetype=no
-     warn_freetype="--without-freetype specified.  OpenGL graphics will not be fully functional."
    fi])
 
 if test $check_freetype = yes; then
@@ -1834,26 +1815,9 @@
   [fontconfig.h fontconfig/fontconfig.h], [FcInit],
   [], [don't use fontconfig library, OpenGL graphics will not be fully functional])
 
-## Check for gl2ps which is required for printing with OpenGL graphics.
-
-AC_CHECK_HEADERS([gl2ps.h],
-  [GL2PS_LIBS="-lgl2ps"],
-  [warn_gl2ps="gl2ps library not found.  Printing of OpenGL graphics will be disabled."])
-
-if test -n "$warn_gl2ps"; then
-  OCTAVE_CONFIGURE_WARNING([warn_gl2ps])
-else
-  save_LIBS="$LIBS"
-  LIBS="$GL2PS_LIBS $LIBS"
-  AC_CHECK_FUNCS([gl2psLineJoin])
-  LIBS="$save_LIBS"
-fi
-
-AC_SUBST(GL2PS_LIBS)
-
 ### GUI/Qt related tests.
 
-QT_VERSIONS="5 4"
+QT_VERSIONS="5"
 
 AC_ARG_WITH([qt],
   [AS_HELP_STRING([--with-qt=VER], [use the Qt major version VER])
@@ -1864,8 +1828,6 @@
      ;;
      no)
        QT_VERSIONS=
-       warn_qt_disabled="--without-qt specified.  The Qt GUI will be disabled."
-       OCTAVE_CONFIGURE_WARNING([warn_qt_disabled])
      ;;
      *)
        QT_VERSIONS="$withval"
@@ -1877,8 +1839,6 @@
   [AS_HELP_STRING([--without-qscintilla], [disable QScintilla editor])],
   [if test x"$withval" = xno; then
      check_qscintilla=no
-     warn_qscintilla_disabled="--without-qscintilla specified.  The GUI editor will be disabled."
-     OCTAVE_CONFIGURE_WARNING([warn_qscintilla_disabled])
    fi])
 
 OCTAVE_CHECK_QT([$QT_VERSIONS])
@@ -2019,6 +1979,25 @@
   opengl_graphics=yes
 fi
 
+## Check for gl2ps which is required for printing with OpenGL graphics.
+
+if test $opengl_graphics = yes; then
+  AC_CHECK_HEADERS([gl2ps.h],
+    [GL2PS_LIBS="-lgl2ps"],
+    [warn_gl2ps="gl2ps library not found.  Printing of OpenGL graphics will be disabled."])
+
+  if test -n "$warn_gl2ps"; then
+    OCTAVE_CONFIGURE_WARNING([warn_gl2ps])
+  else
+    save_LIBS="$LIBS"
+    LIBS="$GL2PS_LIBS $LIBS"
+    AC_CHECK_FUNCS([gl2psLineJoin])
+    LIBS="$save_LIBS"
+  fi
+
+  AC_SUBST(GL2PS_LIBS)
+fi
+
 ### Check for the qrupdate library
 
 dnl No need to adjust FFLAGS because only link is attempted.
@@ -2032,7 +2011,7 @@
   [Fortran 77], [don't use qrupdate, disable QR & Cholesky updating functions])
 
 ## Additional check to see if qrupdate lib found supports LU updates
-if test -z "$warn_qrupdate"; then
+if test -n "$QRUPDATE_LIBS"; then
   AC_CACHE_CHECK([for slup1up in $QRUPDATE_LIBS],
     [octave_cv_func_slup1up],
     [LIBS="$LIBS $QRUPDATE_LIBS"
@@ -2130,7 +2109,7 @@
   [cs${CXSPARSE_TAG}sqr],
   [C++], [don't use CXSparse library, disable some sparse matrix functionality])
 
-if test -z "$warn_cxsparse"; then
+if test -n "$CXSPARSE_LIBS"; then
   ## Additional check for CXSparse version >= 2.2
   if test $octave_cv_lib_cxsparse = yes; then
     OCTAVE_CHECK_CXSPARSE_VERSION_OK
@@ -2223,50 +2202,56 @@
 
 ### Check for SUNDIALS IDA library and header.
 
-save_CPPFLAGS="$CPPFLAGS"
-save_LDFLAGS="$LDFLAGS"
-save_LIBS="$LIBS"
-LIBS="$SUNDIALS_NVECSERIAL_LIBS $KLU_LIBS $BLAS_LIBS $FLIBS $LIBS"
-LDFLAGS="$SUNDIALS_NVECSERIAL_LDFLAGS $KLU_LDFLAGS $BLAS_LDFLAGS $LDFLAGS"
-CPPFLAGS="$SUNDIALS_NVECSERIAL_CPPFLAGS $KLU_CPPFLAGS $BLAS_CPPFLAGS $CPPFLAGS"
-OCTAVE_CHECK_LIB(sundials_ida, [SUNDIALS IDA],
-  [SUNDIALS IDA library not found.  The solvers ode15i and ode15s will be disabled.],
-  [ida/ida.h ida.h], [IDAInit],
-  [], [don't use SUNDIALS IDA library, disable solvers ode15i and ode15s])
-CPPFLAGS="$save_CPPFLAGS"
-LDFLAGS="$save_LDFLAGS"
-LIBS="$save_LIBS"
+if test -n "$SUNDIALS_NVECSERIAL_LIBS"; then
+
+  save_CPPFLAGS="$CPPFLAGS"
+  save_LDFLAGS="$LDFLAGS"
+  save_LIBS="$LIBS"
+  LIBS="$SUNDIALS_NVECSERIAL_LIBS $KLU_LIBS $BLAS_LIBS $FLIBS $LIBS"
+  LDFLAGS="$SUNDIALS_NVECSERIAL_LDFLAGS $KLU_LDFLAGS $BLAS_LDFLAGS $LDFLAGS"
+  CPPFLAGS="$SUNDIALS_NVECSERIAL_CPPFLAGS $KLU_CPPFLAGS $BLAS_CPPFLAGS $CPPFLAGS"
+  OCTAVE_CHECK_LIB(sundials_ida, [SUNDIALS IDA],
+    [SUNDIALS IDA library not found.  The solvers ode15i and ode15s will be disabled.],
+    [ida/ida.h ida.h], [IDAInit],
+    [], [don't use SUNDIALS IDA library, disable solvers ode15i and ode15s])
+  CPPFLAGS="$save_CPPFLAGS"
+  LDFLAGS="$save_LDFLAGS"
+  LIBS="$save_LIBS"
+fi
 
 ### Check for SUNDIALS library features, some required, some optional.
 
-CPPFLAGS="$SUNDIALS_IDA_CPPFLAGS $SUNDIALS_NVECSERIAL_CPPFLAGS $KLU_CPPFLAGS $BLAS_CPPFLAGS $CPPFLAGS"
-LDFLAGS="$SUNDIALS_IDA_LDFLAGS $SUNDIALS_NVECSERIAL_LDFLAGS $KLU_LDFLAGS $BLAS_LDFLAGS $LDFLAGS"
-LIBS="$SUNDIALS_IDA_LIBS $SUNDIALS_NVECSERIAL_LIBS $KLU_LIBS $BLAS_LIBS $FLIBS $LIBS"
-if test -z "$warn_sundials_nvecserial" && test -z "$warn_sundials_ida"; then
-  dnl Any of the following tests could determine that SUNDIALS is incompatible
-  dnl and should be disabled. In that event, they all populate the same
-  dnl variable with appropriate warning messages, and further tests should be
-  dnl skipped if a warning message has already been generated that SUNDIALS is
-  dnl disabled.
-  warn_sundials_disabled=
-  if test -z "$warn_sundials_disabled"; then
-    OCTAVE_CHECK_SUNDIALS_COMPATIBLE_API
+if test -n "$SUNDIALS_IDA_LIBS" && test -n "$SUNDIALS_NVECSERIAL_LIBS"; then
+
+  CPPFLAGS="$SUNDIALS_IDA_CPPFLAGS $SUNDIALS_NVECSERIAL_CPPFLAGS $KLU_CPPFLAGS $BLAS_CPPFLAGS $CPPFLAGS"
+  LDFLAGS="$SUNDIALS_IDA_LDFLAGS $SUNDIALS_NVECSERIAL_LDFLAGS $KLU_LDFLAGS $BLAS_LDFLAGS $LDFLAGS"
+  LIBS="$SUNDIALS_IDA_LIBS $SUNDIALS_NVECSERIAL_LIBS $KLU_LIBS $BLAS_LIBS $FLIBS $LIBS"
+  if test -z "$warn_sundials_nvecserial" && test -z "$warn_sundials_ida"; then
+    dnl Any of the following tests could determine that SUNDIALS is incompatible
+    dnl and should be disabled. In that event, they all populate the same
+    dnl variable with appropriate warning messages, and further tests should be
+    dnl skipped if a warning message has already been generated that SUNDIALS is
+    dnl disabled.
+    warn_sundials_disabled=
+    if test -z "$warn_sundials_disabled"; then
+      OCTAVE_CHECK_SUNDIALS_COMPATIBLE_API
+    fi
+    if test -z "$warn_sundials_disabled"; then
+      OCTAVE_CHECK_SUNDIALS_SIZEOF_REALTYPE
+    fi
+    if test -z "$warn_sundials_disabled"; then
+      OCTAVE_CHECK_SUNDIALS_SUNLINSOL_DENSE
+    fi
+    dnl The following tests determine whether certain optional features are
+    dnl present in the SUNDIALS libraries, but will not disable using SUNDIALS.
+    if test -z "$warn_sundials_disabled"; then
+      OCTAVE_CHECK_SUNDIALS_SUNLINSOL_KLU
+    fi
   fi
-  if test -z "$warn_sundials_disabled"; then
-    OCTAVE_CHECK_SUNDIALS_SIZEOF_REALTYPE
-  fi
-  if test -z "$warn_sundials_disabled"; then
-    OCTAVE_CHECK_SUNDIALS_SUNLINSOL_DENSE
-  fi
-  dnl The following tests determine whether certain optional features are
-  dnl present in the SUNDIALS libraries, but will not disable using SUNDIALS.
-  if test -z "$warn_sundials_disabled"; then
-    OCTAVE_CHECK_SUNDIALS_SUNLINSOL_KLU
-  fi
+  CPPFLAGS="$save_CPPFLAGS"
+  LDFLAGS="$save_LDFLAGS"
+  LIBS="$save_LIBS"
 fi
-CPPFLAGS="$save_CPPFLAGS"
-LDFLAGS="$save_LDFLAGS"
-LIBS="$save_LIBS"
 
 dnl Define this way instead of with an #if in oct-conf-post.h so that
 dnl the build features script will get the correct value.
@@ -2275,36 +2260,36 @@
 dnl How can we do a better job here?  Do we need to disable sundials
 dnl any tests fail, or can we fix __ode15__.cc so that it still partially
 dnl works when some things are missing (for example, KLU)?
-if test -n "$SUNDIALS_IDA_LIBS" \
-    && test -n "$SUNDIALS_NVECSERIAL_LIBS" \
-    && test "x$octave_cv_sundials_sunlinsol_dense" = xyes \
-    && test "x$octave_cv_sundials_realtype_is_double" = xyes \
-    && test "x$octave_have_sundials_compatible_api" = xyes; then
-  AC_DEFINE(HAVE_SUNDIALS, 1, [Define to 1 if SUNDIALS is available.])
-
-  ## Collections of options needed to build with SUNDIALS and its dependencies.
-  SUNDIALS_XCPPFLAGS="$SUNDIALS_IDA_CPPFLAGS $SUNDIALS_SUNLINSOLKLU_CPPFLAGS $SUNDIALS_NVECSERIAL_CPPFLAGS $KLU_CPPFLAGS"
-  SUNDIALS_XLDFLAGS="$SUNDIALS_IDA_LDFLAGS $SUNDIALS_SUNLINSOLKLU_LDFLAGS $SUNDIALS_NVECSERIAL_LDFLAGS $KLU_LDFLAGS"
-  SUNDIALS_XLIBS="$SUNDIALS_IDA_LIBS $SUNDIALS_SUNLINSOLKLU_LIBS $SUNDIALS_NVECSERIAL_LIBS $KLU_LIBS"
-else
-  SUNDIALS_IDA_CPPFLAGS=
-  SUNDIALS_IDA_LDFLAGS=
-  SUNDIALS_IDA_LIBS=
-  SUNDIALS_SUNLINSOLKLU_CPPFLAGS=
-  SUNDIALS_SUNLINSOLKLU_LDFLAGS=
-  SUNDIALS_SUNLINSOLKLU_LIBS=
-  SUNDIALS_NVECSERIAL_CPPFLAGS=
-  SUNDIALS_NVECSERIAL_LDFLAGS=
-  SUNDIALS_NVECSERIAL_LIBS=
-  SUNDIALS_XCPPFLAGS=
-  SUNDIALS_XLDFLAGS=
-  SUNDIALS_XLIBS=
-  dnl Emit a fallback warning message in case SUNDIALS has been disabled for
-  dnl some reason that hasn't already generated one of these known warnings.
-  if test -z "$warn_sundials_nvecserial" && test -z "$warn_sundials_ida" \
-      && test -z "$warn_sundials_disabled"; then
-    warn_sundials_disabled="SUNDIALS libraries are missing some feature.  The solvers ode15i and ode15s will be disabled."
-    OCTAVE_CONFIGURE_WARNING([warn_sundials_disabled])
+if test -n "$SUNDIALS_IDA_LIBS" && test -n "$SUNDIALS_NVECSERIAL_LIBS"; then
+  if test "x$octave_cv_sundials_sunlinsol_dense" = xyes \
+      && test "x$octave_cv_sundials_realtype_is_double" = xyes \
+      && test "x$octave_have_sundials_compatible_api" = xyes; then
+    AC_DEFINE(HAVE_SUNDIALS, 1, [Define to 1 if SUNDIALS is available.])
+
+    ## Options needed to build with SUNDIALS and its dependencies.
+    SUNDIALS_XCPPFLAGS="$SUNDIALS_IDA_CPPFLAGS $SUNDIALS_SUNLINSOLKLU_CPPFLAGS $SUNDIALS_NVECSERIAL_CPPFLAGS $KLU_CPPFLAGS"
+    SUNDIALS_XLDFLAGS="$SUNDIALS_IDA_LDFLAGS $SUNDIALS_SUNLINSOLKLU_LDFLAGS $SUNDIALS_NVECSERIAL_LDFLAGS $KLU_LDFLAGS"
+    SUNDIALS_XLIBS="$SUNDIALS_IDA_LIBS $SUNDIALS_SUNLINSOLKLU_LIBS $SUNDIALS_NVECSERIAL_LIBS $KLU_LIBS"
+  else
+    SUNDIALS_IDA_CPPFLAGS=
+    SUNDIALS_IDA_LDFLAGS=
+    SUNDIALS_IDA_LIBS=
+    SUNDIALS_SUNLINSOLKLU_CPPFLAGS=
+    SUNDIALS_SUNLINSOLKLU_LDFLAGS=
+    SUNDIALS_SUNLINSOLKLU_LIBS=
+    SUNDIALS_NVECSERIAL_CPPFLAGS=
+    SUNDIALS_NVECSERIAL_LDFLAGS=
+    SUNDIALS_NVECSERIAL_LIBS=
+    SUNDIALS_XCPPFLAGS=
+    SUNDIALS_XLDFLAGS=
+    SUNDIALS_XLIBS=
+    dnl Emit a fallback warning message in case SUNDIALS has been disabled for
+    dnl some reason that hasn't already generated one of these known warnings.
+    if test -z "$warn_sundials_nvecserial" && test -z "$warn_sundials_ida" \
+        && test -z "$warn_sundials_disabled"; then
+      warn_sundials_disabled="SUNDIALS libraries are missing some feature.  The solvers ode15i and ode15s will be disabled."
+      OCTAVE_CONFIGURE_WARNING([warn_sundials_disabled])
+    fi
   fi
 fi
 
@@ -2325,7 +2310,7 @@
    OCTAVE_CHECK_LIB_ARPACK_OK_1(
      [AC_DEFINE(HAVE_ARPACK, 1, [Define to 1 if ARPACK is available.])],
      [warn_arpack="ARPACK library found, but does not seem to work properly; disabling eigs function"])
-   if test -z "$warn_arpack"; then
+   if test -n "$ARPACK_LIBS"; then
      OCTAVE_CHECK_LIB_ARPACK_OK_2([],
        [AC_MSG_WARN([ARPACK library found, but is buggy; upgrade library (>= v3.3.0) for better results])])
    fi
@@ -2602,6 +2587,7 @@
      warn_docs="building documentation disabled; make dist will fail."
      OCTAVE_CONFIGURE_WARNING([warn_docs])
    fi], [])
+
 if test $ENABLE_DOCS = yes; then
   if test $opengl_graphics = no || test "$have_qt_opengl_offscreen" = no; then
     if test -n "$warn_gnuplot"; then
@@ -2620,6 +2606,7 @@
   AC_DEFINE(ENABLE_DOCS, 1,
     [Define to 1 to build Octave documentation files.])
 fi
+
 AM_CONDITIONAL([AMCOND_BUILD_DOCS], [test $ENABLE_DOCS = yes])
 
 AM_CONDITIONAL([AMCOND_BUILD_QT_DOCS],
@@ -3003,7 +2990,7 @@
   libgui/mk-default-qt-settings.sh
   liboctave/external/mk-f77-def.sh
   liboctave/mk-version-h.sh
-  libinterp/corefcn/mk-mxarray-h.sh
+  libinterp/corefcn/mk-mxtypes-h.sh
   build-aux/subst-config-vals.sh
   build-aux/subst-cross-config-vals.sh
   build-aux/subst-script-vals.sh])
--- a/doc/interpreter/contributors.in	Tue Jul 07 18:34:23 2020 -0400
+++ b/doc/interpreter/contributors.in	Tue Jul 07 19:40:20 2020 -0400
@@ -89,6 +89,7 @@
 Paul Eggert
 Stephen Eglen
 Peter Ekberg
+Abdallah K. Elshamy
 Garrett Euler
 Edmund Grimley Evans
 Rolf Fabian
@@ -246,6 +247,7 @@
 Laurent Mazet
 G. D. McBain
 Ronald van der Meer
+Markus Meisinger
 Júlio Hoffimann Mendes
 Ed Meyer
 Thorsten Meyer
--- a/doc/interpreter/genpropdoc.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/doc/interpreter/genpropdoc.m	Tue Jul 07 19:40:20 2020 -0400
@@ -39,9 +39,10 @@
 
 function genpropdoc (objname, fname)
   objnames = {"root", "figure", "axes", ...
-              "image", "light", "line", "patch", "surface", "text", ...
-              "uibuttongroup", "uicontextmenu", "uicontrol", "uipanel", ...
-              "uimenu", "uipushtool", "uitable", "uitoggletool" "uitoolbar"
+              "image", "light", "line", "patch", "scatter", "surface", ...
+              "text", "uibuttongroup", "uicontextmenu", "uicontrol", ...
+              "uipanel", "uimenu", "uipushtool", "uitable", ...
+              "uitoggletool", "uitoolbar"
              };
 
   ## Base properties
@@ -169,6 +170,11 @@
         s.doc = "If __prop__ is @qcode{\"on\"}, the __objname__ is \
 clipped in its parent axes limits.";
 
+      case "contextmenu"
+        s.doc = "Graphics handle of the uicontextmenu object that is \
+currently associated to this __objname__ object.";
+        s.valid = valid_handle;
+
       case "createfcn"
         s.doc = "Callback function executed immediately after __objname__ \
 has been created.  Function is set by using default property on root object, \
@@ -228,11 +234,6 @@
         s.valid = valid_string;
         s.printdefault = false;
 
-      case "uicontextmenu"
-        s.doc = "Graphics handle of the uicontextmenu object that is \
-currently associated to this __objname__ object.";
-        s.valid = valid_handle;
-
       case "userdata"
         s.doc = "User-defined data to associate with the graphics object.";
         s.valid = "Any Octave data";
@@ -657,12 +658,6 @@
         s.doc = doc_unused;
 
       ## Specific properties
-      case "activepositionproperty"
-        s.doc = "Specify which of @qcode{\"position\"} or \
-@qcode{\"outerposition\"} properties takes precedence when axes \
-annotations extent changes.  @xref{XREFaxesposition, , @w{position property}}, \
-and @ref{XREFaxesposition, , @w{outerposition property}}.";
-
       case "alim"
         s.doc = sprintf (doc_notimpl, "Transparency");
 
@@ -769,6 +764,11 @@
 
       case "gridlinestyle"
 
+      case "innerposition"
+        s.doc = "The @qcode{\"innerposition\"} property is the same as the \
+@ref{XREFaxesposition, , @w{@qcode{\"position\"} property}}.";
+        s.valid = valid_4elvec;
+
       case "labelfontsizemultiplier"
         s.doc = "Ratio between the x/y/zlabel fontsize and the tick \
 label fontsize";
@@ -837,6 +837,13 @@
 @xref{XREFaxesouterposition, , @w{outerposition property}}.";
         s.valid = valid_4elvec;
 
+      case "positionconstraint"
+        s.doc = "Specify which of @qcode{\"innerposition\"} or \
+@qcode{\"outerposition\"} properties takes precedence when axes \
+annotations extent changes.  \
+@xref{XREFaxesinnerposition, , @w{@qcode{\"innerposition\"} property}}, \
+and @ref{XREFaxesouterposition, , @w{@qcode{\"outerposition\"} property}}.";
+
       case "projection"
         s.doc = doc_unused;
 
@@ -1533,6 +1540,117 @@
 
     endswitch
 
+  ## Scatter properties
+  elseif (strcmp (objname, "scatter"))
+    switch (field)
+      ## Overridden shared properties
+      case "children"
+        s.doc = doc_unused;
+
+      ## Specific properties
+      case "cdatamode"
+        s.doc = "If @code{cdatamode} is @qcode{\"auto\"}, @code{cdata} is set \
+to the color from the @code{colororder} of the ancestor axes corresponding to \
+the @code{seriesindex}.";
+
+      case "cdatasource"
+        s.doc = sprintf (doc_notimpl, "Data from workspace variables");
+
+      case "cdata"
+        s.doc = "Data defining the scatter object color.\n\
+\n\
+If @code{cdata} is a scalar index into the current colormap or a RGB triplet, \
+it defines the color of all scatter markers.\n\
+\n\
+If @code{cdata} is an N-by-1 vector of indices or an N-by-3 (RGB) matrix, \
+it defines the color of each one of the N scatter markers.";
+        s.valid = valid_scalmat;
+
+
+      case "displayname"
+        s.doc = "Text of the legend entry corresponding to this scatter object.";
+
+      case "linewidth"
+        s.doc = "Line width of the edge of the markers.";
+
+      case "marker"
+        s.doc = "@xref{XREFlinemarker, , @w{line marker property}}.";
+
+      case "markeredgealpha"
+        s.doc = "Transparency level of the faces of the markers where a \
+value of 0 means complete transparency and a value of 1 means solid faces \
+without transparency.  Note that the markers are not sorted from back to \
+front which might lead to unexpected results when rendering layered \
+transparent markers or in combination with other transparent objects.";
+        s.valid = "scalar";
+
+      case "markeredgecolor"
+        s.doc = "Color of the edge of the markers.  @qcode{\"none\"} means \
+that the edges are transparent and @qcode{\"flat\"} means that the value \
+from @code{cdata} is used.  @xref{XREFlinemarkeredgecolor, , \
+@w{line markeredgecolor property}}.";
+        s.valid = packopt ({markdef("@qcode{\"none\"}"), ...
+                            "@qcode{\"flat\"}", ...
+                            valid_color});
+
+      case "markerfacealpha"
+        s.doc = "Transparency level of the faces of the markers where a \
+value of 0 means complete transparency and a value of 1 means solid faces \
+without transparency.  Note that the markers are not sorted from back to \
+front which might lead to unexpected results when rendering layered \
+transparent markers or in combination with other transparent objects.";
+        s.valid = "scalar";
+
+      case "markerfacecolor"
+        s.doc = "Color of the face of the markers.  @qcode{\"none\"} means \
+that the faces are transparent, @qcode{\"flat\"} means that the value from \
+@code{cdata} is used, and @qcode{\"auto\"} uses the @code{color} property of \
+the ancestor axes. @xref{XREFlinemarkerfacecolor, , \
+@w{line markerfacecolor property}}.";
+        s.valid = packopt ({markdef("@qcode{\"none\"}"), ...
+                            "@qcode{\"flat\"}", ...
+                            "@qcode{\"auto\"}", ...
+                            valid_color});
+
+      case "seriesindex"
+        s.doc = "Each scatter object in the same axes is asigned an \
+incrementing integer.  This corresponds to the index into the \
+@code{colororder} of the ancestor axes that is used if @code{cdatamode} is \
+set to @qcode{\"auto\"}.";
+
+      case "sizedatasource"
+        s.doc = sprintf (doc_notimpl, "Data from workspace variables");
+
+      case "sizedata"
+        s.doc = "Size of the area of the marker. A scalar value applies to \
+all markers.  If @code{cdata} is an N-by-1 vector, it defines the color of \
+each one of the N scatter markers.";
+        s.valid =  packopt ({"[]", "scalar", "vector"});
+
+      case "xdatasource"
+        s.doc = sprintf (doc_notimpl, "Data from workspace variables");
+
+      case "xdata"
+        s.doc = "Vector with the x coordinates of the scatter object.";
+        s.valid = "vector";
+
+      case "ydatasource"
+        s.doc = sprintf (doc_notimpl, "Data from workspace variables");
+
+      case "ydata"
+        s.doc = "Vector with the y coordinates of the scatter object.";
+        s.valid = "vector";
+
+      case "zdatasource"
+        s.doc = sprintf (doc_notimpl, "Data from workspace variables");
+
+      case "zdata"
+        s.doc = "For 3D data, vector with the y coordinates of the scatter \
+object.";
+        s.valid = packopt ({"[]", "vector"});
+
+    endswitch
+
   ## Light properties
   elseif (strcmp (objname, "light"))
     switch (field)
@@ -1865,6 +1983,10 @@
     h = 0;
   elseif (strcmp (objname, "figure"))
     h = hf;
+  elseif (strcmp (objname, "scatter"))
+    ## Make sure to get a scatter object independent of graphics toolkit
+    hax = axes (hf);
+    h = __go_scatter__ (hax);
   else
     eval (["h = " objname " ();"]);
   endif
--- a/doc/interpreter/graphics_properties.mk	Tue Jul 07 18:34:23 2020 -0400
+++ b/doc/interpreter/graphics_properties.mk	Tue Jul 07 19:40:20 2020 -0400
@@ -5,6 +5,7 @@
   interpreter/plot-lineproperties.texi \
   interpreter/plot-patchproperties.texi \
   interpreter/plot-rootproperties.texi \
+  interpreter/plot-scatterproperties.texi \
   interpreter/plot-surfaceproperties.texi \
   interpreter/plot-textproperties.texi
 
@@ -35,5 +36,8 @@
 interpreter/plot-surfaceproperties.texi: interpreter/genpropdoc.m
 	$(AM_V_GEN)$(call gen-propdoc-texi,surface)
 
+interpreter/plot-scatterproperties.texi: interpreter/genpropdoc.m
+	$(AM_V_GEN)$(call gen-propdoc-texi,scatter)
+
 interpreter/plot-textproperties.texi: interpreter/genpropdoc.m
 	$(AM_V_GEN)$(call gen-propdoc-texi,text)
--- a/doc/interpreter/gui.txi	Tue Jul 07 18:34:23 2020 -0400
+++ b/doc/interpreter/gui.txi	Tue Jul 07 19:40:20 2020 -0400
@@ -141,6 +141,10 @@
 
 @DOCSTRING(isguirunning)
 
+@DOCSTRING(getpixelposition)
+
+@DOCSTRING(listfonts)
+
 @DOCSTRING(movegui)
 
 @DOCSTRING(openvar)
--- a/doc/interpreter/matrix.txi	Tue Jul 07 18:34:23 2020 -0400
+++ b/doc/interpreter/matrix.txi	Tue Jul 07 19:40:20 2020 -0400
@@ -175,6 +175,8 @@
 
 @DOCSTRING(randg)
 
+@DOCSTRING(rng)
+
 The generators operate in the new or old style together, it is not
 possible to mix the two.  Initializing any generator with
 @qcode{"state"} or @qcode{"seed"} causes the others to switch to the
--- a/doc/interpreter/module.mk	Tue Jul 07 18:34:23 2020 -0400
+++ b/doc/interpreter/module.mk	Tue Jul 07 19:40:20 2020 -0400
@@ -8,6 +8,7 @@
   %reldir%/plot-lineproperties.texi \
   %reldir%/plot-patchproperties.texi \
   %reldir%/plot-rootproperties.texi \
+  %reldir%/plot-scatterproperties.texi \
   %reldir%/plot-surfaceproperties.texi \
   %reldir%/plot-textproperties.texi \
   %reldir%/plot-uimenuproperties.texi \
@@ -51,6 +52,9 @@
 %reldir%/plot-rootproperties.texi: %reldir%/genpropdoc.m $(GRAPHICS_PROPS_SRC)
 	$(AM_V_GEN)$(call gen-propdoc-texi,root)
 
+%reldir%/plot-scatterproperties.texi: %reldir%/genpropdoc.m $(GRAPHICS_PROPS_SRC)
+	$(AM_V_GEN)$(call gen-propdoc-texi,scatter)
+
 %reldir%/plot-surfaceproperties.texi: %reldir%/genpropdoc.m $(GRAPHICS_PROPS_SRC)
 	$(AM_V_GEN)$(call gen-propdoc-texi,surface)
 
--- a/doc/interpreter/octave.texi	Tue Jul 07 18:34:23 2020 -0400
+++ b/doc/interpreter/octave.texi	Tue Jul 07 19:40:20 2020 -0400
@@ -568,6 +568,7 @@
 * Text Properties::
 * Image Properties::
 * Patch Properties::
+* Scatter Properties::
 * Surface Properties::
 * Light Properties::
 * Uimenu Properties::
@@ -599,7 +600,6 @@
 * Error Bar Series::
 * Line Series::
 * Quiver Group::
-* Scatter Group::
 * Stair Group::
 * Stem Series::
 * Surface Group::
--- a/doc/interpreter/plot.txi	Tue Jul 07 18:34:23 2020 -0400
+++ b/doc/interpreter/plot.txi	Tue Jul 07 19:40:20 2020 -0400
@@ -245,6 +245,8 @@
 
 @DOCSTRING(quiver3)
 
+@DOCSTRING(streamribbon)
+
 @DOCSTRING(streamtube)
 
 @DOCSTRING(ostreamtube)
@@ -1170,24 +1172,30 @@
 The graphics functions use pointers, which are of class graphics_handle, in
 order to address the data structures which control visual display.  A
 graphics handle may point to any one of a number of different base object
-types and these objects are the graphics data structures themselves.  The
+types.  These objects are the graphics data structures themselves.  The
 primitive graphic object types are: @code{figure}, @code{axes}, @code{line},
-@code{text}, @code{patch}, @code{surface}, @code{text}, @code{image}, and
-@code{light}.
-
-Each of these objects has a function by the same name, and, each of these
+@code{text}, @code{patch}, @code{scatter}, @code{surface}, @code{text},
+@code{image}, and @code{light}.
+
+Each of these objects has a function by the same name, and each of these
 functions returns a graphics handle pointing to an object of the corresponding
-type.  In addition there are several functions which operate on properties of
-the graphics objects and which also return handles: the functions @code{plot}
-and @code{plot3} return a handle pointing to an object of type line, the
-function @code{subplot} returns a handle pointing to an object of type axes,
-the function @code{fill} returns a handle pointing to an object of type patch,
-the functions @code{area}, @code{bar}, @code{barh}, @code{contour},
-@code{contourf}, @code{contour3}, @code{surf}, @code{mesh}, @code{surfc},
-@code{meshc}, @code{errorbar}, @code{quiver}, @code{quiver3}, @code{scatter},
-@code{scatter3}, @code{stair}, @code{stem}, @code{stem3} each return a handle
-to a complex data structure as documented in
-@ref{XREFdatasources,,Data Sources}.
+type.
+
+In addition, there are several functions which operate on properties of the
+graphics objects and which also return handles.  This includes but is not
+limited to the following functions:  The functions @code{plot} and @code{plot3}
+return a handle pointing to an object of type @code{line}.  The function
+@code{subplot} returns a handle pointing to an object of type @code{axes}.
+The functions @code{fill}, @code{trimesh}, and @code{trisurf} return a handle
+pointing to an object of type patch.  The function @code{scatter3} returns a
+handle to an object of type scatter.  The functions @code{slice}, @code{surf},
+@code{surfl}, @code{mesh}, @code{meshz}, @code{pcolor}, and @code{waterfall}
+each return a handle of type surface.  The function @code{camlight} returns a
+handle to an object of type light.  The functions @code{area}, @code{bar},
+@code{barh}, @code{contour}, @code{contourf}, @code{contour3}, @code{surfc},
+@code{meshc}, @code{errorbar}, @code{quiver}, @code{quiver3}, @code{stair},
+@code{stem}, @code{stem3} each return a handle to a complex data structure as
+documented in @ref{XREFdatasources,,Data Sources}.
 
 The graphics objects are arranged in a hierarchy:
 
@@ -1199,8 +1207,12 @@
 
 3. Below the @code{figure} objects are @code{axes} or @code{hggroup} objects.
 
-4. Below the @code{axes} objects are @code{line}, @code{text}, @code{patch},
-@code{surface}, @code{image}, and @code{light} objects.
+4. Below the @code{axes} or @code{hggroup} objects are @code{line},
+@code{text}, @code{patch}, @code{scatter}, @code{surface}, @code{image}, and
+@code{light} objects.
+
+It is possible to walk this hierarchical tree by querying the @qcode{"parent"}
+and @qcode{"children"} properties of the graphics objects.
 
 Graphics handles may be distinguished from function handles
 (@pxref{Function Handles}) by means of the function @code{ishghandle}.
@@ -1489,6 +1501,7 @@
 * Text Properties::
 * Image Properties::
 * Patch Properties::
+* Scatter Properties::
 * Surface Properties::
 * Light Properties::
 * Uimenu Properties::
@@ -1563,6 +1576,13 @@
 @include plot-patchproperties.texi
 
 
+@node Scatter Properties
+@subsubsection Scatter Properties
+@prindex @sortas{@ Scatter Properties} Scatter Properties
+
+@include plot-scatterproperties.texi
+
+
 @node Surface Properties
 @subsubsection Surface Properties
 @prindex @sortas{@ Surface Properties} Surface Properties
@@ -2119,7 +2139,6 @@
 * Error Bar Series::
 * Line Series::
 * Quiver Group::
-* Scatter Group::
 * Stair Group::
 * Stem Series::
 * Surface Group::
@@ -2445,46 +2464,6 @@
 Data source variables.
 @end table
 
-@node Scatter Group
-@subsubsection Scatter Group
-@cindex group objects
-@cindex scatter group
-
-Scatter series objects are created by the @code{scatter} or @code{scatter3}
-functions.  A single hggroup element contains as many children as there are
-points in the scatter plot, with each child representing one of the points.
-The properties of the stem series are
-
-@table @code
-@item linewidth
-The line width of the line objects of the points.  @xref{Line Styles}.
-
-@item  marker
-@itemx markeredgecolor
-@itemx markerfacecolor
-The line and fill color of the markers of the points.  @xref{Colors}.
-
-@item  xdata
-@itemx ydata
-@itemx zdata
-The original x, y and z data of the stems.
-
-@item cdata
-The color data for the points of the plot.  Each point can have a separate
-color, or a unique color can be specified.
-
-@item sizedata
-The size data for the points of the plot.  Each point can its own size or a
-unique size can be specified.
-
-@item  xdatasource
-@itemx ydatasource
-@itemx zdatasource
-@itemx cdatasource
-@itemx sizedatasource
-Data source variables.
-@end table
-
 @node Stair Group
 @subsubsection Stair Group
 @cindex group objects
--- a/doc/interpreter/strings.txi	Tue Jul 07 18:34:23 2020 -0400
+++ b/doc/interpreter/strings.txi	Tue Jul 07 19:40:20 2020 -0400
@@ -416,6 +416,10 @@
 
 @DOCSTRING(strncmpi)
 
+@DOCSTRING(startsWith)
+
+@DOCSTRING(endsWith)
+
 @node Manipulating Strings
 @section Manipulating Strings
 
--- a/doc/interpreter/system.txi	Tue Jul 07 18:34:23 2020 -0400
+++ b/doc/interpreter/system.txi	Tue Jul 07 19:40:20 2020 -0400
@@ -554,6 +554,8 @@
 
 @DOCSTRING(license)
 
+@DOCSTRING(memory)
+
 @DOCSTRING(getrusage)
 
 @DOCSTRING(winqueryreg)
--- a/etc/GNULIB.UPDATE	Tue Jul 07 18:34:23 2020 -0400
+++ b/etc/GNULIB.UPDATE	Tue Jul 07 19:40:20 2020 -0400
@@ -1,39 +1,13 @@
 ## Instructions for updating gnulib on development branch
 
-## Change directory to the local Octave repositoy and clone the gnulib git
-## repository:
-git clone git://git.savannah.gnu.org/gnulib.git gnulib-git
-
-## Convert to hg (might take some time):
-hg --config extensions.convert= convert ./gnulib-git ./gnulib-hg
+## "cd" to a directory where you want to clone the gnulib repository and run:
+git clone git://git.savannah.gnu.org/gnulib.git
 
-## Change directory to the gnulib sub-repo in Octave and execute the following
-## commands:
-cd ./gnulib
-hg pull default
-hg update
-hg log -rtip --template "{node}\n"
-
-## Take note of the SHA-1 hash (LAST_OLD_HASH) of that revision.
+## If you already have a local gnulib git repository, pull the latest changes:
+git pull
 
-## Locate the first new revision in the converted repository and replace it in
-## the following command:
-cd ../gnulib-hg
-hg log -r20111 --template "{node}\n"
-
-## Take note of the SHA-1 hash (FIRST_NEW_HASH) of that revision.
+## Query the commit id of the current head:
+git rev-parse HEAD
 
-## Change to the main directory of the local Octave repository and execute the
-## following command replacing the hashes with the information just gathered:
-cd ..
-echo FIRST_NEW_HASH LAST_OLD_HASH > splicemap
-
-## Execute the following command (having replaced FIRST_NEW_HASH):
-hg --config extensions.convert= convert ./gnulib-hg ./gnulib --splicemap ./splicemap --config convert.hg.startrev=FIRST_NEW_HASH
-
-## In the Octave repository do the following:
-cd gnulib
-hg update
-cd ..
-hg commit -m "maint: update gnulib subrepo."
-hg push default -r . 
+## Locate the line in bootstrap.conf starting with ": ${GNULIB_REVISION=" and
+## replace the git commit id with the new one.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/etc/NEWS.6	Tue Jul 07 19:40:20 2020 -0400
@@ -0,0 +1,307 @@
+Summary of important user-visible changes for version 6 (yyyy-mm-dd):
+----------------------------------------------------------------------
+
+### General improvements
+
+- The `intersect`, `setdiff`, `setxor`, `union`, and `unique` functions
+  accept a new sorting option `"stable"` which will return output values
+  in the same order as the input, rather than in ascending order.
+
+- Complex RESTful web services can now be accessed by the `webread` and
+  `webwrite` functions alongside with the `weboptions` structure.  One
+  major feature is the support for cookies to enable RESTful
+  communication with the web service.
+
+  Additionally, the system web browser can be opened by the `web` function.
+
+- The `linspace` function now produces symmetrical sequences when the
+  endpoints are symmetric.  This is more intuitive and also compatible
+  with recent changes made in Matlab R2019b.
+
+- The underlying algorithm of the `rand` function has been changed.
+  For single precision outputs, the algorithm has been fixed so that it
+  produces values strictly in the range (0, 1).  Previously, it could
+  occasionally generate the right endpoint value of 1 (See bug #41742).
+  In addition, the new implementation uses a uniform interval between
+  floating point values in the range (0, 1) rather than targeting a
+  uniform density (# of random integers / length along real number
+  line).
+
+- Numerical integration has been improved.  The `quadv` function has
+  been re-written so that it can compute integrands of periodic
+  functions.  At the same time, performance is better with ~3.5X fewer
+  function evaluations required.  A bug in `quadgk` that caused complex
+  path integrals specified with `"Waypoints"` to occasionally be
+  calculated in the opposite direction was fixed.
+
+- The `edit` function option `"editinplace"` now defaults to `true` and
+  the option `"home"` now defaults to the empty matrix `[]`.  Files will
+  no longer be copied to the user's HOME directory for editing.  The old
+  behavior can be restored by setting `"editinplace"` to `false` and
+  `"home"` to `"~/octave"`.
+
+- The `format` command supports two new options: `uppercase` and
+  `lowercase` (default).  With the default, print a lowercase 'e' for
+  the exponent character in scientific notation and lowercase 'a-f' for
+  the hex digits representing 10-15.  With `uppercase`, print 'E' and
+  'A-F' instead.  The previous uppercase formats, `E` and `G`, no longer
+  control the case of the output.
+
+  Additionally, the `format` command can be called with multiple options
+  for controlling the format, spacing, and case in arbitrary order.
+  For example:
+
+        format long e uppercase loose
+
+  Note, in the case of multiple competing format options the rightmost
+  one is used, and, in case of an error, the previous format remains
+  unchanged.
+
+- L-value references (e.g., increment (++), decrement (--), and all
+  in-place assignment operators (+=, -=, *=, /=, etc.)) are no longer
+  allowed in anonymous functions.
+
+- New warnings have been added about questionable uses of the colon ':'
+  range operator.  Each has a new warning ID so that it can be disabled
+  if desired.
+
+  >  `Octave:colon-complex-argument`   : when any arg is complex  
+  >  `Octave:colon-nonscalar-argument` : when any arg is non-scalar
+
+- The `regexp` and related functions now correctly handle and *require*
+  strings in UTF-8 encoding.  As with any other function that requires
+  strings to be encoded in Octave's native encoding, you can use
+  `native2unicode` to convert from your preferred locale.  For example,
+  the copyright symbol in UTF-8 is `native2unicode (169, "latin1")`.
+
+- The startup file `octaverc` now can be located in the platform
+  dependent location for user local configuration files (e.g.
+  ${XDG_CONFIG_HOME}/octave/octaverc on Unix-like operating systems or
+  %APPDATA%\octave\octaverc on Windows).
+
+- `pkg describe` now lists dependencies and inverse dependencies
+  (i.e., other installed packages that depend on the package in
+  question).
+
+- When unloading a package, `pkg` now checks if any remaining loaded
+  packages depend on the one to be removed.  If this is the case `pkg`
+  aborts with an explanatory error message.  This behavior can be
+  overridden with the `-nodeps` option.
+
+- The command
+
+    dbstop in CLASS at METHOD
+
+  now works to set breakpoints in classdef constructors and methods.
+
+#### Graphics backend
+
+- The use of Qt4 for graphics and the GUI is deprecated in Octave
+  version 6 and no further bug fixes will be made.  Qt4 support will be
+  removed completely in Octave version 7.
+
+- The `legend` function has been entirely rewritten.  This fixes a
+  number of historical bugs, but also implements new properties such as
+  `"AutoUpdate"` and `"NumColumns"`.  The gnuplot toolkit---which is no
+  longer actively maintained---still uses the old legend function.
+
+- The `axis` function was updated which resolved 10 bugs affecting
+  axes to which `"equal"` had been applied.
+
+- Graphic primitives now accept a color property value of `"none"`
+  which is useful when a particular primitive needs to be hidden
+  (for example, the Y-axis of an axes object with `"ycolor" = "none"`)
+  without hiding the entire primitive `"visibility" = "off"`.
+
+- A new property `"FontSmoothing"` has been added to text and axes
+  objects that controls whether anti-aliasing is used during the
+  rendering of characters.  The default is `"on"` which produces smooth,
+  more visually appealing text.
+
+- The figure property `"windowscrollwheelfcn"`is now implemented.
+  This makes it possible to provide a callback function to be executed
+  when users manipulate the mouse wheel on a given figure.
+
+- The figure properties `"pointer"`, `"pointershapecdata"`, and
+  `"pointershapehotspot"` are now implemented.  This makes it possible
+  to change the shape of the cursor (pointer in Matlab-speak) displayed
+  in a plot window.
+
+- The figure property `"paperpositionmode"` now has the default `"auto"`
+  rather than `"manual"`.  This change is more intuitive and is
+  Matlab compatible.
+
+- The appearance of patterned lines `"LineStyle" = ":"|"--"|"-."` has
+  been improved for small widths (`"LineWidth"` less than 1.5 pixels)
+  which is a common scenario.
+
+- Printing to EPS files now uses a tight bounding box (`"-tight"`
+  argument to print) by default.  This makes more sense for EPS
+  files which are normally embedded within other documents, and is
+  Matlab compatible.  If necessary use the `"-loose"` option to
+  reproduce figures as they appeared in previous versions of Octave.
+
+- The following print devices are no longer officially supported: cdr,
+  corel, aifm, ill, cgm, hpgl, mf and dxf.  A warning will be thrown
+  when using those devices, and the code for supporting those formats
+  will eventually be removed from a future version of Octave.
+
+- The placement of text subscripts and superscripts has been
+re-engineered and now produces visually attractive results similar to
+Latex.
+
+### Matlab compatibility
+
+- The function `unique` now returns column index vectors for the second
+  and third outputs.  When duplicate values are present, the default
+  index to return is now the `"first"` occurrence.  The previous Octave
+  behavior, or Matlab behavior from releases prior to R2012b, can be
+  obtained by using the `"legacy"` flag.
+
+- The function `setdiff` with the `"rows"` argument now returns Matlab
+  compatible results.  The previous Octave behavior, or Matlab behavior
+  from releases prior to R2012b, can be obtained by using the `"legacy"`
+  flag.
+
+- The functions `intersect`, `setxor`, and `union` now accept a
+  `"legacy"` flag which changes the index values (second and third
+  outputs) as well as the orientation of all outputs to match Matlab
+  releases prior to R2012b.
+
+- The function `streamtube` is Matlab compatible and plots tubes along
+  streamlines which are scaled by the vector field divergence. The
+  Octave-only extension `ostreamtube` can be used to visualize the flow
+  expansion and contraction of the vector field due to the local
+  crossflow divergence.
+
+- The interpreter now supports handles to nested functions.
+
+- The graphics properties `"LineWidth"` and `"MarkerSize"` are now
+  measured in points, *not* pixels.  Compared to previous versions
+  of Octave, some lines and markers will appear 4/3 larger.
+
+- The meta.class property "SuperClassList" has been renamed
+  "Superclasslist" for Matlab compatibility.  The original name will
+  exist as an alias until Octave version 8.1.
+
+- The function `javaaddpath` now prepends new directories to the
+  existing dynamic classpath by default.  To append them instead, use
+  the new `"-end"` argument.  Multiple directories may now be specified
+  in a cell array of strings.
+
+- An undocumented function `gui_mainfcn` has been added, for compatibility
+  with figures created with Matlab's GUIDE.
+
+- Several validator functions of type `mustBe*` have been added.  See
+  the list of new functions below.
+
+### Alphabetical list of new functions added in Octave 6
+
+* `commandhistory`
+* `commandwindow`
+* `filebrowser`
+* `is_same_file`
+* `lightangle`
+* `mustBeFinite`
+* `mustBeGreaterThan`
+* `mustBeGreaterThanOrEqual`
+* `mustBeInteger`
+* `mustBeLessThan`
+* `mustBeLessThanOrEqual`
+* `mustBeMember`
+* `mustBeNegative`
+* `mustBeNonempty`
+* `mustBeNonNan`
+* `mustBeNonnegative`
+* `mustBeNonpositive`
+* `mustBeNonsparse`
+* `mustBeNonzero`
+* `mustBeNumeric`
+* `mustBeNumericOrLogical`
+* `mustBePositive`
+* `mustBeReal`
+* `namedargs2cell`
+* `newline`
+* `ode23s`
+* `ostreamtube`
+* `rescale`
+* `rotx`
+* `roty`
+* `rotz`
+* `stream2`
+* `stream3`
+* `streamline`
+* `streamtube`
+* `uisetfont`
+* `verLessThan`
+* `web`
+* `weboptions`
+* `webread`
+* `webwrite`
+* `workspace`
+
+
+### Deprecated functions and properties
+
+The following functions and properties have been deprecated in Octave 6
+and will be removed from Octave 8 (or whatever version is the second
+major release after 6):
+
+- Functions
+
+  Function               | Replacement
+  -----------------------|------------------
+  `runtests`             | `oruntests`
+
+- Properties
+
+  Object           | Property      | Value
+  -----------------|---------------|------------
+                   |               |
+
+
+### Removed functions and properties
+
+The following functions and properties were deprecated in Octave 4.4
+and have been removed from Octave 6.
+
+- Functions
+
+  Function             | Replacement
+  ---------------------|------------------
+  `chop`               | `sprintf` for visual results
+  `desktop`            | `isguirunning`
+  `tmpnam`             | `tempname`
+  `toascii`            | `double`
+  `java2mat`           | `__java2mat__`
+
+- Properties
+
+  Object               | Property                  | Value
+  ---------------------|---------------------------|-----------------------
+  `annotation`         | `edgecolor ("rectangle")` |
+  `axes`               | `drawmode`                |
+  `figure`             | `doublebuffer`            |
+                       | `mincolormap`             |
+                       | `wvisual`                 |
+                       | `wvisualmode`             |
+                       | `xdisplay`                |
+                       | `xvisual`                 |
+                       | `xvisualmode`             |
+  `line`               | `interpreter`             |
+  `patch`              | `interpreter`             |
+  `surface`            | `interpreter`             |
+  `text`               | `fontweight`              | `"demi"` and `"light"`
+  `uibuttongroup`      | `fontweight`              | `"demi"` and `"light"`
+  `uicontrol`          | `fontweight`              | `"demi"` and `"light"`
+  `uipanel`            | `fontweight`              | `"demi"` and `"light"`
+  `uitable`            | `fontweight`              | `"demi"` and `"light"`
+
+
+### Old release news
+
+- [Octave 5.x](etc/NEWS.5)
+- [Octave 4.x](etc/NEWS.4)
+- [Octave 3.x](etc/NEWS.3)
+- [Octave 2.x](etc/NEWS.2)
+- [Octave 1.x](etc/NEWS.1)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/module.mk	Tue Jul 07 19:40:20 2020 -0400
@@ -0,0 +1,75 @@
+%canon_reldir%_EXTRA_DIST =
+
+%canon_reldir%_CLEANFILES =
+%canon_reldir%_DISTCLEANFILES =
+%canon_reldir%_MAINTAINERCLEANFILES =
+
+%canon_reldir%_SRC = \
+  %reldir%/@FIRfilter/FIRfilter.m \
+  %reldir%/@FIRfilter/FIRfilter_aggregation.m \
+  %reldir%/@FIRfilter/display.m \
+  %reldir%/@FIRfilter/subsasgn.m \
+  %reldir%/@FIRfilter/subsref.m \
+  %reldir%/@polynomial/disp.m \
+  %reldir%/@polynomial/double.m \
+  %reldir%/@polynomial/end.m \
+  %reldir%/@polynomial/get.m \
+  %reldir%/@polynomial/mtimes.m \
+  %reldir%/@polynomial/numel.m \
+  %reldir%/@polynomial/plot.m \
+  %reldir%/@polynomial/polynomial.m \
+  %reldir%/@polynomial/polynomial_superiorto.m \
+  %reldir%/@polynomial/polyval.m \
+  %reldir%/@polynomial/roots.m \
+  %reldir%/@polynomial/set.m \
+  %reldir%/@polynomial/subsasgn.m \
+  %reldir%/@polynomial/subsref.m \
+  %reldir%/addtwomatrices.cc \
+  %reldir%/celldemo.cc \
+  %reldir%/embedded.cc \
+  %reldir%/fortrandemo.cc \
+  %reldir%/fortransub.f \
+  %reldir%/funcdemo.cc \
+  %reldir%/globaldemo.cc \
+  %reldir%/helloworld.cc \
+  %reldir%/make_int.cc \
+  %reldir%/mex_demo.c \
+  %reldir%/mycell.c \
+  %reldir%/myfeval.c \
+  %reldir%/myfevalf.f \
+  %reldir%/myfunc.c \
+  %reldir%/myhello.c \
+  %reldir%/mypow2.c \
+  %reldir%/myprop.c \
+  %reldir%/myset.c \
+  %reldir%/mysparse.c \
+  %reldir%/mystring.c \
+  %reldir%/mystruct.c \
+  %reldir%/oct_demo.cc \
+  %reldir%/oregonator.cc \
+  %reldir%/oregonator.m \
+  %reldir%/paramdemo.cc \
+  %reldir%/polynomial2.m \
+  %reldir%/standalone.cc \
+  %reldir%/standalonebuiltin.cc \
+  %reldir%/stringdemo.cc \
+  %reldir%/structdemo.cc \
+  %reldir%/unwinddemo.cc
+
+%canon_reldir%_EXTRA_DIST += \
+  $(%canon_reldir%_SRC)
+
+EXTRA_DIST += $(%canon_reldir%_EXTRA_DIST)
+
+CLEANFILES += $(%canon_reldir%_CLEANFILES)
+DISTCLEANFILES += $(%canon_reldir%_DISTCLEANFILES)
+MAINTAINERCLEANFILES += $(%canon_reldir%_MAINTAINERCLEANFILES)
+
+examples-clean:
+	rm -f $(%canon_reldir%_CLEANFILES)
+
+examples-distclean: examples-clean
+	rm -f $(%canon_reldir%_DISTCLEANFILES)
+
+examples-maintainer-clean: examples-distclean
+	rm -f $(%canon_reldir%_MAINTAINERCLEANFILES)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/data/README	Tue Jul 07 19:40:20 2020 -0400
@@ -0,0 +1,51 @@
+* penny data file:
+
+  See the discussion here:
+  https://savannah.gnu.org/patch/?func=detailitem&item_id=8472
+
+* west0479 data file:
+
+  Chemical engineering plant models Eight stage column section, all
+  rigorous from set CHEMWEST, from the Harwell-Boeing Collection.
+
+  west0479.mtx: original file obtained from from
+  https://math.nist.gov/MatrixMarket/data/Harwell-Boeing/chemwest/west0479.html
+
+  west0479.mat: generated from west0479.mtx as follows:
+
+    x = load ("west0479.mtx");
+    nr = x(1,1);
+    nc = x(1,2);
+    i = x(2:end,1);
+    j = x(2:end,2);
+    sv = x(2:end,3);
+    west0479 = sparse(i, j, sv, nr, nc);
+    save -text west0479.mat west0479
+
+  Note that the original file has 1910 entries but 22 of them are exact
+  zeros:
+
+    384 86  0.0000000000000e+00
+    360 116  0.0000000000000e+00
+    361 117  0.0000000000000e+00
+    362 118  0.0000000000000e+00
+    238 224  0.0000000000000e+00
+    239 225  0.0000000000000e+00
+    240 226  0.0000000000000e+00
+    250 240  0.0000000000000e+00
+    251 241  0.0000000000000e+00
+    252 242  0.0000000000000e+00
+    272 259  0.0000000000000e+00
+    273 260  0.0000000000000e+00
+    274 261  0.0000000000000e+00
+    294 278  0.0000000000000e+00
+    295 279  0.0000000000000e+00
+    296 280  0.0000000000000e+00
+    316 297  0.0000000000000e+00
+    317 298  0.0000000000000e+00
+    318 299  0.0000000000000e+00
+    338 316  0.0000000000000e+00
+    339 317  0.0000000000000e+00
+    340 318  0.0000000000000e+00
+
+  These are not explicitly included in the west0479.mat file.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/data/module.mk	Tue Jul 07 19:40:20 2020 -0400
@@ -0,0 +1,15 @@
+%canon_reldir%_EXTRA_DIST =
+
+%canon_reldir%_DAT = \
+  %reldir%/penny.mat \
+  %reldir%/west0479.mat
+
+%canon_reldir%_EXTRA_DIST += \
+  $(%canon_reldir%_DAT) \
+  %reldir%/README \
+  %reldir%/west0479.mtx
+
+octdata_DATA += \
+  $(%canon_reldir%_DAT)
+
+EXTRA_DIST += $(%canon_reldir%_EXTRA_DIST)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/data/west0479.mat	Tue Jul 07 19:40:20 2020 -0400
@@ -0,0 +1,1896 @@
+# Created by Octave 5.2.0, Thu Jun 04 22:49:15 2020 EDT <jwe@devnull>
+# name: west0479
+# type: sparse matrix
+# nnz: 1888
+# rows: 479
+# columns: 479
+25 1 1
+31 1 -0.037648130000000002
+87 1 -0.34423959999999998
+26 2 1
+31 2 -0.024522619999999998
+88 2 -0.3737086
+27 3 1
+31 3 -0.036613039999999999
+89 3 -0.83693790000000001
+28 4 130
+29 4 -2.433767
+29 5 1
+30 5 -1.6140909999999999
+30 6 1.6140909999999999
+31 6 -0.21873210000000001
+87 6 -1
+88 6 -1
+89 6 -1
+32 7 -1.138352
+43 7 0.036694280000000003
+111 7 0.099316360000000006
+112 7 0.099316360000000006
+113 7 0.099316360000000006
+33 8 -0.5
+43 8 0.016117289999999999
+111 8 0.087245760000000006
+34 9 -0.36119180000000001
+43 9 0.01164286
+112 9 0.1050415
+35 10 -0.3218876
+43 10 0.01037591
+113 10 0.1404166
+36 11 -0.43624160000000001
+37 11 -0.76804249999999996
+38 11 -0.14302790000000001
+39 11 -0.15938859999999999
+37 12 1
+43 12 -0.048560819999999998
+111 12 -0.2628684
+38 13 1
+43 13 -0.030925950000000001
+112 13 -0.27901280000000001
+39 14 1
+43 14 -0.046123589999999999
+113 14 -0.62418819999999997
+40 15 5.2824359999999997
+42 15 -0.61239209999999999
+41 16 0.2886822
+42 16 -0.2163815
+42 17 1.3287739999999999
+43 17 -0.36946859999999998
+111 17 -1
+112 17 -1
+113 17 -1
+2 18 48.176470000000002
+8 18 -1
+11 18 -3.3474840000000003e-05
+3 19 83.5
+9 19 -1
+12 19 -4.1365390000000001e-05
+4 20 171.94120000000001
+10 20 -1
+13 20 -8.4843450000000005e-05
+5 21 96.651380000000003
+8 21 2.5
+11 21 3.3474840000000003e-05
+6 22 168.2706
+9 22 2.5
+12 22 4.1365390000000001e-05
+7 23 347.5872
+10 23 2.5
+13 23 8.4843450000000005e-05
+8 24 1
+17 24 -0.1106967
+27 24 1.605232
+9 25 1
+17 25 -0.089808520000000003
+10 26 1
+17 26 -0.15173690000000001
+11 27 1.0104550000000001
+18 27 -0.5
+12 28 1.005978
+18 28 -0.29999999999999999
+13 29 1.002885
+18 29 -0.20000000000000001
+14 30 1
+17 30 -0.1811855
+15 31 1
+17 31 -0.24002390000000001
+16 32 1
+17 32 -0.22654840000000001
+17 33 1
+19 33 -1
+30 33 1.5
+42 33 0.5
+18 34 1
+20 34 -316220
+23 34 -12323.690000000001
+24 34 -1
+30 34 -35226.800000000003
+41 34 18449.02
+19 35 5.2983390000000004
+21 35 0.0024526869999999998
+20 36 1080.8589999999999
+21 36 -0.2050215
+21 37 0.14419199999999999
+22 37 63.05986
+30 37 -0.1159299
+22 38 -18449.02
+24 38 0.84533389999999997
+40 38 -18449.02
+41 38 -15595.58
+23 39 1
+30 39 0.20204929999999999
+42 39 -0.88547100000000001
+24 40 0.0001000234
+30 40 2.4483389999999998
+42 40 0.81611299999999998
+68 41 1
+74 41 -0.0002278669
+99 41 -0.26243949999999999
+69 42 1
+74 42 -0.00041887629999999999
+100 42 -0.32161960000000001
+70 43 1
+74 43 -0.001576933
+101 43 -0.72647609999999996
+71 44 300
+72 44 -2.8518910000000002
+72 45 1
+73 45 -0.28701589999999999
+73 46 0.28701589999999999
+74 46 -0.0043413219999999999
+99 46 -1
+100 46 -1
+101 46 -1
+75 47 -1.138352
+86 47 0.042002860000000003
+123 47 0.9414806
+124 47 0.9414806
+125 47 0.9414806
+76 48 -0.3218876
+86 48 0.011877
+123 48 1.3310949999999999
+77 49 -0.36119180000000001
+86 49 0.013327240000000001
+124 49 0.99575290000000005
+78 50 -0.5
+86 50 0.01844898
+125 50 0.82705600000000001
+79 51 -1
+80 51 -19.239999999999998
+81 51 -3.8029999999999999
+82 51 -9.4809999999999999
+80 52 1
+86 52 -0.00088757840000000001
+123 52 -0.099473919999999993
+81 53 1
+86 53 -0.0013313680000000001
+124 53 -0.099473919999999993
+82 54 1
+86 54 -0.0022189459999999999
+125 54 -0.099473919999999993
+83 55 1.177613
+85 55 -3.1089630000000001
+84 56 0.99194249999999995
+85 56 -2.640056
+85 57 3.1921119999999998
+86 57 -0.044613630000000001
+123 57 -1
+124 57 -1
+125 57 -1
+45 58 109.86879999999999
+51 58 -1
+54 58 -3.3081099999999997e-05
+46 59 191.38460000000001
+52 59 -1
+55 59 -4.1084670000000001e-05
+47 60 395.4796
+53 60 -1
+56 60 -8.456383e-05
+48 61 221.73390000000001
+51 61 2.5
+54 61 3.3081099999999997e-05
+49 62 387.00920000000002
+52 62 2.5
+55 62 4.1084670000000001e-05
+50 63 800.81650000000002
+53 63 2.5
+56 63 8.456383e-05
+51 64 1
+60 64 -0.0091702290000000002
+52 65 1
+60 65 -0.046441099999999999
+53 66 1
+60 66 -0.48999189999999998
+54 67 1.0045299999999999
+61 67 -0.20000000000000001
+55 68 1.002591
+61 68 -0.29999999999999999
+56 69 1.00125
+61 69 -0.5
+57 70 1
+60 70 -0.037500529999999997
+58 71 1
+60 71 -0.124143
+59 72 1
+60 72 -0.29275319999999999
+60 73 1
+62 73 -1
+73 73 0.18537329999999999
+85 73 0.06179109
+61 74 1
+63 74 -316220
+66 74 -16364.190000000001
+67 74 -1
+73 74 -4696.7820000000002
+84 74 131.85400000000001
+62 75 22.12913
+64 75 0.95375259999999995
+63 76 2494.29
+64 76 -1.021587
+64 77 0.88782810000000001
+65 77 1.0400419999999999
+73 77 -2.640056
+65 78 -131.85400000000001
+67 78 0.0080574700000000006
+83 78 -131.85400000000001
+84 78 -1.0624089999999999
+66 79 1
+73 79 0.1016426
+85 79 -0.06179109
+67 80 0.0076452569999999999
+73 80 23.098949999999999
+85 80 7.699649
+31 81 1
+244 81 1
+43 82 1
+1 83 1
+17 83 -3.850231
+18 83 -8.4599350000000005e-05
+31 83 2.0159099999999999
+35 83 1
+43 83 1.596171
+243 83 -0.78975119999999999
+74 84 1
+388 84 0.88175619999999999
+86 85 1
+44 86 1
+60 86 -2.7937599999999998
+61 86 -8.4458229999999999e-05
+74 86 2.0156649999999998
+78 86 1
+86 86 1.5939939999999999
+387 86 -0.96191499999999996
+385 87 0.002424669
+386 87 0.030362779999999999
+387 87 0.67304509999999995
+388 87 1.45936
+96 88 0.016896609999999999
+97 88 0.034848030000000002
+98 88 -0.060080179999999997
+120 88 -0.55527170000000003
+121 88 -0.47703980000000001
+122 88 -0.1858293
+141 88 -1
+142 88 -1
+143 88 -1
+185 88 -55.188569999999999
+186 88 -95.676860000000005
+187 88 -215.83770000000001
+389 88 1
+438 88 1
+439 88 1
+440 88 1
+441 88 1
+442 88 1
+443 88 1
+450 88 -0.0018907559999999999
+451 88 -0.0015311400000000001
+452 88 -0.001013726
+455 88 2.5
+456 88 26.063700000000001
+458 88 1
+459 88 -1.5
+461 88 -9.6031809999999993
+462 88 -9.4541850000000007
+463 88 -9.4376809999999995
+464 88 -48.295720000000003
+472 88 0.90759219999999996
+473 88 -4.3759670000000002
+474 88 -8.997992
+475 88 -8.8819579999999991
+476 88 1
+182 89 1
+183 89 1
+184 89 1
+391 89 1
+455 89 -1
+456 89 -26.063700000000001
+458 89 -1
+468 89 1
+388 90 -1.45936
+467 90 1
+479 91 1
+203 92 -1
+204 92 -1
+205 92 -1
+209 92 1
+210 92 1
+211 92 1
+382 92 56.953099999999999
+385 92 0.70583249999999997
+437 92 1
+453 92 -0.64913719999999997
+454 92 -3.2948409999999999e-05
+467 92 0.53807479999999996
+469 92 1
+479 92 0.082471119999999995
+203 93 -1
+204 93 -1
+205 93 -1
+209 93 1
+210 93 1
+211 93 1
+383 93 11.58384
+386 93 0.70583249999999997
+437 93 1
+453 93 -1.021542
+454 93 -4.0990330000000002e-05
+467 93 -0.36302479999999998
+470 93 1
+479 93 0.069522609999999999
+203 94 -1
+204 94 -1
+205 94 -1
+209 94 1
+210 94 1
+211 94 1
+384 94 0.3209631
+387 94 0.70583249999999997
+437 94 1
+453 94 -2.049007
+454 94 -8.4470029999999998e-05
+467 94 0.91353620000000002
+471 94 1
+479 94 0.83976379999999995
+241 95 0.55083519999999997
+242 95 0.4489223
+243 95 0.0002425203
+244 95 0.40528330000000001
+108 96 -0.067276619999999995
+109 96 -0.15700610000000001
+110 96 -0.097475699999999998
+132 96 -0.25060070000000001
+133 96 -0.2802617
+134 96 0.1008491
+245 96 -1
+395 96 1
+396 96 1
+397 96 1
+398 96 1
+399 96 1
+400 96 1
+407 96 -0.0028636019999999998
+408 96 -0.0023162590000000002
+409 96 -0.00153089
+412 96 2.5
+413 96 11.5878
+415 96 1
+416 96 -1.101224
+418 96 -1.3644320000000001
+419 96 -1.2188209999999999
+420 96 -1.2108589999999999
+421 96 -34.621049999999997
+429 96 0.60313589999999995
+430 96 -0.59963840000000002
+431 96 -1.403392
+432 96 -1.3703860000000001
+433 96 1
+246 97 1
+412 97 -1
+413 97 -11.5878
+415 97 -1
+425 97 1
+244 98 -0.40528330000000001
+424 98 1
+436 99 1
+160 100 -0.85938400000000004
+161 100 -0.773339
+162 100 -0.79517400000000005
+238 100 -1
+241 100 1
+394 100 1
+410 100 -1.623659
+411 100 -3.3032779999999999e-05
+424 100 3.5720350000000001
+426 100 1
+436 100 0.92435319999999999
+160 101 -1.171821
+161 101 -1.277352
+162 101 -1.250508
+239 101 -1
+242 101 1
+394 101 1
+410 101 -2.4602889999999999
+411 101 -4.1050809999999997e-05
+424 101 -2.1785329999999998
+427 101 1
+436 101 0.65098420000000001
+160 102 -2.3280470000000002
+161 102 -2.4161549999999998
+162 102 -2.5121660000000001
+240 102 -1
+243 102 1
+394 102 1
+410 102 -4.7536199999999997
+411 102 -8.45305e-05
+424 102 6.1671399999999998
+428 102 1
+436 102 3.3966910000000001
+241 103 0.043736570000000002
+242 103 0.57396460000000005
+243 103 0.15834899999999999
+244 103 0.18781249999999999
+253 103 -0.044344130000000002
+254 103 -0.58193779999999995
+255 103 -0.16054869999999999
+256 103 -1
+135 104 -1
+136 104 -1
+137 104 -1
+151 104 -62.680900000000001
+152 104 -123.89
+153 104 -464.35550000000001
+245 104 1
+248 104 -0.051646549999999999
+249 104 -0.32417620000000003
+148 105 1
+149 105 1
+150 105 1
+247 105 1
+244 106 -0.18781249999999999
+248 106 1
+256 106 1
+249 107 1
+147 108 1
+169 108 -1
+170 108 -1
+171 108 -1
+175 108 1
+176 108 1
+177 108 1
+238 108 9.7738750000000003
+241 108 0.77605020000000002
+248 108 7.2528309999999996
+249 108 0.78041000000000005
+253 108 -0.78683060000000005
+147 109 1
+169 109 -1
+170 109 -1
+171 109 -1
+175 109 1
+176 109 1
+177 109 1
+239 109 0.60698209999999997
+242 109 0.77605020000000002
+248 109 -2.3895080000000002
+249 109 0.68493979999999999
+254 109 -0.78683060000000005
+147 110 1
+169 110 -1
+170 110 -1
+171 110 -1
+175 110 1
+176 110 1
+177 110 1
+240 110 0.001188564
+243 110 0.77605020000000002
+248 110 11.55883
+249 110 2.2026439999999998
+255 110 -0.78683060000000005
+363 111 -0.17051479999999999
+364 111 -0.43429630000000002
+365 111 -0.26674209999999998
+366 111 -2.609302
+385 111 0.1956447
+386 111 0.49830160000000001
+387 111 0.30605369999999998
+388 111 0.42239599999999999
+215 112 1
+216 112 1
+217 112 1
+218 112 1
+219 112 1
+220 112 1
+227 112 -0.0018907559999999999
+228 112 -0.0015311400000000001
+229 112 -0.001013726
+232 112 2.5
+233 112 16.672409999999999
+235 112 1
+236 112 -1.5
+389 112 -1
+392 112 -0.46212130000000001
+393 112 -0.1234962
+232 113 -1
+233 113 -16.672409999999999
+235 113 -1
+368 113 -1
+369 113 -1
+390 113 1
+366 114 2.609302
+388 114 -0.42239599999999999
+392 114 1
+393 115 1
+181 116 1
+194 116 -0.58697619999999995
+195 116 -0.50651550000000001
+196 116 -0.5139918
+230 116 -1.0366850000000001
+231 116 -3.2948409999999999e-05
+363 116 -0.87155309999999997
+382 116 -1
+385 116 1
+392 116 2.63998
+393 116 0.55742069999999999
+181 117 1
+194 117 -0.80016370000000003
+195 117 -0.83640899999999996
+196 117 -0.8081026
+230 117 -1.6376949999999999
+231 117 -4.0990330000000002e-05
+364 117 -0.87155309999999997
+383 117 -1
+386 117 1
+392 117 -1.7736780000000001
+393 117 0.40754220000000002
+181 118 1
+194 118 -1.5893889999999999
+195 118 -1.5818110000000001
+196 118 -1.6231180000000001
+230 118 -3.205686
+231 118 -8.4470029999999998e-05
+365 118 -0.87155309999999997
+384 118 -1
+387 118 1
+392 118 4.4676090000000004
+393 118 2.2475290000000001
+93 119 -1
+96 119 -1
+248 119 -0.40421560000000001
+262 119 -0.1818777
+284 119 -0.1563455
+306 119 -0.15456990000000001
+328 119 -0.1521778
+350 119 -0.091905799999999996
+372 119 -0.0078705370000000004
+94 120 -1
+97 120 -1
+248 120 -1.8091710000000001
+262 120 -3.1896550000000001
+284 120 -3.3490190000000002
+306 120 -3.358644
+328 120 -3.3085849999999999
+350 120 -1.96787
+372 120 -0.11333559999999999
+95 121 -1
+98 121 -1
+248 121 -2.4566020000000002
+262 121 -4.1011280000000001
+284 121 -4.2908920000000004
+306 121 -4.3026030000000004
+328 121 -4.2541469999999997
+350 121 -2.9523890000000002
+372 121 -1.157365
+93 122 -0.0081214960000000006
+96 122 -0.016896609999999999
+248 122 -0.0045387600000000002
+262 122 -0.00217052
+284 122 -0.0018740689999999999
+306 122 -0.0018533180000000001
+328 122 -0.0018248369999999999
+350 122 -0.001106561
+372 122 -0.0001054494
+94 123 -0.016749989999999999
+97 123 -0.034848030000000002
+248 123 -0.041896919999999997
+262 123 -0.078506679999999995
+284 123 -0.082793510000000001
+306 123 -0.083055320000000002
+328 123 -0.081826380000000004
+350 123 -0.048866050000000001
+372 123 -0.0031317319999999999
+95 124 -0.028878029999999999
+98 124 -0.060080179999999997
+248 124 -0.098082240000000001
+262 124 -0.17402809999999999
+284 124 -0.18288550000000001
+306 124 -0.1834374
+328 124 -0.18139140000000001
+350 124 -0.12639719999999999
+372 124 -0.055136770000000002
+105 125 -1
+108 125 -1
+264 125 -0.76362319999999995
+286 125 -0.5413211
+308 125 -0.52907530000000003
+330 125 -0.52832599999999996
+352 125 -0.52965340000000005
+374 125 -0.59901059999999995
+392 125 -0.57467679999999999
+106 126 -1
+109 126 -1
+264 126 -1.4679789999999999
+286 126 -1.289806
+308 126 -1.279992
+330 126 -1.279385
+352 126 -1.2801739999999999
+374 126 -1.3601430000000001
+392 126 -0.71491899999999997
+107 127 -1
+110 127 -1
+264 127 -0.0043708569999999997
+286 127 -0.0039541009999999998
+308 127 -0.0039318030000000002
+330 127 -0.0039476679999999997
+352 127 -0.0047490229999999998
+374 127 -0.072455389999999995
+392 127 -1.6023639999999999
+105 128 -0.1122933
+108 128 -0.067276619999999995
+264 128 -0.054601370000000003
+286 128 -0.038877219999999997
+308 128 -0.03800866
+330 128 -0.037958989999999998
+352 128 -0.038208859999999997
+374 128 -0.048085490000000002
+392 128 -0.05817862
+106 129 -0.2620633
+109 129 -0.15700610000000001
+264 129 -0.24496080000000001
+286 129 -0.2161806
+308 129 -0.21459739999999999
+330 129 -0.21451909999999999
+352 129 -0.21552299999999999
+374 129 -0.25480999999999998
+392 129 -0.16890749999999999
+107 130 -0.1626995
+110 130 -0.097475699999999998
+264 130 -0.00045281759999999999
+286 130 -0.00041145290000000001
+308 130 -0.00040925029999999999
+330 130 -0.0004109467
+352 130 -0.00049637369999999995
+374 130 -0.0084271850000000002
+392 130 -0.2350352
+117 131 -1
+120 131 -1
+249 131 -0.069702840000000002
+263 131 -0.019243320000000001
+285 131 -0.01583793
+307 131 -0.01561791
+329 131 -0.01558321
+351 131 -0.01471856
+373 131 -0.0057599519999999996
+118 132 -1
+121 132 -1
+249 132 -0.74171359999999997
+263 132 -0.80234939999999999
+285 132 -0.80658470000000004
+307 132 -0.80682860000000001
+329 132 -0.80550310000000003
+351 132 -0.74926979999999999
+373 132 -0.19719700000000001
+119 133 -1
+122 133 -1
+249 133 -0.51275979999999999
+263 133 -0.52522530000000001
+285 133 -0.52614130000000003
+307 133 -0.52622449999999998
+329 133 -0.52730270000000001
+351 133 -0.57231860000000001
+373 133 -1.025242
+117 134 -0.46575929999999999
+120 134 -0.96900310000000001
+249 134 -0.044884880000000002
+263 134 -0.01317012
+285 134 -0.01088739
+307 134 -0.010739240000000001
+329 134 -0.01071655
+351 134 -0.01016303
+373 134 -0.0044257189999999998
+118 135 -0.57440230000000003
+121 135 -1.195033
+249 135 -0.58903419999999995
+263 135 -0.67721739999999997
+285 135 -0.68380180000000002
+307 135 -0.68420530000000002
+329 135 -0.68315610000000004
+351 135 -0.63804399999999994
+373 135 -0.18686159999999999
+119 136 -0.2292285
+122 136 -0.47690549999999998
+249 136 -0.1625065
+263 136 -0.17691419999999999
+285 136 -0.1780062
+307 136 -0.17808560000000001
+329 136 -0.17846999999999999
+351 136 -0.19449250000000001
+373 136 -0.38770260000000001
+129 137 -1
+132 137 -1
+265 137 -0.34272789999999997
+287 137 -0.2911376
+309 137 -0.2876937
+331 137 -0.28748889999999999
+353 137 -0.28823179999999998
+375 137 -0.30269869999999999
+393 137 -0.17507890000000001
+130 138 -1
+133 138 -1
+265 138 -1.0623339999999999
+287 138 -1.118506
+309 138 -1.1222529999999999
+331 138 -1.122512
+353 138 -1.1232850000000001
+375 138 -1.1082339999999999
+393 138 -0.35118640000000001
+131 139 -1
+134 139 -1
+265 139 -0.0023999820000000002
+287 139 -0.00260173
+309 139 -0.0026156270000000001
+331 139 -0.0026280330000000001
+353 139 -0.0031617350000000002
+375 139 -0.044793810000000003
+393 139 -0.59723090000000001
+129 140 -2.0182530000000001
+132 140 -1.209166
+265 140 -0.44044889999999998
+287 140 -0.3758029
+309 140 -0.37146430000000003
+331 140 -0.37124049999999997
+353 140 -0.37371090000000001
+375 140 -0.43672879999999997
+393 140 -0.31856279999999998
+130 141 -2.5626880000000001
+133 141 -1.535345
+265 141 -1.7335130000000001
+287 141 -1.833245
+309 141 -1.839915
+331 141 -1.840541
+353 141 -1.849286
+375 141 -2.0302660000000001
+393 141 -0.81137049999999999
+131 142 -0.92554289999999995
+134 142 -0.55450670000000002
+265 142 -0.0014144089999999999
+287 142 -0.001540086
+309 142 -0.0015487579999999999
+331 142 -0.0015562740000000001
+353 142 -0.001879925
+375 142 -0.029637400000000001
+393 142 -0.49833870000000002
+135 143 -1.4338919999999999
+141 143 -2.1577039999999998
+266 143 -1.523971
+288 143 -1.530708
+310 143 -1.531148
+332 143 -1.5313159999999999
+354 143 -1.537533
+376 143 -1.710928
+136 144 -0.94320599999999999
+142 144 -1.4193260000000001
+267 144 -1.0024599999999999
+289 144 -1.006891
+311 144 -1.0071810000000001
+333 144 -1.0072909999999999
+355 144 -1.0113810000000001
+377 144 -1.1254390000000001
+137 145 -0.59645269999999995
+143 145 -0.89753530000000004
+268 145 -0.63392269999999995
+290 145 -0.63672519999999999
+312 145 -0.63690829999999998
+334 145 -0.63697809999999999
+356 145 -0.63956420000000003
+378 145 -0.71169090000000002
+135 146 -1
+141 146 -1
+266 146 -1
+288 146 -1
+310 146 -1
+332 146 -1
+354 146 -1
+376 146 -1
+136 147 -1
+142 147 -1
+267 147 -1
+289 147 -1
+311 147 -1
+333 147 -1
+355 147 -1
+377 147 -1
+137 148 -1
+143 148 -1
+268 148 -1
+290 148 -1
+312 148 -1
+334 148 -1
+356 148 -1
+378 148 -1
+138 149 -1
+148 149 1
+238 149 0.55083519999999997
+139 150 -1
+149 150 1.6474949999999999
+239 150 0.73959730000000001
+140 151 -1
+150 151 841.35159999999996
+240 151 0.2040448
+144 152 -1
+182 152 1
+382 152 0.1956447
+145 153 -1
+183 153 1
+383 153 0.49830160000000001
+146 154 -1
+184 154 3.1156220000000001
+384 154 0.95354779999999995
+395 155 66.224919999999997
+401 155 -1
+404 155 -3.3282569999999997e-05
+396 156 115.06229999999999
+402 156 -1
+405 156 -4.122831e-05
+397 157 237.33869999999999
+403 157 -1
+406 157 -8.4706899999999994e-05
+398 158 133.245
+401 158 2.5
+404 158 3.3282569999999997e-05
+399 159 232.26390000000001
+402 159 2.5
+405 159 4.122831e-05
+400 160 480.18209999999999
+403 160 2.5
+406 160 8.4706899999999994e-05
+160 161 -0.47337899999999999
+401 161 1
+410 161 -0.2116876
+161 162 -0.57343169999999999
+402 162 1
+410 162 -0.31667149999999999
+162 163 -0.00060925110000000003
+403 163 1
+410 163 -3.511874e-07
+163 164 -4575.0039999999999
+404 164 1.0075620000000001
+411 164 -0.55083519999999997
+164 165 -3681.4160000000002
+405 165 1.004324
+411 165 -0.4489223
+165 166 -1787.818
+406 166 1.002087
+411 166 -0.0002425203
+160 167 -0.52605639999999998
+161 167 -0.42598229999999998
+407 167 1
+410 167 -0.47048839999999997
+160 168 -0.00056459870000000005
+162 168 -0.4380098
+408 168 1
+410 168 -0.00050495930000000002
+161 169 -0.00058596669999999996
+162 169 -0.56138089999999996
+409 169 1
+410 169 -0.00064718760000000001
+163 170 -1
+164 170 -1
+165 170 -1
+410 170 1
+412 170 -1
+423 170 0.061444209999999999
+435 170 0.0204814
+157 171 -1
+163 171 4124.0600000000004
+164 171 4124.0600000000004
+165 171 4124.0600000000004
+411 171 1
+413 171 -316220
+416 171 -20034.240000000002
+417 171 -1
+423 171 -2625.6570000000002
+434 171 222.12899999999999
+412 172 18.737269999999999
+414 172 0.94488159999999999
+413 173 1494.367
+414 173 -1.02078
+158 174 -0.99186010000000002
+163 174 -17.922339999999998
+164 174 -17.922339999999998
+165 174 -17.922339999999998
+414 174 0.86282899999999996
+415 174 1.0497190000000001
+423 174 -0.73414950000000001
+157 175 0.0081398600000000005
+415 175 -222.12899999999999
+417 175 0.0081398600000000005
+433 175 -222.12899999999999
+434 175 -1.8080989999999999
+163 176 -1.0913280000000001
+164 176 -1.629397
+165 176 -1.4448529999999999
+416 176 1
+423 176 0.047364059999999999
+435 176 -0.027898139999999998
+417 177 0.0045385340000000003
+423 177 7.5792400000000004
+435 177 2.5264129999999998
+148 178 -1
+178 178 -1
+149 179 -1
+179 179 -1
+150 180 -1
+180 180 -1
+148 181 1.0266459999999999
+166 181 -1
+149 182 1.0737239999999999
+167 182 -1
+150 183 1.2081470000000001
+168 183 -1
+148 184 -1
+154 184 -1
+149 185 -1
+155 185 -1
+150 186 -1
+156 186 -1
+215 187 99.149730000000005
+221 187 -1
+224 187 -3.311398e-05
+216 188 172.6396
+222 188 -1
+225 188 -4.1108120000000002e-05
+217 189 356.63979999999998
+223 189 -1
+226 189 -8.4587179999999994e-05
+218 190 200.0008
+221 190 2.5
+224 190 3.311398e-05
+219 191 349.00330000000002
+222 191 2.5
+225 191 4.1108120000000002e-05
+220 192 722.06780000000003
+223 192 2.5
+226 192 8.4587179999999994e-05
+194 193 -0.1148388
+221 193 1
+230 193 -0.011645920000000001
+195 194 -0.41678389999999998
+222 194 1
+230 194 -0.17006160000000001
+196 195 -0.49676140000000002
+223 195 1
+230 195 -0.2436893
+197 196 -5276.8620000000001
+224 196 1.0050250000000001
+231 196 -0.1956447
+198 197 -4241.5910000000003
+225 197 1.002874
+231 197 -0.49830160000000001
+199 198 -2058.2939999999999
+226 198 1.001387
+231 198 -0.30605369999999998
+194 199 -0.39872279999999999
+195 199 -0.099097089999999999
+227 199 1
+230 199 -0.080869759999999999
+194 200 -0.48643839999999999
+196 200 -0.1005598
+228 200 1
+230 200 -0.098660410000000004
+195 201 -0.48411900000000002
+196 201 -0.4026788
+229 201 1
+230 201 -0.39507300000000001
+197 202 -1
+198 202 -1
+199 202 -1
+230 202 1
+232 202 -1
+191 203 -1
+197 203 3297.623
+198 203 3297.623
+199 203 3297.623
+231 203 1
+233 203 -316220
+236 203 -18966.66
+237 203 -1
+232 204 22.66987
+234 204 0.95486020000000005
+233 205 2248.7060000000001
+234 205 -1.0206550000000001
+192 206 -0.99229509999999999
+197 206 -21.898569999999999
+198 206 -21.898569999999999
+199 206 -21.898569999999999
+234 206 0.89000959999999996
+235 206 1.0392049999999999
+191 207 0.0077048969999999996
+235 207 -146.1362
+237 207 0.0077048969999999996
+197 208 -0.65890519999999997
+198 208 -1.1064970000000001
+199 208 -1.000909
+236 208 1
+237 209 0.0068956570000000003
+182 210 -1
+212 210 -1
+183 211 -1
+213 211 -1
+184 212 -1
+214 212 -1
+182 213 1
+200 213 -1
+183 214 1.0226759999999999
+201 214 -1
+184 215 1.091418
+202 215 -1
+182 216 -1
+188 216 -1
+183 217 -1
+189 217 -1
+184 218 -1
+190 218 -1
+241 219 -0.19969609999999999
+242 219 -0.78596160000000004
+243 219 -0.00064128229999999996
+244 219 0.40690409999999999
+253 219 0.20247019999999999
+254 219 0.79687960000000002
+255 219 0.00065019060000000002
+256 219 -2.166544
+257 220 -1
+264 220 -0.30001499999999998
+265 220 -0.40746149999999998
+246 221 -1
+247 221 -1
+258 221 1
+244 222 0.40690409999999999
+256 222 -2.166544
+264 222 1
+265 223 1
+241 224 -0.98629889999999998
+250 224 -1
+253 224 1
+261 224 1
+264 224 3.5018579999999999
+265 224 1.241884
+242 225 -0.98629889999999998
+251 225 -1
+254 225 1
+261 225 1
+264 225 -2.149559
+265 225 0.93602390000000002
+243 226 -0.98629889999999998
+252 226 -1
+255 226 1
+261 226 1
+264 226 6.0259859999999996
+265 226 4.0868380000000002
+253 227 0.0119553
+254 227 0.61475029999999997
+255 227 0.1605955
+256 227 0.59918099999999996
+275 227 -0.011949680000000001
+276 227 -0.61446120000000004
+277 227 -0.16052
+278 227 -1
+257 228 1
+262 228 -0.093350859999999994
+263 228 -0.34681810000000002
+266 228 -1
+267 228 -1
+268 228 -1
+259 229 1
+256 230 -0.59918099999999996
+262 230 1
+278 230 1
+263 231 1
+250 232 13.33342
+253 232 0.78730109999999998
+260 232 1
+262 232 12.12026
+263 232 0.77025089999999996
+275 232 -0.78693089999999999
+251 233 1.020551
+254 233 0.78730109999999998
+260 233 1
+262 233 -3.9843989999999998
+263 233 0.681342
+276 233 -0.78693089999999999
+252 234 0.0031874849999999999
+255 234 0.78730109999999998
+260 234 1
+262 234 19.25216
+263 234 2.236907
+277 234 -0.78693089999999999
+253 235 -0.17008129999999999
+254 235 -0.82969219999999999
+255 235 -0.00069701409999999996
+256 235 2.5673629999999998
+275 235 0.1700014
+276 235 0.82930199999999998
+277 235 0.00069668629999999996
+278 235 -4.2847869999999997
+279 236 -1
+286 236 -0.25546930000000001
+287 236 -0.41224569999999999
+258 237 -1
+259 237 -1
+280 237 1
+256 238 2.5673629999999998
+278 238 -4.2847869999999997
+286 238 1
+287 239 1
+253 240 -1.0004710000000001
+272 240 -1
+275 240 1
+283 240 1
+286 240 2.9555289999999999
+287 240 1.2544139999999999
+254 241 -1.0004710000000001
+273 241 -1
+276 241 1
+283 241 1
+286 241 -1.8159689999999999
+287 241 0.94521189999999999
+255 242 -1.0004710000000001
+274 242 -1
+277 242 1
+283 242 1
+286 242 5.0849970000000004
+287 242 4.1364789999999996
+250 243 0.20247019999999999
+269 243 -1
+251 244 0.79687960000000002
+270 244 -1
+252 245 0.20398230000000001
+271 245 -1
+275 246 0.0098180809999999993
+276 246 0.61664169999999996
+278 246 0.95579440000000004
+297 246 -0.0098175689999999999
+298 246 -0.61660959999999998
+299 246 -0.16051480000000001
+300 246 -1
+279 247 1
+284 247 -0.098217899999999997
+285 247 -0.34856389999999998
+288 247 -1
+289 247 -1
+290 247 -1
+281 248 1
+278 249 -0.95579440000000004
+284 249 1
+300 249 1
+285 250 1
+272 251 13.626709999999999
+275 251 0.78698299999999999
+282 251 1
+284 251 12.68233
+285 251 0.76942869999999997
+297 251 -0.78694200000000003
+273 252 1.058389
+276 252 0.78698299999999999
+282 252 1
+284 252 -4.1684890000000001
+285 252 0.68102850000000004
+298 252 -0.78694200000000003
+274 253 0.0034155829999999998
+277 253 0.78698299999999999
+282 253 1
+284 253 20.139959999999999
+285 253 2.2394150000000002
+299 253 -0.78694200000000003
+275 254 -0.16786980000000001
+276 254 -0.83148250000000001
+277 254 -0.00069990470000000002
+278 254 4.3289929999999996
+297 254 0.16786100000000001
+298 254 0.83143909999999999
+299 254 0.00069986820000000004
+300 254 -4.5292089999999998
+301 255 -1
+308 255 -0.2530153
+309 255 -0.4125625
+280 256 -1
+281 256 -1
+302 256 1
+278 257 4.3289929999999996
+300 257 -4.5292089999999998
+308 257 1
+309 258 1
+275 259 -1.0000519999999999
+294 259 -1
+297 259 1
+305 259 1
+308 259 2.9254359999999999
+309 259 1.2552490000000001
+276 260 -1.0000519999999999
+295 260 -1
+298 260 1
+305 260 1
+308 260 -1.797593
+309 260 0.94582429999999995
+277 261 -1.0000519999999999
+296 261 -1
+299 261 1
+305 261 1
+308 261 5.0331659999999996
+309 261 4.1397830000000004
+272 262 0.1700014
+291 262 -1
+273 263 0.82930199999999998
+292 263 -1
+274 264 0.20397290000000001
+293 264 -1
+297 265 0.0096798500000000003
+298 265 0.61671089999999995
+299 265 0.1605181
+300 265 0.99729840000000003
+319 265 -0.0096801700000000001
+320 265 -0.61673129999999998
+321 265 -0.16052340000000001
+322 265 -1
+301 266 1
+306 266 -0.09852872
+307 266 -0.34867100000000001
+310 266 -1
+311 266 -1
+312 266 -1
+303 267 1
+300 268 -0.99729840000000003
+306 268 1
+322 268 1
+307 269 1
+294 270 13.64601
+297 270 0.78690890000000002
+304 270 1
+306 270 12.716189999999999
+307 270 0.7693586
+319 270 -0.78693489999999999
+295 271 1.060897
+298 271 0.78690890000000002
+304 271 1
+306 271 -4.1795749999999998
+307 271 0.68099359999999998
+320 271 -0.78693489999999999
+296 272 0.003430968
+299 272 0.78690890000000002
+304 272 1
+306 272 20.19341
+307 272 2.2395320000000001
+321 272 -0.78693489999999999
+297 273 -0.16772329999999999
+298 273 -0.83154050000000002
+299 273 -0.00070311129999999996
+300 273 4.531911
+319 273 0.16772880000000001
+320 273 0.83156799999999997
+321 273 0.0007031346
+322 273 -4.5441880000000001
+323 274 -1
+330 274 -0.25288909999999998
+331 274 -0.41262900000000002
+302 275 -1
+303 275 -1
+324 275 1
+300 276 4.531911
+322 276 -4.5441880000000001
+330 276 1
+331 277 1
+297 278 -0.99996689999999999
+316 278 -1
+319 278 1
+327 278 1
+330 278 2.9235699999999998
+331 278 1.2552939999999999
+298 279 -0.99996689999999999
+317 279 -1
+320 279 1
+327 279 1
+330 279 -1.7964899999999999
+331 279 0.94585160000000001
+299 280 -0.99996689999999999
+318 280 -1
+321 280 1
+327 280 1
+330 280 5.029935
+331 280 4.1401399999999997
+294 281 0.16786100000000001
+313 281 -1
+295 282 0.83143909999999999
+314 282 -1
+296 283 0.20398559999999999
+315 283 -1
+319 284 0.0096473500000000007
+320 284 0.61499680000000001
+321 284 0.1606638
+322 284 1.012275
+341 284 -0.0096630710000000005
+342 284 -0.61599899999999996
+343 284 -0.1609257
+344 284 -1
+323 285 1
+328 285 -0.097740149999999998
+329 285 -0.348389
+332 285 -1
+333 285 -1
+334 285 -1
+325 286 1
+322 287 -1.012275
+328 287 1
+344 287 1
+329 288 1
+316 289 13.653370000000001
+319 289 0.78530800000000001
+326 289 1
+328 289 12.53604
+329 289 0.76861380000000001
+341 289 -0.7865877
+317 290 1.0618540000000001
+320 290 0.78530800000000001
+326 290 1
+328 290 -4.1203450000000004
+329 290 0.68034459999999997
+342 290 -0.7865877
+318 291 0.0034368480000000002
+321 291 0.78530800000000001
+326 291 1
+328 291 19.9072
+329 291 2.2374860000000001
+343 291 -0.7865877
+319 292 -0.16769600000000001
+320 292 -0.8298335
+321 292 -0.00084358209999999998
+322 292 4.5319130000000003
+341 292 0.16796929999999999
+342 292 0.83118579999999997
+343 292 0.00084495670000000003
+344 292 -4.4769569999999996
+345 293 -1
+352 293 -0.25422820000000002
+353 293 -0.41467850000000001
+324 294 -1
+325 294 -1
+346 294 1
+322 295 4.5319120000000002
+344 295 -4.4769569999999996
+352 295 1
+353 296 1
+319 297 -0.99837310000000001
+338 297 -1
+341 297 1
+349 297 1
+352 297 2.9258000000000002
+353 297 1.2548710000000001
+320 298 -0.99837310000000001
+339 298 -1
+342 298 1
+349 298 1
+352 298 -1.799474
+353 298 0.94529589999999997
+321 299 -0.99837310000000001
+340 299 -1
+343 299 1
+349 299 1
+352 299 5.032978
+353 299 4.1465319999999997
+316 300 0.16772880000000001
+335 300 -1
+317 301 0.83156799999999997
+336 301 -1
+318 302 0.20458699999999999
+337 302 -1
+341 303 0.0089580030000000008
+342 303 0.56239150000000004
+343 303 0.17143159999999999
+344 303 1.5349870000000001
+363 303 -0.0093684010000000002
+364 303 -0.58815669999999998
+365 303 -0.17928549999999999
+366 303 -1
+345 304 1
+350 304 -0.076424569999999997
+351 304 -0.33630700000000002
+354 304 -1
+355 304 -1
+356 304 -1
+347 305 1
+344 306 -1.5349870000000001
+350 306 1
+366 306 1
+351 307 1
+338 308 13.9277
+341 308 0.74278120000000003
+348 308 1
+350 308 7.7124139999999999
+351 308 0.73754050000000004
+363 308 -0.77681060000000002
+339 309 1.0977920000000001
+342 309 0.74278120000000003
+348 309 1
+350 309 -2.5345339999999998
+351 309 0.65320800000000001
+364 309 -0.77681060000000002
+340 310 0.00366104
+343 310 0.74278120000000003
+348 310 1
+350 310 12.244490000000001
+351 310 2.151386
+365 310 -0.77681060000000002
+341 311 -0.1672642
+342 311 -0.77757829999999994
+343 311 -0.01135093
+344 311 3.9419710000000001
+363 311 0.1749272
+364 311 0.81320190000000003
+365 311 0.01187095
+366 311 -2.568082
+367 312 -1
+374 312 -0.31132270000000001
+375 312 -0.45572679999999999
+346 313 -1
+347 313 -1
+368 313 1
+344 314 3.9419710000000001
+366 314 -2.568082
+374 314 1
+375 315 1
+341 316 -0.95619350000000003
+360 316 -1
+363 316 1
+371 316 1
+374 316 3.149454
+375 316 1.212998
+342 317 -0.95619350000000003
+361 317 -1
+364 317 1
+371 317 1
+374 317 -1.985919
+375 317 0.9070684
+343 318 -0.95619350000000003
+362 318 -1
+365 318 1
+371 318 1
+374 318 5.3936869999999999
+375 318 4.2274630000000002
+338 319 0.16796929999999999
+357 319 -1
+339 320 0.83118579999999997
+358 320 -1
+340 321 0.2307969
+359 321 -1
+363 322 0.0049560029999999996
+364 322 0.2092511
+365 322 0.4341566
+366 322 6.177384
+385 322 -0.0056864039999999999
+386 322 -0.24008989999999999
+387 322 -0.49814130000000001
+388 322 -1
+367 323 1
+372 323 -0.051899590000000002
+373 323 -0.22819929999999999
+376 323 -1
+377 323 -1
+378 323 -1
+369 324 1
+366 325 -6.177384
+372 325 1
+388 325 1
+373 326 1
+360 327 22.88466
+363 327 0.64836369999999999
+370 327 1
+372 327 1.04345
+373 327 0.42175859999999998
+385 327 -0.74391759999999996
+361 328 2.5197029999999998
+364 328 0.64836369999999999
+370 328 1
+372 328 -0.3414664
+373 328 0.3798898
+386 328 -0.74391759999999996
+362 329 0.017727920000000001
+365 329 0.64836369999999999
+370 329 1
+372 329 1.6460520000000001
+373 329 1.3054760000000001
+387 329 -0.74391759999999996
+360 330 0.1749272
+379 330 -1
+361 331 0.81320190000000003
+380 331 -1
+362 332 0.66961899999999996
+381 332 -1
+87 333 6.3180579999999997
+93 333 1.008121
+88 334 2.1016520000000001
+94 334 0.98324999999999996
+89 335 10.216340000000001
+95 335 0.97112200000000004
+90 336 4.7715329999999998
+96 336 1.0168969999999999
+91 337 1.5445530000000001
+97 337 0.96515200000000001
+92 338 7.4032580000000001
+98 338 0.93991979999999997
+99 339 276.76479999999998
+105 339 0.88770669999999996
+100 340 192.19040000000001
+106 340 1.2620629999999999
+101 341 465.29739999999998
+107 341 0.8373005
+102 342 402.63529999999997
+108 342 0.93272339999999998
+103 343 243.95160000000001
+109 343 1.157006
+104 344 694.42570000000001
+110 344 0.90252429999999995
+111 345 2.1471689999999999
+117 345 0.73310410000000004
+112 346 1.830354
+118 346 0.77070689999999997
+113 347 5.4194959999999996
+119 347 0.91067969999999998
+114 348 1.5934600000000001
+120 348 0.44472830000000002
+115 349 1.5193589999999999
+121 349 0.52296010000000004
+116 350 5.9272710000000002
+122 350 0.81417070000000002
+123 351 8.6013230000000007
+129 351 0.58171510000000004
+124 352 6.1974850000000004
+130 352 0.53220719999999999
+125 353 37.67033
+131 353 1.1683300000000001
+126 354 10.955349999999999
+132 354 0.74939929999999999
+127 355 8.2864269999999998
+133 355 0.71973830000000005
+128 356 35.092930000000003
+134 356 1.100849
+135 357 0.4338919
+138 357 2.2797130000000001
+136 358 0.1137572
+139 358 0.60698209999999997
+137 359 0.4035473
+140 359 0.0080049890000000005
+141 360 1.1577040000000001
+144 360 4.0422279999999997
+142 361 0.41932589999999997
+145 361 2.449611
+143 362 0.10246470000000001
+146 362 0.36475180000000001
+151 363 172.5745
+154 363 14.91761
+152 364 161.58449999999999
+155 364 12.0938
+153 365 145.31450000000001
+156 365 5.7400960000000003
+157 366 0.0045018890000000002
+158 366 0.95263589999999998
+159 366 -1
+158 367 0.94488159999999999
+163 367 19.882059999999999
+164 367 15.998699999999999
+165 367 7.7694989999999997
+159 368 1.00814
+163 368 98.828980000000001
+164 368 147.5558
+165 368 130.84370000000001
+160 369 1
+163 369 1.8011980000000001
+161 370 1
+164 370 2.196221
+162 371 1
+165 371 2.0607380000000002
+163 372 19.882059999999999
+166 372 0.9740453
+164 373 15.998699999999999
+167 373 0.93133779999999999
+165 374 7.7694989999999997
+168 374 0.82771399999999995
+169 375 -1
+172 375 -1
+175 375 0.056357909999999997
+176 375 0.056357909999999997
+177 375 0.056357909999999997
+170 376 -1
+173 376 -1
+175 376 0.73959730000000001
+176 376 0.73959730000000001
+177 376 0.73959730000000001
+171 377 -1
+174 377 -1
+175 377 0.2040448
+176 377 0.2040448
+177 377 0.2040448
+172 378 1
+175 378 -1
+173 379 1
+176 379 -1
+174 380 1
+177 380 -1
+175 381 1
+178 381 1
+176 382 1
+179 382 1
+177 383 1
+180 383 1
+102 384 -19.453890000000001
+418 384 1
+424 384 -0.09530421
+103 385 -22.090309999999999
+419 385 1
+424 385 -0.088197620000000004
+104 386 -49.563589999999998
+420 386 1
+424 386 -0.00010690420000000001
+421 387 179.7345
+422 387 -2.5957400000000002
+422 388 1
+423 388 -0.09621652
+102 389 -1
+103 389 -1
+104 389 -1
+423 389 0.09621652
+424 389 -0.0088937280000000001
+126 390 0.93082790000000004
+127 390 0.93082790000000004
+128 390 0.93082790000000004
+425 390 -1.138352
+436 390 0.095341780000000001
+126 391 0.81769789999999998
+426 391 -0.55083519999999997
+436 391 0.04613478
+127 392 0.81769789999999998
+427 392 -0.4489223
+436 392 0.037599149999999998
+128 393 6.8068650000000002
+428 393 -0.0020188419999999999
+436 393 0.0001690866
+429 394 -0.60313589999999995
+430 394 -1.1914260000000001
+431 394 -0.2090101
+432 394 -0.2323664
+126 395 -1.5881989999999999
+430 395 1
+436 395 -0.089606729999999996
+127 396 -1.7894779999999999
+431 396 1
+436 396 -0.082283250000000002
+128 397 -4.012804
+432 397 1
+436 397 -9.9680419999999997e-05
+433 398 1.186874
+435 398 -0.87134319999999998
+434 399 0.99186010000000002
+435 399 -0.73414950000000001
+126 400 -1
+127 400 -1
+128 400 -1
+435 400 0.89782490000000004
+436 400 -0.1024269
+185 401 263.30250000000001
+188 401 16.710229999999999
+186 402 252.3125
+189 402 15.091379999999999
+187 403 236.04249999999999
+190 403 11.440289999999999
+191 404 0.0068429329999999998
+192 404 0.96227439999999997
+193 404 -1
+192 405 0.95486020000000005
+197 405 35.042119999999997
+198 405 28.167190000000002
+199 405 13.66854
+193 406 1.0077050000000001
+197 406 85.846760000000003
+198 406 144.16210000000001
+199 406 130.40539999999999
+194 407 1
+197 407 1.6589050000000001
+195 408 1
+198 408 2.1064970000000001
+196 409 1
+199 409 2.000909
+197 410 35.042119999999997
+200 410 1
+198 411 28.167190000000002
+201 411 0.97782690000000005
+199 412 13.66854
+202 412 0.91623940000000004
+203 413 -1
+206 413 -1
+209 413 0.0034351899999999999
+210 413 0.0034351899999999999
+211 413 0.0034351899999999999
+204 414 -1
+207 414 -1
+209 414 0.043016970000000002
+210 414 0.043016970000000002
+211 414 0.043016970000000002
+205 415 -1
+208 415 -1
+209 415 0.95354779999999995
+210 415 0.95354779999999995
+211 415 0.95354779999999995
+206 416 1
+209 416 -1
+207 417 1
+210 417 -1
+208 418 1
+211 418 -1
+209 419 1
+212 419 1
+210 420 1
+213 420 1
+211 421 1
+214 421 1
+90 422 -0.047613129999999997
+461 422 1
+467 422 -2.3334699999999999e-05
+91 423 -0.057464349999999997
+462 423 1
+467 423 -0.00035266559999999999
+92 424 -0.12956039999999999
+463 424 1
+467 424 -0.017625419999999999
+464 425 270.46249999999998
+465 425 -2.8000669999999999
+465 426 1
+466 426 -1.6856930000000001
+90 427 -1
+91 427 -1
+92 427 -1
+466 427 1.6856930000000001
+467 427 -0.1426674
+114 428 0.12149740000000001
+115 428 0.12149740000000001
+116 428 0.12149740000000001
+468 428 -1.138352
+479 428 0.021230519999999999
+114 429 0.60555749999999997
+469 429 -0.019490179999999999
+479 429 0.00036349629999999998
+115 430 0.3357927
+470 430 -0.13533829999999999
+479 430 0.0025240900000000001
+116 431 0.1067309
+471 431 -0.95354779999999995
+479 431 0.017783879999999998
+472 432 -0.90759219999999996
+473 432 -5.7118219999999997
+474 432 -0.93568410000000002
+475 432 -1.0346550000000001
+114 433 -0.043240929999999997
+473 433 1
+479 433 -2.5956110000000001e-05
+115 434 -0.052174909999999998
+474 434 1
+479 434 -0.00039218899999999998
+116 435 -0.1176314
+475 435 1
+479 435 -0.019600159999999998
+476 436 5.3140780000000003
+478 436 -1.002184
+477 437 0.34483720000000001
+478 437 -0.26478620000000003
+114 438 -1
+115 438 -1
+116 438 -1
+478 438 1.7669710000000001
+479 438 -0.1747406
+438 439 99.149730000000005
+444 439 -1
+447 439 -3.311398e-05
+439 440 172.6396
+445 440 -1
+448 440 -4.1108120000000002e-05
+440 441 356.63979999999998
+446 441 -1
+449 441 -8.4587179999999994e-05
+441 442 200.0008
+444 442 2.5
+447 442 3.311398e-05
+442 443 349.00330000000002
+445 443 2.5
+448 443 4.1108120000000002e-05
+443 444 722.06780000000003
+446 444 2.5
+449 444 8.4587179999999994e-05
+444 445 1
+453 445 -1.4485650000000001e-06
+445 446 1
+453 446 -0.0005113292
+446 447 1
+453 447 -0.95438869999999998
+447 448 1.0050250000000001
+454 448 -0.0034351899999999999
+448 449 1.002874
+454 449 -0.043016970000000002
+449 450 1.001387
+454 450 -0.95354779999999995
+450 451 1
+453 451 -4.9455600000000001e-05
+451 452 1
+453 452 -0.0021775570000000001
+452 453 1
+453 453 -0.042871529999999998
+453 454 1
+455 454 -1
+466 454 1.5
+478 454 0.5
+454 455 1
+456 455 -316220
+459 455 -12132.58
+460 455 -1
+466 455 -20451.810000000001
+477 455 9152.7510000000002
+455 456 9.1463570000000001
+457 456 0.0037734919999999998
+456 457 2248.7060000000001
+457 457 -0.12505330000000001
+457 458 0.067588380000000003
+458 458 65.087119999999999
+466 458 -0.18859039999999999
+458 459 -9152.7510000000002
+460 459 0.75439429999999996
+476 459 -9152.7510000000002
+477 459 -6904.7830000000004
+459 460 1
+466 460 0.18569289999999999
+478 460 -0.5
+460 461 0.00019167939999999999
+466 461 2.6684519999999998
+478 461 0.88948400000000005
+266 462 0.52397099999999996
+269 462 2.5902729999999998
+267 463 0.1209036
+270 463 1
+268 464 0.36607729999999999
+271 464 0.018323329999999999
+288 465 0.53070830000000002
+291 465 2.6120320000000001
+289 466 0.12143809999999999
+292 466 1
+290 467 0.36327480000000001
+293 467 0.019398479999999999
+310 468 0.53114850000000002
+313 468 2.6134469999999999
+311 469 0.1214731
+314 469 1
+312 470 0.36309170000000002
+315 470 0.01947045
+332 471 0.53131620000000002
+335 471 2.6139860000000001
+333 472 0.12148639999999999
+336 472 1
+334 473 0.36302190000000001
+337 473 0.01949793
+354 474 0.53753340000000005
+357 474 2.63388
+355 475 0.12197959999999999
+358 475 1
+356 476 0.36043579999999997
+359 476 0.020538460000000001
+376 477 0.71092829999999996
+379 477 3.1304669999999999
+377 478 0.13573579999999999
+380 478 1
+378 479 0.28830909999999998
+381 479 0.071489880000000006
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/data/west0479.mtx	Tue Jul 07 19:40:20 2020 -0400
@@ -0,0 +1,1912 @@
+%%MatrixMarket matrix coordinate real general
+479 479 1910
+25 1  1.0000000000000e+00
+31 1 -3.7648130000000e-02
+87 1 -3.4423960000000e-01
+26 2  1.0000000000000e+00
+31 2 -2.4522620000000e-02
+88 2 -3.7370860000000e-01
+27 3  1.0000000000000e+00
+31 3 -3.6613040000000e-02
+89 3 -8.3693790000000e-01
+28 4  1.3000000000000e+02
+29 4 -2.4337670000000e+00
+29 5  1.0000000000000e+00
+30 5 -1.6140910000000e+00
+30 6  1.6140910000000e+00
+31 6 -2.1873210000000e-01
+87 6 -1.0000000000000e+00
+88 6 -1.0000000000000e+00
+89 6 -1.0000000000000e+00
+32 7 -1.1383520000000e+00
+43 7  3.6694280000000e-02
+111 7  9.9316360000000e-02
+112 7  9.9316360000000e-02
+113 7  9.9316360000000e-02
+33 8 -5.0000000000000e-01
+43 8  1.6117290000000e-02
+111 8  8.7245760000000e-02
+34 9 -3.6119180000000e-01
+43 9  1.1642860000000e-02
+112 9  1.0504150000000e-01
+35 10 -3.2188760000000e-01
+43 10  1.0375910000000e-02
+113 10  1.4041660000000e-01
+36 11 -4.3624160000000e-01
+37 11 -7.6804250000000e-01
+38 11 -1.4302790000000e-01
+39 11 -1.5938860000000e-01
+37 12  1.0000000000000e+00
+43 12 -4.8560820000000e-02
+111 12 -2.6286840000000e-01
+38 13  1.0000000000000e+00
+43 13 -3.0925950000000e-02
+112 13 -2.7901280000000e-01
+39 14  1.0000000000000e+00
+43 14 -4.6123590000000e-02
+113 14 -6.2418820000000e-01
+40 15  5.2824360000000e+00
+42 15 -6.1239210000000e-01
+41 16  2.8868220000000e-01
+42 16 -2.1638150000000e-01
+42 17  1.3287740000000e+00
+43 17 -3.6946860000000e-01
+111 17 -1.0000000000000e+00
+112 17 -1.0000000000000e+00
+113 17 -1.0000000000000e+00
+2 18  4.8176470000000e+01
+8 18 -1.0000000000000e+00
+11 18 -3.3474840000000e-05
+3 19  8.3500000000000e+01
+9 19 -1.0000000000000e+00
+12 19 -4.1365390000000e-05
+4 20  1.7194120000000e+02
+10 20 -1.0000000000000e+00
+13 20 -8.4843450000000e-05
+5 21  9.6651380000000e+01
+8 21  2.5000000000000e+00
+11 21  3.3474840000000e-05
+6 22  1.6827060000000e+02
+9 22  2.5000000000000e+00
+12 22  4.1365390000000e-05
+7 23  3.4758720000000e+02
+10 23  2.5000000000000e+00
+13 23  8.4843450000000e-05
+8 24  1.0000000000000e+00
+17 24 -1.1069670000000e-01
+27 24  1.6052320000000e+00
+9 25  1.0000000000000e+00
+17 25 -8.9808520000000e-02
+10 26  1.0000000000000e+00
+17 26 -1.5173690000000e-01
+11 27  1.0104550000000e+00
+18 27 -5.0000000000000e-01
+12 28  1.0059780000000e+00
+18 28 -3.0000000000000e-01
+13 29  1.0028850000000e+00
+18 29 -2.0000000000000e-01
+14 30  1.0000000000000e+00
+17 30 -1.8118550000000e-01
+15 31  1.0000000000000e+00
+17 31 -2.4002390000000e-01
+16 32  1.0000000000000e+00
+17 32 -2.2654840000000e-01
+17 33  1.0000000000000e+00
+19 33 -1.0000000000000e+00
+30 33  1.5000000000000e+00
+42 33  5.0000000000000e-01
+18 34  1.0000000000000e+00
+20 34 -3.1622000000000e+05
+23 34 -1.2323690000000e+04
+24 34 -1.0000000000000e+00
+30 34 -3.5226800000000e+04
+41 34  1.8449020000000e+04
+19 35  5.2983390000000e+00
+21 35  2.4526870000000e-03
+20 36  1.0808590000000e+03
+21 36 -2.0502150000000e-01
+21 37  1.4419200000000e-01
+22 37  6.3059860000000e+01
+30 37 -1.1592990000000e-01
+22 38 -1.8449020000000e+04
+24 38  8.4533390000000e-01
+40 38 -1.8449020000000e+04
+41 38 -1.5595580000000e+04
+23 39  1.0000000000000e+00
+30 39  2.0204930000000e-01
+42 39 -8.8547100000000e-01
+24 40  1.0002340000000e-04
+30 40  2.4483390000000e+00
+42 40  8.1611300000000e-01
+68 41  1.0000000000000e+00
+74 41 -2.2786690000000e-04
+99 41 -2.6243950000000e-01
+69 42  1.0000000000000e+00
+74 42 -4.1887630000000e-04
+100 42 -3.2161960000000e-01
+70 43  1.0000000000000e+00
+74 43 -1.5769330000000e-03
+101 43 -7.2647610000000e-01
+71 44  3.0000000000000e+02
+72 44 -2.8518910000000e+00
+72 45  1.0000000000000e+00
+73 45 -2.8701590000000e-01
+73 46  2.8701590000000e-01
+74 46 -4.3413220000000e-03
+99 46 -1.0000000000000e+00
+100 46 -1.0000000000000e+00
+101 46 -1.0000000000000e+00
+75 47 -1.1383520000000e+00
+86 47  4.2002860000000e-02
+123 47  9.4148060000000e-01
+124 47  9.4148060000000e-01
+125 47  9.4148060000000e-01
+76 48 -3.2188760000000e-01
+86 48  1.1877000000000e-02
+123 48  1.3310950000000e+00
+77 49 -3.6119180000000e-01
+86 49  1.3327240000000e-02
+124 49  9.9575290000000e-01
+78 50 -5.0000000000000e-01
+86 50  1.8448980000000e-02
+125 50  8.2705600000000e-01
+79 51 -1.0000000000000e+00
+80 51 -1.9240000000000e+01
+81 51 -3.8030000000000e+00
+82 51 -9.4810000000000e+00
+80 52  1.0000000000000e+00
+86 52 -8.8757840000000e-04
+123 52 -9.9473920000000e-02
+81 53  1.0000000000000e+00
+86 53 -1.3313680000000e-03
+124 53 -9.9473920000000e-02
+82 54  1.0000000000000e+00
+86 54 -2.2189460000000e-03
+125 54 -9.9473920000000e-02
+83 55  1.1776130000000e+00
+85 55 -3.1089630000000e+00
+84 56  9.9194250000000e-01
+85 56 -2.6400560000000e+00
+85 57  3.1921120000000e+00
+86 57 -4.4613630000000e-02
+123 57 -1.0000000000000e+00
+124 57 -1.0000000000000e+00
+125 57 -1.0000000000000e+00
+45 58  1.0986880000000e+02
+51 58 -1.0000000000000e+00
+54 58 -3.3081100000000e-05
+46 59  1.9138460000000e+02
+52 59 -1.0000000000000e+00
+55 59 -4.1084670000000e-05
+47 60  3.9547960000000e+02
+53 60 -1.0000000000000e+00
+56 60 -8.4563830000000e-05
+48 61  2.2173390000000e+02
+51 61  2.5000000000000e+00
+54 61  3.3081100000000e-05
+49 62  3.8700920000000e+02
+52 62  2.5000000000000e+00
+55 62  4.1084670000000e-05
+50 63  8.0081650000000e+02
+53 63  2.5000000000000e+00
+56 63  8.4563830000000e-05
+51 64  1.0000000000000e+00
+60 64 -9.1702290000000e-03
+52 65  1.0000000000000e+00
+60 65 -4.6441100000000e-02
+53 66  1.0000000000000e+00
+60 66 -4.8999190000000e-01
+54 67  1.0045300000000e+00
+61 67 -2.0000000000000e-01
+55 68  1.0025910000000e+00
+61 68 -3.0000000000000e-01
+56 69  1.0012500000000e+00
+61 69 -5.0000000000000e-01
+57 70  1.0000000000000e+00
+60 70 -3.7500530000000e-02
+58 71  1.0000000000000e+00
+60 71 -1.2414300000000e-01
+59 72  1.0000000000000e+00
+60 72 -2.9275320000000e-01
+60 73  1.0000000000000e+00
+62 73 -1.0000000000000e+00
+73 73  1.8537330000000e-01
+85 73  6.1791090000000e-02
+61 74  1.0000000000000e+00
+63 74 -3.1622000000000e+05
+66 74 -1.6364190000000e+04
+67 74 -1.0000000000000e+00
+73 74 -4.6967820000000e+03
+84 74  1.3185400000000e+02
+62 75  2.2129130000000e+01
+64 75  9.5375260000000e-01
+63 76  2.4942900000000e+03
+64 76 -1.0215870000000e+00
+64 77  8.8782810000000e-01
+65 77  1.0400420000000e+00
+73 77 -2.6400560000000e+00
+65 78 -1.3185400000000e+02
+67 78  8.0574700000000e-03
+83 78 -1.3185400000000e+02
+84 78 -1.0624090000000e+00
+66 79  1.0000000000000e+00
+73 79  1.0164260000000e-01
+85 79 -6.1791090000000e-02
+67 80  7.6452570000000e-03
+73 80  2.3098950000000e+01
+85 80  7.6996490000000e+00
+31 81  1.0000000000000e+00
+244 81  1.0000000000000e+00
+43 82  1.0000000000000e+00
+1 83  1.0000000000000e+00
+17 83 -3.8502310000000e+00
+18 83 -8.4599350000000e-05
+31 83  2.0159100000000e+00
+35 83  1.0000000000000e+00
+43 83  1.5961710000000e+00
+243 83 -7.8975120000000e-01
+74 84  1.0000000000000e+00
+388 84  8.8175620000000e-01
+86 85  1.0000000000000e+00
+44 86  1.0000000000000e+00
+60 86 -2.7937600000000e+00
+61 86 -8.4458230000000e-05
+74 86  2.0156650000000e+00
+78 86  1.0000000000000e+00
+86 86  1.5939940000000e+00
+384 86  0.0000000000000e+00
+387 86 -9.6191500000000e-01
+385 87  2.4246690000000e-03
+386 87  3.0362780000000e-02
+387 87  6.7304510000000e-01
+388 87  1.4593600000000e+00
+96 88  1.6896610000000e-02
+97 88  3.4848030000000e-02
+98 88 -6.0080180000000e-02
+120 88 -5.5527170000000e-01
+121 88 -4.7703980000000e-01
+122 88 -1.8582930000000e-01
+141 88 -1.0000000000000e+00
+142 88 -1.0000000000000e+00
+143 88 -1.0000000000000e+00
+185 88 -5.5188570000000e+01
+186 88 -9.5676860000000e+01
+187 88 -2.1583770000000e+02
+389 88  1.0000000000000e+00
+438 88  1.0000000000000e+00
+439 88  1.0000000000000e+00
+440 88  1.0000000000000e+00
+441 88  1.0000000000000e+00
+442 88  1.0000000000000e+00
+443 88  1.0000000000000e+00
+450 88 -1.8907560000000e-03
+451 88 -1.5311400000000e-03
+452 88 -1.0137260000000e-03
+455 88  2.5000000000000e+00
+456 88  2.6063700000000e+01
+458 88  1.0000000000000e+00
+459 88 -1.5000000000000e+00
+461 88 -9.6031810000000e+00
+462 88 -9.4541850000000e+00
+463 88 -9.4376810000000e+00
+464 88 -4.8295720000000e+01
+472 88  9.0759220000000e-01
+473 88 -4.3759670000000e+00
+474 88 -8.9979920000000e+00
+475 88 -8.8819580000000e+00
+476 88  1.0000000000000e+00
+182 89  1.0000000000000e+00
+183 89  1.0000000000000e+00
+184 89  1.0000000000000e+00
+391 89  1.0000000000000e+00
+455 89 -1.0000000000000e+00
+456 89 -2.6063700000000e+01
+458 89 -1.0000000000000e+00
+468 89  1.0000000000000e+00
+388 90 -1.4593600000000e+00
+467 90  1.0000000000000e+00
+479 91  1.0000000000000e+00
+203 92 -1.0000000000000e+00
+204 92 -1.0000000000000e+00
+205 92 -1.0000000000000e+00
+209 92  1.0000000000000e+00
+210 92  1.0000000000000e+00
+211 92  1.0000000000000e+00
+382 92  5.6953100000000e+01
+385 92  7.0583250000000e-01
+437 92  1.0000000000000e+00
+453 92 -6.4913720000000e-01
+454 92 -3.2948410000000e-05
+467 92  5.3807480000000e-01
+469 92  1.0000000000000e+00
+479 92  8.2471120000000e-02
+203 93 -1.0000000000000e+00
+204 93 -1.0000000000000e+00
+205 93 -1.0000000000000e+00
+209 93  1.0000000000000e+00
+210 93  1.0000000000000e+00
+211 93  1.0000000000000e+00
+383 93  1.1583840000000e+01
+386 93  7.0583250000000e-01
+437 93  1.0000000000000e+00
+453 93 -1.0215420000000e+00
+454 93 -4.0990330000000e-05
+467 93 -3.6302480000000e-01
+470 93  1.0000000000000e+00
+479 93  6.9522610000000e-02
+203 94 -1.0000000000000e+00
+204 94 -1.0000000000000e+00
+205 94 -1.0000000000000e+00
+209 94  1.0000000000000e+00
+210 94  1.0000000000000e+00
+211 94  1.0000000000000e+00
+384 94  3.2096310000000e-01
+387 94  7.0583250000000e-01
+437 94  1.0000000000000e+00
+453 94 -2.0490070000000e+00
+454 94 -8.4470030000000e-05
+467 94  9.1353620000000e-01
+471 94  1.0000000000000e+00
+479 94  8.3976380000000e-01
+241 95  5.5083520000000e-01
+242 95  4.4892230000000e-01
+243 95  2.4252030000000e-04
+244 95  4.0528330000000e-01
+108 96 -6.7276620000000e-02
+109 96 -1.5700610000000e-01
+110 96 -9.7475700000000e-02
+132 96 -2.5060070000000e-01
+133 96 -2.8026170000000e-01
+134 96  1.0084910000000e-01
+245 96 -1.0000000000000e+00
+395 96  1.0000000000000e+00
+396 96  1.0000000000000e+00
+397 96  1.0000000000000e+00
+398 96  1.0000000000000e+00
+399 96  1.0000000000000e+00
+400 96  1.0000000000000e+00
+407 96 -2.8636020000000e-03
+408 96 -2.3162590000000e-03
+409 96 -1.5308900000000e-03
+412 96  2.5000000000000e+00
+413 96  1.1587800000000e+01
+415 96  1.0000000000000e+00
+416 96 -1.1012240000000e+00
+418 96 -1.3644320000000e+00
+419 96 -1.2188210000000e+00
+420 96 -1.2108590000000e+00
+421 96 -3.4621050000000e+01
+429 96  6.0313590000000e-01
+430 96 -5.9963840000000e-01
+431 96 -1.4033920000000e+00
+432 96 -1.3703860000000e+00
+433 96  1.0000000000000e+00
+246 97  1.0000000000000e+00
+412 97 -1.0000000000000e+00
+413 97 -1.1587800000000e+01
+415 97 -1.0000000000000e+00
+425 97  1.0000000000000e+00
+244 98 -4.0528330000000e-01
+424 98  1.0000000000000e+00
+436 99  1.0000000000000e+00
+160 100 -8.5938400000000e-01
+161 100 -7.7333900000000e-01
+162 100 -7.9517400000000e-01
+238 100 -1.0000000000000e+00
+241 100  1.0000000000000e+00
+394 100  1.0000000000000e+00
+410 100 -1.6236590000000e+00
+411 100 -3.3032780000000e-05
+424 100  3.5720350000000e+00
+426 100  1.0000000000000e+00
+436 100  9.2435320000000e-01
+160 101 -1.1718210000000e+00
+161 101 -1.2773520000000e+00
+162 101 -1.2505080000000e+00
+239 101 -1.0000000000000e+00
+242 101  1.0000000000000e+00
+394 101  1.0000000000000e+00
+410 101 -2.4602890000000e+00
+411 101 -4.1050810000000e-05
+424 101 -2.1785330000000e+00
+427 101  1.0000000000000e+00
+436 101  6.5098420000000e-01
+160 102 -2.3280470000000e+00
+161 102 -2.4161550000000e+00
+162 102 -2.5121660000000e+00
+240 102 -1.0000000000000e+00
+243 102  1.0000000000000e+00
+394 102  1.0000000000000e+00
+410 102 -4.7536200000000e+00
+411 102 -8.4530500000000e-05
+424 102  6.1671400000000e+00
+428 102  1.0000000000000e+00
+436 102  3.3966910000000e+00
+241 103  4.3736570000000e-02
+242 103  5.7396460000000e-01
+243 103  1.5834900000000e-01
+244 103  1.8781250000000e-01
+253 103 -4.4344130000000e-02
+254 103 -5.8193780000000e-01
+255 103 -1.6054870000000e-01
+256 103 -1.0000000000000e+00
+135 104 -1.0000000000000e+00
+136 104 -1.0000000000000e+00
+137 104 -1.0000000000000e+00
+151 104 -6.2680900000000e+01
+152 104 -1.2389000000000e+02
+153 104 -4.6435550000000e+02
+245 104  1.0000000000000e+00
+248 104 -5.1646550000000e-02
+249 104 -3.2417620000000e-01
+148 105  1.0000000000000e+00
+149 105  1.0000000000000e+00
+150 105  1.0000000000000e+00
+247 105  1.0000000000000e+00
+244 106 -1.8781250000000e-01
+248 106  1.0000000000000e+00
+256 106  1.0000000000000e+00
+249 107  1.0000000000000e+00
+147 108  1.0000000000000e+00
+169 108 -1.0000000000000e+00
+170 108 -1.0000000000000e+00
+171 108 -1.0000000000000e+00
+175 108  1.0000000000000e+00
+176 108  1.0000000000000e+00
+177 108  1.0000000000000e+00
+238 108  9.7738750000000e+00
+241 108  7.7605020000000e-01
+248 108  7.2528310000000e+00
+249 108  7.8041000000000e-01
+253 108 -7.8683060000000e-01
+147 109  1.0000000000000e+00
+169 109 -1.0000000000000e+00
+170 109 -1.0000000000000e+00
+171 109 -1.0000000000000e+00
+175 109  1.0000000000000e+00
+176 109  1.0000000000000e+00
+177 109  1.0000000000000e+00
+239 109  6.0698210000000e-01
+242 109  7.7605020000000e-01
+248 109 -2.3895080000000e+00
+249 109  6.8493980000000e-01
+254 109 -7.8683060000000e-01
+147 110  1.0000000000000e+00
+169 110 -1.0000000000000e+00
+170 110 -1.0000000000000e+00
+171 110 -1.0000000000000e+00
+175 110  1.0000000000000e+00
+176 110  1.0000000000000e+00
+177 110  1.0000000000000e+00
+240 110  1.1885640000000e-03
+243 110  7.7605020000000e-01
+248 110  1.1558830000000e+01
+249 110  2.2026440000000e+00
+255 110 -7.8683060000000e-01
+363 111 -1.7051480000000e-01
+364 111 -4.3429630000000e-01
+365 111 -2.6674210000000e-01
+366 111 -2.6093020000000e+00
+385 111  1.9564470000000e-01
+386 111  4.9830160000000e-01
+387 111  3.0605370000000e-01
+388 111  4.2239600000000e-01
+215 112  1.0000000000000e+00
+216 112  1.0000000000000e+00
+217 112  1.0000000000000e+00
+218 112  1.0000000000000e+00
+219 112  1.0000000000000e+00
+220 112  1.0000000000000e+00
+227 112 -1.8907560000000e-03
+228 112 -1.5311400000000e-03
+229 112 -1.0137260000000e-03
+232 112  2.5000000000000e+00
+233 112  1.6672410000000e+01
+235 112  1.0000000000000e+00
+236 112 -1.5000000000000e+00
+389 112 -1.0000000000000e+00
+392 112 -4.6212130000000e-01
+393 112 -1.2349620000000e-01
+232 113 -1.0000000000000e+00
+233 113 -1.6672410000000e+01
+235 113 -1.0000000000000e+00
+368 113 -1.0000000000000e+00
+369 113 -1.0000000000000e+00
+390 113  1.0000000000000e+00
+366 114  2.6093020000000e+00
+388 114 -4.2239600000000e-01
+392 114  1.0000000000000e+00
+393 115  1.0000000000000e+00
+181 116  1.0000000000000e+00
+194 116 -5.8697620000000e-01
+195 116 -5.0651550000000e-01
+196 116 -5.1399180000000e-01
+230 116 -1.0366850000000e+00
+231 116 -3.2948410000000e-05
+360 116  0.0000000000000e+00
+363 116 -8.7155310000000e-01
+382 116 -1.0000000000000e+00
+385 116  1.0000000000000e+00
+392 116  2.6399800000000e+00
+393 116  5.5742070000000e-01
+181 117  1.0000000000000e+00
+194 117 -8.0016370000000e-01
+195 117 -8.3640900000000e-01
+196 117 -8.0810260000000e-01
+230 117 -1.6376950000000e+00
+231 117 -4.0990330000000e-05
+361 117  0.0000000000000e+00
+364 117 -8.7155310000000e-01
+383 117 -1.0000000000000e+00
+386 117  1.0000000000000e+00
+392 117 -1.7736780000000e+00
+393 117  4.0754220000000e-01
+181 118  1.0000000000000e+00
+194 118 -1.5893890000000e+00
+195 118 -1.5818110000000e+00
+196 118 -1.6231180000000e+00
+230 118 -3.2056860000000e+00
+231 118 -8.4470030000000e-05
+362 118  0.0000000000000e+00
+365 118 -8.7155310000000e-01
+384 118 -1.0000000000000e+00
+387 118  1.0000000000000e+00
+392 118  4.4676090000000e+00
+393 118  2.2475290000000e+00
+93 119 -1.0000000000000e+00
+96 119 -1.0000000000000e+00
+248 119 -4.0421560000000e-01
+262 119 -1.8187770000000e-01
+284 119 -1.5634550000000e-01
+306 119 -1.5456990000000e-01
+328 119 -1.5217780000000e-01
+350 119 -9.1905800000000e-02
+372 119 -7.8705370000000e-03
+94 120 -1.0000000000000e+00
+97 120 -1.0000000000000e+00
+248 120 -1.8091710000000e+00
+262 120 -3.1896550000000e+00
+284 120 -3.3490190000000e+00
+306 120 -3.3586440000000e+00
+328 120 -3.3085850000000e+00
+350 120 -1.9678700000000e+00
+372 120 -1.1333560000000e-01
+95 121 -1.0000000000000e+00
+98 121 -1.0000000000000e+00
+248 121 -2.4566020000000e+00
+262 121 -4.1011280000000e+00
+284 121 -4.2908920000000e+00
+306 121 -4.3026030000000e+00
+328 121 -4.2541470000000e+00
+350 121 -2.9523890000000e+00
+372 121 -1.1573650000000e+00
+93 122 -8.1214960000000e-03
+96 122 -1.6896610000000e-02
+248 122 -4.5387600000000e-03
+262 122 -2.1705200000000e-03
+284 122 -1.8740690000000e-03
+306 122 -1.8533180000000e-03
+328 122 -1.8248370000000e-03
+350 122 -1.1065610000000e-03
+372 122 -1.0544940000000e-04
+94 123 -1.6749990000000e-02
+97 123 -3.4848030000000e-02
+248 123 -4.1896920000000e-02
+262 123 -7.8506680000000e-02
+284 123 -8.2793510000000e-02
+306 123 -8.3055320000000e-02
+328 123 -8.1826380000000e-02
+350 123 -4.8866050000000e-02
+372 123 -3.1317320000000e-03
+95 124 -2.8878030000000e-02
+98 124 -6.0080180000000e-02
+248 124 -9.8082240000000e-02
+262 124 -1.7402810000000e-01
+284 124 -1.8288550000000e-01
+306 124 -1.8343740000000e-01
+328 124 -1.8139140000000e-01
+350 124 -1.2639720000000e-01
+372 124 -5.5136770000000e-02
+105 125 -1.0000000000000e+00
+108 125 -1.0000000000000e+00
+264 125 -7.6362320000000e-01
+286 125 -5.4132110000000e-01
+308 125 -5.2907530000000e-01
+330 125 -5.2832600000000e-01
+352 125 -5.2965340000000e-01
+374 125 -5.9901060000000e-01
+392 125 -5.7467680000000e-01
+106 126 -1.0000000000000e+00
+109 126 -1.0000000000000e+00
+264 126 -1.4679790000000e+00
+286 126 -1.2898060000000e+00
+308 126 -1.2799920000000e+00
+330 126 -1.2793850000000e+00
+352 126 -1.2801740000000e+00
+374 126 -1.3601430000000e+00
+392 126 -7.1491900000000e-01
+107 127 -1.0000000000000e+00
+110 127 -1.0000000000000e+00
+264 127 -4.3708570000000e-03
+286 127 -3.9541010000000e-03
+308 127 -3.9318030000000e-03
+330 127 -3.9476680000000e-03
+352 127 -4.7490230000000e-03
+374 127 -7.2455390000000e-02
+392 127 -1.6023640000000e+00
+105 128 -1.1229330000000e-01
+108 128 -6.7276620000000e-02
+264 128 -5.4601370000000e-02
+286 128 -3.8877220000000e-02
+308 128 -3.8008660000000e-02
+330 128 -3.7958990000000e-02
+352 128 -3.8208860000000e-02
+374 128 -4.8085490000000e-02
+392 128 -5.8178620000000e-02
+106 129 -2.6206330000000e-01
+109 129 -1.5700610000000e-01
+264 129 -2.4496080000000e-01
+286 129 -2.1618060000000e-01
+308 129 -2.1459740000000e-01
+330 129 -2.1451910000000e-01
+352 129 -2.1552300000000e-01
+374 129 -2.5481000000000e-01
+392 129 -1.6890750000000e-01
+107 130 -1.6269950000000e-01
+110 130 -9.7475700000000e-02
+264 130 -4.5281760000000e-04
+286 130 -4.1145290000000e-04
+308 130 -4.0925030000000e-04
+330 130 -4.1094670000000e-04
+352 130 -4.9637370000000e-04
+374 130 -8.4271850000000e-03
+392 130 -2.3503520000000e-01
+117 131 -1.0000000000000e+00
+120 131 -1.0000000000000e+00
+249 131 -6.9702840000000e-02
+263 131 -1.9243320000000e-02
+285 131 -1.5837930000000e-02
+307 131 -1.5617910000000e-02
+329 131 -1.5583210000000e-02
+351 131 -1.4718560000000e-02
+373 131 -5.7599520000000e-03
+118 132 -1.0000000000000e+00
+121 132 -1.0000000000000e+00
+249 132 -7.4171360000000e-01
+263 132 -8.0234940000000e-01
+285 132 -8.0658470000000e-01
+307 132 -8.0682860000000e-01
+329 132 -8.0550310000000e-01
+351 132 -7.4926980000000e-01
+373 132 -1.9719700000000e-01
+119 133 -1.0000000000000e+00
+122 133 -1.0000000000000e+00
+249 133 -5.1275980000000e-01
+263 133 -5.2522530000000e-01
+285 133 -5.2614130000000e-01
+307 133 -5.2622450000000e-01
+329 133 -5.2730270000000e-01
+351 133 -5.7231860000000e-01
+373 133 -1.0252420000000e+00
+117 134 -4.6575930000000e-01
+120 134 -9.6900310000000e-01
+249 134 -4.4884880000000e-02
+263 134 -1.3170120000000e-02
+285 134 -1.0887390000000e-02
+307 134 -1.0739240000000e-02
+329 134 -1.0716550000000e-02
+351 134 -1.0163030000000e-02
+373 134 -4.4257190000000e-03
+118 135 -5.7440230000000e-01
+121 135 -1.1950330000000e+00
+249 135 -5.8903420000000e-01
+263 135 -6.7721740000000e-01
+285 135 -6.8380180000000e-01
+307 135 -6.8420530000000e-01
+329 135 -6.8315610000000e-01
+351 135 -6.3804400000000e-01
+373 135 -1.8686160000000e-01
+119 136 -2.2922850000000e-01
+122 136 -4.7690550000000e-01
+249 136 -1.6250650000000e-01
+263 136 -1.7691420000000e-01
+285 136 -1.7800620000000e-01
+307 136 -1.7808560000000e-01
+329 136 -1.7847000000000e-01
+351 136 -1.9449250000000e-01
+373 136 -3.8770260000000e-01
+129 137 -1.0000000000000e+00
+132 137 -1.0000000000000e+00
+265 137 -3.4272790000000e-01
+287 137 -2.9113760000000e-01
+309 137 -2.8769370000000e-01
+331 137 -2.8748890000000e-01
+353 137 -2.8823180000000e-01
+375 137 -3.0269870000000e-01
+393 137 -1.7507890000000e-01
+130 138 -1.0000000000000e+00
+133 138 -1.0000000000000e+00
+265 138 -1.0623340000000e+00
+287 138 -1.1185060000000e+00
+309 138 -1.1222530000000e+00
+331 138 -1.1225120000000e+00
+353 138 -1.1232850000000e+00
+375 138 -1.1082340000000e+00
+393 138 -3.5118640000000e-01
+131 139 -1.0000000000000e+00
+134 139 -1.0000000000000e+00
+265 139 -2.3999820000000e-03
+287 139 -2.6017300000000e-03
+309 139 -2.6156270000000e-03
+331 139 -2.6280330000000e-03
+353 139 -3.1617350000000e-03
+375 139 -4.4793810000000e-02
+393 139 -5.9723090000000e-01
+129 140 -2.0182530000000e+00
+132 140 -1.2091660000000e+00
+265 140 -4.4044890000000e-01
+287 140 -3.7580290000000e-01
+309 140 -3.7146430000000e-01
+331 140 -3.7124050000000e-01
+353 140 -3.7371090000000e-01
+375 140 -4.3672880000000e-01
+393 140 -3.1856280000000e-01
+130 141 -2.5626880000000e+00
+133 141 -1.5353450000000e+00
+265 141 -1.7335130000000e+00
+287 141 -1.8332450000000e+00
+309 141 -1.8399150000000e+00
+331 141 -1.8405410000000e+00
+353 141 -1.8492860000000e+00
+375 141 -2.0302660000000e+00
+393 141 -8.1137050000000e-01
+131 142 -9.2554290000000e-01
+134 142 -5.5450670000000e-01
+265 142 -1.4144090000000e-03
+287 142 -1.5400860000000e-03
+309 142 -1.5487580000000e-03
+331 142 -1.5562740000000e-03
+353 142 -1.8799250000000e-03
+375 142 -2.9637400000000e-02
+393 142 -4.9833870000000e-01
+135 143 -1.4338920000000e+00
+141 143 -2.1577040000000e+00
+266 143 -1.5239710000000e+00
+288 143 -1.5307080000000e+00
+310 143 -1.5311480000000e+00
+332 143 -1.5313160000000e+00
+354 143 -1.5375330000000e+00
+376 143 -1.7109280000000e+00
+136 144 -9.4320600000000e-01
+142 144 -1.4193260000000e+00
+267 144 -1.0024600000000e+00
+289 144 -1.0068910000000e+00
+311 144 -1.0071810000000e+00
+333 144 -1.0072910000000e+00
+355 144 -1.0113810000000e+00
+377 144 -1.1254390000000e+00
+137 145 -5.9645270000000e-01
+143 145 -8.9753530000000e-01
+268 145 -6.3392270000000e-01
+290 145 -6.3672520000000e-01
+312 145 -6.3690830000000e-01
+334 145 -6.3697810000000e-01
+356 145 -6.3956420000000e-01
+378 145 -7.1169090000000e-01
+135 146 -1.0000000000000e+00
+141 146 -1.0000000000000e+00
+266 146 -1.0000000000000e+00
+288 146 -1.0000000000000e+00
+310 146 -1.0000000000000e+00
+332 146 -1.0000000000000e+00
+354 146 -1.0000000000000e+00
+376 146 -1.0000000000000e+00
+136 147 -1.0000000000000e+00
+142 147 -1.0000000000000e+00
+267 147 -1.0000000000000e+00
+289 147 -1.0000000000000e+00
+311 147 -1.0000000000000e+00
+333 147 -1.0000000000000e+00
+355 147 -1.0000000000000e+00
+377 147 -1.0000000000000e+00
+137 148 -1.0000000000000e+00
+143 148 -1.0000000000000e+00
+268 148 -1.0000000000000e+00
+290 148 -1.0000000000000e+00
+312 148 -1.0000000000000e+00
+334 148 -1.0000000000000e+00
+356 148 -1.0000000000000e+00
+378 148 -1.0000000000000e+00
+138 149 -1.0000000000000e+00
+148 149  1.0000000000000e+00
+238 149  5.5083520000000e-01
+139 150 -1.0000000000000e+00
+149 150  1.6474950000000e+00
+239 150  7.3959730000000e-01
+140 151 -1.0000000000000e+00
+150 151  8.4135160000000e+02
+240 151  2.0404480000000e-01
+144 152 -1.0000000000000e+00
+182 152  1.0000000000000e+00
+382 152  1.9564470000000e-01
+145 153 -1.0000000000000e+00
+183 153  1.0000000000000e+00
+383 153  4.9830160000000e-01
+146 154 -1.0000000000000e+00
+184 154  3.1156220000000e+00
+384 154  9.5354780000000e-01
+395 155  6.6224920000000e+01
+401 155 -1.0000000000000e+00
+404 155 -3.3282570000000e-05
+396 156  1.1506230000000e+02
+402 156 -1.0000000000000e+00
+405 156 -4.1228310000000e-05
+397 157  2.3733870000000e+02
+403 157 -1.0000000000000e+00
+406 157 -8.4706900000000e-05
+398 158  1.3324500000000e+02
+401 158  2.5000000000000e+00
+404 158  3.3282570000000e-05
+399 159  2.3226390000000e+02
+402 159  2.5000000000000e+00
+405 159  4.1228310000000e-05
+400 160  4.8018210000000e+02
+403 160  2.5000000000000e+00
+406 160  8.4706900000000e-05
+160 161 -4.7337900000000e-01
+401 161  1.0000000000000e+00
+410 161 -2.1168760000000e-01
+161 162 -5.7343170000000e-01
+402 162  1.0000000000000e+00
+410 162 -3.1667150000000e-01
+162 163 -6.0925110000000e-04
+403 163  1.0000000000000e+00
+410 163 -3.5118740000000e-07
+163 164 -4.5750040000000e+03
+404 164  1.0075620000000e+00
+411 164 -5.5083520000000e-01
+164 165 -3.6814160000000e+03
+405 165  1.0043240000000e+00
+411 165 -4.4892230000000e-01
+165 166 -1.7878180000000e+03
+406 166  1.0020870000000e+00
+411 166 -2.4252030000000e-04
+160 167 -5.2605640000000e-01
+161 167 -4.2598230000000e-01
+407 167  1.0000000000000e+00
+410 167 -4.7048840000000e-01
+160 168 -5.6459870000000e-04
+162 168 -4.3800980000000e-01
+408 168  1.0000000000000e+00
+410 168 -5.0495930000000e-04
+161 169 -5.8596670000000e-04
+162 169 -5.6138090000000e-01
+409 169  1.0000000000000e+00
+410 169 -6.4718760000000e-04
+163 170 -1.0000000000000e+00
+164 170 -1.0000000000000e+00
+165 170 -1.0000000000000e+00
+410 170  1.0000000000000e+00
+412 170 -1.0000000000000e+00
+423 170  6.1444210000000e-02
+435 170  2.0481400000000e-02
+157 171 -1.0000000000000e+00
+163 171  4.1240600000000e+03
+164 171  4.1240600000000e+03
+165 171  4.1240600000000e+03
+411 171  1.0000000000000e+00
+413 171 -3.1622000000000e+05
+416 171 -2.0034240000000e+04
+417 171 -1.0000000000000e+00
+423 171 -2.6256570000000e+03
+434 171  2.2212900000000e+02
+412 172  1.8737270000000e+01
+414 172  9.4488160000000e-01
+413 173  1.4943670000000e+03
+414 173 -1.0207800000000e+00
+158 174 -9.9186010000000e-01
+163 174 -1.7922340000000e+01
+164 174 -1.7922340000000e+01
+165 174 -1.7922340000000e+01
+414 174  8.6282900000000e-01
+415 174  1.0497190000000e+00
+423 174 -7.3414950000000e-01
+157 175  8.1398600000000e-03
+415 175 -2.2212900000000e+02
+417 175  8.1398600000000e-03
+433 175 -2.2212900000000e+02
+434 175 -1.8080990000000e+00
+163 176 -1.0913280000000e+00
+164 176 -1.6293970000000e+00
+165 176 -1.4448530000000e+00
+416 176  1.0000000000000e+00
+423 176  4.7364060000000e-02
+435 176 -2.7898140000000e-02
+417 177  4.5385340000000e-03
+423 177  7.5792400000000e+00
+435 177  2.5264130000000e+00
+148 178 -1.0000000000000e+00
+178 178 -1.0000000000000e+00
+149 179 -1.0000000000000e+00
+179 179 -1.0000000000000e+00
+150 180 -1.0000000000000e+00
+180 180 -1.0000000000000e+00
+148 181  1.0266460000000e+00
+166 181 -1.0000000000000e+00
+149 182  1.0737240000000e+00
+167 182 -1.0000000000000e+00
+150 183  1.2081470000000e+00
+168 183 -1.0000000000000e+00
+148 184 -1.0000000000000e+00
+154 184 -1.0000000000000e+00
+149 185 -1.0000000000000e+00
+155 185 -1.0000000000000e+00
+150 186 -1.0000000000000e+00
+156 186 -1.0000000000000e+00
+215 187  9.9149730000000e+01
+221 187 -1.0000000000000e+00
+224 187 -3.3113980000000e-05
+216 188  1.7263960000000e+02
+222 188 -1.0000000000000e+00
+225 188 -4.1108120000000e-05
+217 189  3.5663980000000e+02
+223 189 -1.0000000000000e+00
+226 189 -8.4587180000000e-05
+218 190  2.0000080000000e+02
+221 190  2.5000000000000e+00
+224 190  3.3113980000000e-05
+219 191  3.4900330000000e+02
+222 191  2.5000000000000e+00
+225 191  4.1108120000000e-05
+220 192  7.2206780000000e+02
+223 192  2.5000000000000e+00
+226 192  8.4587180000000e-05
+194 193 -1.1483880000000e-01
+221 193  1.0000000000000e+00
+230 193 -1.1645920000000e-02
+195 194 -4.1678390000000e-01
+222 194  1.0000000000000e+00
+230 194 -1.7006160000000e-01
+196 195 -4.9676140000000e-01
+223 195  1.0000000000000e+00
+230 195 -2.4368930000000e-01
+197 196 -5.2768620000000e+03
+224 196  1.0050250000000e+00
+231 196 -1.9564470000000e-01
+198 197 -4.2415910000000e+03
+225 197  1.0028740000000e+00
+231 197 -4.9830160000000e-01
+199 198 -2.0582940000000e+03
+226 198  1.0013870000000e+00
+231 198 -3.0605370000000e-01
+194 199 -3.9872280000000e-01
+195 199 -9.9097090000000e-02
+227 199  1.0000000000000e+00
+230 199 -8.0869760000000e-02
+194 200 -4.8643840000000e-01
+196 200 -1.0055980000000e-01
+228 200  1.0000000000000e+00
+230 200 -9.8660410000000e-02
+195 201 -4.8411900000000e-01
+196 201 -4.0267880000000e-01
+229 201  1.0000000000000e+00
+230 201 -3.9507300000000e-01
+197 202 -1.0000000000000e+00
+198 202 -1.0000000000000e+00
+199 202 -1.0000000000000e+00
+230 202  1.0000000000000e+00
+232 202 -1.0000000000000e+00
+191 203 -1.0000000000000e+00
+197 203  3.2976230000000e+03
+198 203  3.2976230000000e+03
+199 203  3.2976230000000e+03
+231 203  1.0000000000000e+00
+233 203 -3.1622000000000e+05
+236 203 -1.8966660000000e+04
+237 203 -1.0000000000000e+00
+232 204  2.2669870000000e+01
+234 204  9.5486020000000e-01
+233 205  2.2487060000000e+03
+234 205 -1.0206550000000e+00
+192 206 -9.9229510000000e-01
+197 206 -2.1898570000000e+01
+198 206 -2.1898570000000e+01
+199 206 -2.1898570000000e+01
+234 206  8.9000960000000e-01
+235 206  1.0392050000000e+00
+191 207  7.7048970000000e-03
+235 207 -1.4613620000000e+02
+237 207  7.7048970000000e-03
+197 208 -6.5890520000000e-01
+198 208 -1.1064970000000e+00
+199 208 -1.0009090000000e+00
+236 208  1.0000000000000e+00
+237 209  6.8956570000000e-03
+182 210 -1.0000000000000e+00
+212 210 -1.0000000000000e+00
+183 211 -1.0000000000000e+00
+213 211 -1.0000000000000e+00
+184 212 -1.0000000000000e+00
+214 212 -1.0000000000000e+00
+182 213  1.0000000000000e+00
+200 213 -1.0000000000000e+00
+183 214  1.0226760000000e+00
+201 214 -1.0000000000000e+00
+184 215  1.0914180000000e+00
+202 215 -1.0000000000000e+00
+182 216 -1.0000000000000e+00
+188 216 -1.0000000000000e+00
+183 217 -1.0000000000000e+00
+189 217 -1.0000000000000e+00
+184 218 -1.0000000000000e+00
+190 218 -1.0000000000000e+00
+241 219 -1.9969610000000e-01
+242 219 -7.8596160000000e-01
+243 219 -6.4128230000000e-04
+244 219  4.0690410000000e-01
+253 219  2.0247020000000e-01
+254 219  7.9687960000000e-01
+255 219  6.5019060000000e-04
+256 219 -2.1665440000000e+00
+257 220 -1.0000000000000e+00
+264 220 -3.0001500000000e-01
+265 220 -4.0746150000000e-01
+246 221 -1.0000000000000e+00
+247 221 -1.0000000000000e+00
+258 221  1.0000000000000e+00
+244 222  4.0690410000000e-01
+256 222 -2.1665440000000e+00
+264 222  1.0000000000000e+00
+265 223  1.0000000000000e+00
+238 224  0.0000000000000e+00
+241 224 -9.8629890000000e-01
+250 224 -1.0000000000000e+00
+253 224  1.0000000000000e+00
+261 224  1.0000000000000e+00
+264 224  3.5018580000000e+00
+265 224  1.2418840000000e+00
+239 225  0.0000000000000e+00
+242 225 -9.8629890000000e-01
+251 225 -1.0000000000000e+00
+254 225  1.0000000000000e+00
+261 225  1.0000000000000e+00
+264 225 -2.1495590000000e+00
+265 225  9.3602390000000e-01
+240 226  0.0000000000000e+00
+243 226 -9.8629890000000e-01
+252 226 -1.0000000000000e+00
+255 226  1.0000000000000e+00
+261 226  1.0000000000000e+00
+264 226  6.0259860000000e+00
+265 226  4.0868380000000e+00
+253 227  1.1955300000000e-02
+254 227  6.1475030000000e-01
+255 227  1.6059550000000e-01
+256 227  5.9918100000000e-01
+275 227 -1.1949680000000e-02
+276 227 -6.1446120000000e-01
+277 227 -1.6052000000000e-01
+278 227 -1.0000000000000e+00
+257 228  1.0000000000000e+00
+262 228 -9.3350860000000e-02
+263 228 -3.4681810000000e-01
+266 228 -1.0000000000000e+00
+267 228 -1.0000000000000e+00
+268 228 -1.0000000000000e+00
+259 229  1.0000000000000e+00
+256 230 -5.9918100000000e-01
+262 230  1.0000000000000e+00
+278 230  1.0000000000000e+00
+263 231  1.0000000000000e+00
+250 232  1.3333420000000e+01
+253 232  7.8730110000000e-01
+260 232  1.0000000000000e+00
+262 232  1.2120260000000e+01
+263 232  7.7025090000000e-01
+275 232 -7.8693090000000e-01
+251 233  1.0205510000000e+00
+254 233  7.8730110000000e-01
+260 233  1.0000000000000e+00
+262 233 -3.9843990000000e+00
+263 233  6.8134200000000e-01
+276 233 -7.8693090000000e-01
+252 234  3.1874850000000e-03
+255 234  7.8730110000000e-01
+260 234  1.0000000000000e+00
+262 234  1.9252160000000e+01
+263 234  2.2369070000000e+00
+277 234 -7.8693090000000e-01
+253 235 -1.7008130000000e-01
+254 235 -8.2969220000000e-01
+255 235 -6.9701410000000e-04
+256 235  2.5673630000000e+00
+275 235  1.7000140000000e-01
+276 235  8.2930200000000e-01
+277 235  6.9668630000000e-04
+278 235 -4.2847870000000e+00
+279 236 -1.0000000000000e+00
+286 236 -2.5546930000000e-01
+287 236 -4.1224570000000e-01
+258 237 -1.0000000000000e+00
+259 237 -1.0000000000000e+00
+280 237  1.0000000000000e+00
+256 238  2.5673630000000e+00
+278 238 -4.2847870000000e+00
+286 238  1.0000000000000e+00
+287 239  1.0000000000000e+00
+250 240  0.0000000000000e+00
+253 240 -1.0004710000000e+00
+272 240 -1.0000000000000e+00
+275 240  1.0000000000000e+00
+283 240  1.0000000000000e+00
+286 240  2.9555290000000e+00
+287 240  1.2544140000000e+00
+251 241  0.0000000000000e+00
+254 241 -1.0004710000000e+00
+273 241 -1.0000000000000e+00
+276 241  1.0000000000000e+00
+283 241  1.0000000000000e+00
+286 241 -1.8159690000000e+00
+287 241  9.4521190000000e-01
+252 242  0.0000000000000e+00
+255 242 -1.0004710000000e+00
+274 242 -1.0000000000000e+00
+277 242  1.0000000000000e+00
+283 242  1.0000000000000e+00
+286 242  5.0849970000000e+00
+287 242  4.1364790000000e+00
+250 243  2.0247020000000e-01
+269 243 -1.0000000000000e+00
+251 244  7.9687960000000e-01
+270 244 -1.0000000000000e+00
+252 245  2.0398230000000e-01
+271 245 -1.0000000000000e+00
+275 246  9.8180810000000e-03
+276 246  6.1664170000000e-01
+278 246  9.5579440000000e-01
+297 246 -9.8175690000000e-03
+298 246 -6.1660960000000e-01
+299 246 -1.6051480000000e-01
+300 246 -1.0000000000000e+00
+279 247  1.0000000000000e+00
+284 247 -9.8217900000000e-02
+285 247 -3.4856390000000e-01
+288 247 -1.0000000000000e+00
+289 247 -1.0000000000000e+00
+290 247 -1.0000000000000e+00
+281 248  1.0000000000000e+00
+278 249 -9.5579440000000e-01
+284 249  1.0000000000000e+00
+300 249  1.0000000000000e+00
+285 250  1.0000000000000e+00
+272 251  1.3626710000000e+01
+275 251  7.8698300000000e-01
+282 251  1.0000000000000e+00
+284 251  1.2682330000000e+01
+285 251  7.6942870000000e-01
+297 251 -7.8694200000000e-01
+273 252  1.0583890000000e+00
+276 252  7.8698300000000e-01
+282 252  1.0000000000000e+00
+284 252 -4.1684890000000e+00
+285 252  6.8102850000000e-01
+298 252 -7.8694200000000e-01
+274 253  3.4155830000000e-03
+277 253  7.8698300000000e-01
+282 253  1.0000000000000e+00
+284 253  2.0139960000000e+01
+285 253  2.2394150000000e+00
+299 253 -7.8694200000000e-01
+275 254 -1.6786980000000e-01
+276 254 -8.3148250000000e-01
+277 254 -6.9990470000000e-04
+278 254  4.3289930000000e+00
+297 254  1.6786100000000e-01
+298 254  8.3143910000000e-01
+299 254  6.9986820000000e-04
+300 254 -4.5292090000000e+00
+301 255 -1.0000000000000e+00
+308 255 -2.5301530000000e-01
+309 255 -4.1256250000000e-01
+280 256 -1.0000000000000e+00
+281 256 -1.0000000000000e+00
+302 256  1.0000000000000e+00
+278 257  4.3289930000000e+00
+300 257 -4.5292090000000e+00
+308 257  1.0000000000000e+00
+309 258  1.0000000000000e+00
+272 259  0.0000000000000e+00
+275 259 -1.0000520000000e+00
+294 259 -1.0000000000000e+00
+297 259  1.0000000000000e+00
+305 259  1.0000000000000e+00
+308 259  2.9254360000000e+00
+309 259  1.2552490000000e+00
+273 260  0.0000000000000e+00
+276 260 -1.0000520000000e+00
+295 260 -1.0000000000000e+00
+298 260  1.0000000000000e+00
+305 260  1.0000000000000e+00
+308 260 -1.7975930000000e+00
+309 260  9.4582430000000e-01
+274 261  0.0000000000000e+00
+277 261 -1.0000520000000e+00
+296 261 -1.0000000000000e+00
+299 261  1.0000000000000e+00
+305 261  1.0000000000000e+00
+308 261  5.0331660000000e+00
+309 261  4.1397830000000e+00
+272 262  1.7000140000000e-01
+291 262 -1.0000000000000e+00
+273 263  8.2930200000000e-01
+292 263 -1.0000000000000e+00
+274 264  2.0397290000000e-01
+293 264 -1.0000000000000e+00
+297 265  9.6798500000000e-03
+298 265  6.1671090000000e-01
+299 265  1.6051810000000e-01
+300 265  9.9729840000000e-01
+319 265 -9.6801700000000e-03
+320 265 -6.1673130000000e-01
+321 265 -1.6052340000000e-01
+322 265 -1.0000000000000e+00
+301 266  1.0000000000000e+00
+306 266 -9.8528720000000e-02
+307 266 -3.4867100000000e-01
+310 266 -1.0000000000000e+00
+311 266 -1.0000000000000e+00
+312 266 -1.0000000000000e+00
+303 267  1.0000000000000e+00
+300 268 -9.9729840000000e-01
+306 268  1.0000000000000e+00
+322 268  1.0000000000000e+00
+307 269  1.0000000000000e+00
+294 270  1.3646010000000e+01
+297 270  7.8690890000000e-01
+304 270  1.0000000000000e+00
+306 270  1.2716190000000e+01
+307 270  7.6935860000000e-01
+319 270 -7.8693490000000e-01
+295 271  1.0608970000000e+00
+298 271  7.8690890000000e-01
+304 271  1.0000000000000e+00
+306 271 -4.1795750000000e+00
+307 271  6.8099360000000e-01
+320 271 -7.8693490000000e-01
+296 272  3.4309680000000e-03
+299 272  7.8690890000000e-01
+304 272  1.0000000000000e+00
+306 272  2.0193410000000e+01
+307 272  2.2395320000000e+00
+321 272 -7.8693490000000e-01
+297 273 -1.6772330000000e-01
+298 273 -8.3154050000000e-01
+299 273 -7.0311130000000e-04
+300 273  4.5319110000000e+00
+319 273  1.6772880000000e-01
+320 273  8.3156800000000e-01
+321 273  7.0313460000000e-04
+322 273 -4.5441880000000e+00
+323 274 -1.0000000000000e+00
+330 274 -2.5288910000000e-01
+331 274 -4.1262900000000e-01
+302 275 -1.0000000000000e+00
+303 275 -1.0000000000000e+00
+324 275  1.0000000000000e+00
+300 276  4.5319110000000e+00
+322 276 -4.5441880000000e+00
+330 276  1.0000000000000e+00
+331 277  1.0000000000000e+00
+294 278  0.0000000000000e+00
+297 278 -9.9996690000000e-01
+316 278 -1.0000000000000e+00
+319 278  1.0000000000000e+00
+327 278  1.0000000000000e+00
+330 278  2.9235700000000e+00
+331 278  1.2552940000000e+00
+295 279  0.0000000000000e+00
+298 279 -9.9996690000000e-01
+317 279 -1.0000000000000e+00
+320 279  1.0000000000000e+00
+327 279  1.0000000000000e+00
+330 279 -1.7964900000000e+00
+331 279  9.4585160000000e-01
+296 280  0.0000000000000e+00
+299 280 -9.9996690000000e-01
+318 280 -1.0000000000000e+00
+321 280  1.0000000000000e+00
+327 280  1.0000000000000e+00
+330 280  5.0299350000000e+00
+331 280  4.1401400000000e+00
+294 281  1.6786100000000e-01
+313 281 -1.0000000000000e+00
+295 282  8.3143910000000e-01
+314 282 -1.0000000000000e+00
+296 283  2.0398560000000e-01
+315 283 -1.0000000000000e+00
+319 284  9.6473500000000e-03
+320 284  6.1499680000000e-01
+321 284  1.6066380000000e-01
+322 284  1.0122750000000e+00
+341 284 -9.6630710000000e-03
+342 284 -6.1599900000000e-01
+343 284 -1.6092570000000e-01
+344 284 -1.0000000000000e+00
+323 285  1.0000000000000e+00
+328 285 -9.7740150000000e-02
+329 285 -3.4838900000000e-01
+332 285 -1.0000000000000e+00
+333 285 -1.0000000000000e+00
+334 285 -1.0000000000000e+00
+325 286  1.0000000000000e+00
+322 287 -1.0122750000000e+00
+328 287  1.0000000000000e+00
+344 287  1.0000000000000e+00
+329 288  1.0000000000000e+00
+316 289  1.3653370000000e+01
+319 289  7.8530800000000e-01
+326 289  1.0000000000000e+00
+328 289  1.2536040000000e+01
+329 289  7.6861380000000e-01
+341 289 -7.8658770000000e-01
+317 290  1.0618540000000e+00
+320 290  7.8530800000000e-01
+326 290  1.0000000000000e+00
+328 290 -4.1203450000000e+00
+329 290  6.8034460000000e-01
+342 290 -7.8658770000000e-01
+318 291  3.4368480000000e-03
+321 291  7.8530800000000e-01
+326 291  1.0000000000000e+00
+328 291  1.9907200000000e+01
+329 291  2.2374860000000e+00
+343 291 -7.8658770000000e-01
+319 292 -1.6769600000000e-01
+320 292 -8.2983350000000e-01
+321 292 -8.4358210000000e-04
+322 292  4.5319130000000e+00
+341 292  1.6796930000000e-01
+342 292  8.3118580000000e-01
+343 292  8.4495670000000e-04
+344 292 -4.4769570000000e+00
+345 293 -1.0000000000000e+00
+352 293 -2.5422820000000e-01
+353 293 -4.1467850000000e-01
+324 294 -1.0000000000000e+00
+325 294 -1.0000000000000e+00
+346 294  1.0000000000000e+00
+322 295  4.5319120000000e+00
+344 295 -4.4769570000000e+00
+352 295  1.0000000000000e+00
+353 296  1.0000000000000e+00
+316 297  0.0000000000000e+00
+319 297 -9.9837310000000e-01
+338 297 -1.0000000000000e+00
+341 297  1.0000000000000e+00
+349 297  1.0000000000000e+00
+352 297  2.9258000000000e+00
+353 297  1.2548710000000e+00
+317 298  0.0000000000000e+00
+320 298 -9.9837310000000e-01
+339 298 -1.0000000000000e+00
+342 298  1.0000000000000e+00
+349 298  1.0000000000000e+00
+352 298 -1.7994740000000e+00
+353 298  9.4529590000000e-01
+318 299  0.0000000000000e+00
+321 299 -9.9837310000000e-01
+340 299 -1.0000000000000e+00
+343 299  1.0000000000000e+00
+349 299  1.0000000000000e+00
+352 299  5.0329780000000e+00
+353 299  4.1465320000000e+00
+316 300  1.6772880000000e-01
+335 300 -1.0000000000000e+00
+317 301  8.3156800000000e-01
+336 301 -1.0000000000000e+00
+318 302  2.0458700000000e-01
+337 302 -1.0000000000000e+00
+341 303  8.9580030000000e-03
+342 303  5.6239150000000e-01
+343 303  1.7143160000000e-01
+344 303  1.5349870000000e+00
+363 303 -9.3684010000000e-03
+364 303 -5.8815670000000e-01
+365 303 -1.7928550000000e-01
+366 303 -1.0000000000000e+00
+345 304  1.0000000000000e+00
+350 304 -7.6424570000000e-02
+351 304 -3.3630700000000e-01
+354 304 -1.0000000000000e+00
+355 304 -1.0000000000000e+00
+356 304 -1.0000000000000e+00
+347 305  1.0000000000000e+00
+344 306 -1.5349870000000e+00
+350 306  1.0000000000000e+00
+366 306  1.0000000000000e+00
+351 307  1.0000000000000e+00
+338 308  1.3927700000000e+01
+341 308  7.4278120000000e-01
+348 308  1.0000000000000e+00
+350 308  7.7124140000000e+00
+351 308  7.3754050000000e-01
+363 308 -7.7681060000000e-01
+339 309  1.0977920000000e+00
+342 309  7.4278120000000e-01
+348 309  1.0000000000000e+00
+350 309 -2.5345340000000e+00
+351 309  6.5320800000000e-01
+364 309 -7.7681060000000e-01
+340 310  3.6610400000000e-03
+343 310  7.4278120000000e-01
+348 310  1.0000000000000e+00
+350 310  1.2244490000000e+01
+351 310  2.1513860000000e+00
+365 310 -7.7681060000000e-01
+341 311 -1.6726420000000e-01
+342 311 -7.7757830000000e-01
+343 311 -1.1350930000000e-02
+344 311  3.9419710000000e+00
+363 311  1.7492720000000e-01
+364 311  8.1320190000000e-01
+365 311  1.1870950000000e-02
+366 311 -2.5680820000000e+00
+367 312 -1.0000000000000e+00
+374 312 -3.1132270000000e-01
+375 312 -4.5572680000000e-01
+346 313 -1.0000000000000e+00
+347 313 -1.0000000000000e+00
+368 313  1.0000000000000e+00
+344 314  3.9419710000000e+00
+366 314 -2.5680820000000e+00
+374 314  1.0000000000000e+00
+375 315  1.0000000000000e+00
+338 316  0.0000000000000e+00
+341 316 -9.5619350000000e-01
+360 316 -1.0000000000000e+00
+363 316  1.0000000000000e+00
+371 316  1.0000000000000e+00
+374 316  3.1494540000000e+00
+375 316  1.2129980000000e+00
+339 317  0.0000000000000e+00
+342 317 -9.5619350000000e-01
+361 317 -1.0000000000000e+00
+364 317  1.0000000000000e+00
+371 317  1.0000000000000e+00
+374 317 -1.9859190000000e+00
+375 317  9.0706840000000e-01
+340 318  0.0000000000000e+00
+343 318 -9.5619350000000e-01
+362 318 -1.0000000000000e+00
+365 318  1.0000000000000e+00
+371 318  1.0000000000000e+00
+374 318  5.3936870000000e+00
+375 318  4.2274630000000e+00
+338 319  1.6796930000000e-01
+357 319 -1.0000000000000e+00
+339 320  8.3118580000000e-01
+358 320 -1.0000000000000e+00
+340 321  2.3079690000000e-01
+359 321 -1.0000000000000e+00
+363 322  4.9560030000000e-03
+364 322  2.0925110000000e-01
+365 322  4.3415660000000e-01
+366 322  6.1773840000000e+00
+385 322 -5.6864040000000e-03
+386 322 -2.4008990000000e-01
+387 322 -4.9814130000000e-01
+388 322 -1.0000000000000e+00
+367 323  1.0000000000000e+00
+372 323 -5.1899590000000e-02
+373 323 -2.2819930000000e-01
+376 323 -1.0000000000000e+00
+377 323 -1.0000000000000e+00
+378 323 -1.0000000000000e+00
+369 324  1.0000000000000e+00
+366 325 -6.1773840000000e+00
+372 325  1.0000000000000e+00
+388 325  1.0000000000000e+00
+373 326  1.0000000000000e+00
+360 327  2.2884660000000e+01
+363 327  6.4836370000000e-01
+370 327  1.0000000000000e+00
+372 327  1.0434500000000e+00
+373 327  4.2175860000000e-01
+385 327 -7.4391760000000e-01
+361 328  2.5197030000000e+00
+364 328  6.4836370000000e-01
+370 328  1.0000000000000e+00
+372 328 -3.4146640000000e-01
+373 328  3.7988980000000e-01
+386 328 -7.4391760000000e-01
+362 329  1.7727920000000e-02
+365 329  6.4836370000000e-01
+370 329  1.0000000000000e+00
+372 329  1.6460520000000e+00
+373 329  1.3054760000000e+00
+387 329 -7.4391760000000e-01
+360 330  1.7492720000000e-01
+379 330 -1.0000000000000e+00
+361 331  8.1320190000000e-01
+380 331 -1.0000000000000e+00
+362 332  6.6961900000000e-01
+381 332 -1.0000000000000e+00
+87 333  6.3180580000000e+00
+93 333  1.0081210000000e+00
+88 334  2.1016520000000e+00
+94 334  9.8325000000000e-01
+89 335  1.0216340000000e+01
+95 335  9.7112200000000e-01
+90 336  4.7715330000000e+00
+96 336  1.0168970000000e+00
+91 337  1.5445530000000e+00
+97 337  9.6515200000000e-01
+92 338  7.4032580000000e+00
+98 338  9.3991980000000e-01
+99 339  2.7676480000000e+02
+105 339  8.8770670000000e-01
+100 340  1.9219040000000e+02
+106 340  1.2620630000000e+00
+101 341  4.6529740000000e+02
+107 341  8.3730050000000e-01
+102 342  4.0263530000000e+02
+108 342  9.3272340000000e-01
+103 343  2.4395160000000e+02
+109 343  1.1570060000000e+00
+104 344  6.9442570000000e+02
+110 344  9.0252430000000e-01
+111 345  2.1471690000000e+00
+117 345  7.3310410000000e-01
+112 346  1.8303540000000e+00
+118 346  7.7070690000000e-01
+113 347  5.4194960000000e+00
+119 347  9.1067970000000e-01
+114 348  1.5934600000000e+00
+120 348  4.4472830000000e-01
+115 349  1.5193590000000e+00
+121 349  5.2296010000000e-01
+116 350  5.9272710000000e+00
+122 350  8.1417070000000e-01
+123 351  8.6013230000000e+00
+129 351  5.8171510000000e-01
+124 352  6.1974850000000e+00
+130 352  5.3220720000000e-01
+125 353  3.7670330000000e+01
+131 353  1.1683300000000e+00
+126 354  1.0955350000000e+01
+132 354  7.4939930000000e-01
+127 355  8.2864270000000e+00
+133 355  7.1973830000000e-01
+128 356  3.5092930000000e+01
+134 356  1.1008490000000e+00
+135 357  4.3389190000000e-01
+138 357  2.2797130000000e+00
+136 358  1.1375720000000e-01
+139 358  6.0698210000000e-01
+137 359  4.0354730000000e-01
+140 359  8.0049890000000e-03
+141 360  1.1577040000000e+00
+144 360  4.0422280000000e+00
+142 361  4.1932590000000e-01
+145 361  2.4496110000000e+00
+143 362  1.0246470000000e-01
+146 362  3.6475180000000e-01
+151 363  1.7257450000000e+02
+154 363  1.4917610000000e+01
+152 364  1.6158450000000e+02
+155 364  1.2093800000000e+01
+153 365  1.4531450000000e+02
+156 365  5.7400960000000e+00
+157 366  4.5018890000000e-03
+158 366  9.5263590000000e-01
+159 366 -1.0000000000000e+00
+158 367  9.4488160000000e-01
+163 367  1.9882060000000e+01
+164 367  1.5998700000000e+01
+165 367  7.7694990000000e+00
+159 368  1.0081400000000e+00
+163 368  9.8828980000000e+01
+164 368  1.4755580000000e+02
+165 368  1.3084370000000e+02
+160 369  1.0000000000000e+00
+163 369  1.8011980000000e+00
+161 370  1.0000000000000e+00
+164 370  2.1962210000000e+00
+162 371  1.0000000000000e+00
+165 371  2.0607380000000e+00
+163 372  1.9882060000000e+01
+166 372  9.7404530000000e-01
+164 373  1.5998700000000e+01
+167 373  9.3133780000000e-01
+165 374  7.7694990000000e+00
+168 374  8.2771400000000e-01
+169 375 -1.0000000000000e+00
+172 375 -1.0000000000000e+00
+175 375  5.6357910000000e-02
+176 375  5.6357910000000e-02
+177 375  5.6357910000000e-02
+170 376 -1.0000000000000e+00
+173 376 -1.0000000000000e+00
+175 376  7.3959730000000e-01
+176 376  7.3959730000000e-01
+177 376  7.3959730000000e-01
+171 377 -1.0000000000000e+00
+174 377 -1.0000000000000e+00
+175 377  2.0404480000000e-01
+176 377  2.0404480000000e-01
+177 377  2.0404480000000e-01
+172 378  1.0000000000000e+00
+175 378 -1.0000000000000e+00
+173 379  1.0000000000000e+00
+176 379 -1.0000000000000e+00
+174 380  1.0000000000000e+00
+177 380 -1.0000000000000e+00
+175 381  1.0000000000000e+00
+178 381  1.0000000000000e+00
+176 382  1.0000000000000e+00
+179 382  1.0000000000000e+00
+177 383  1.0000000000000e+00
+180 383  1.0000000000000e+00
+102 384 -1.9453890000000e+01
+418 384  1.0000000000000e+00
+424 384 -9.5304210000000e-02
+103 385 -2.2090310000000e+01
+419 385  1.0000000000000e+00
+424 385 -8.8197620000000e-02
+104 386 -4.9563590000000e+01
+420 386  1.0000000000000e+00
+424 386 -1.0690420000000e-04
+421 387  1.7973450000000e+02
+422 387 -2.5957400000000e+00
+422 388  1.0000000000000e+00
+423 388 -9.6216520000000e-02
+102 389 -1.0000000000000e+00
+103 389 -1.0000000000000e+00
+104 389 -1.0000000000000e+00
+423 389  9.6216520000000e-02
+424 389 -8.8937280000000e-03
+126 390  9.3082790000000e-01
+127 390  9.3082790000000e-01
+128 390  9.3082790000000e-01
+425 390 -1.1383520000000e+00
+436 390  9.5341780000000e-02
+126 391  8.1769790000000e-01
+426 391 -5.5083520000000e-01
+436 391  4.6134780000000e-02
+127 392  8.1769790000000e-01
+427 392 -4.4892230000000e-01
+436 392  3.7599150000000e-02
+128 393  6.8068650000000e+00
+428 393 -2.0188420000000e-03
+436 393  1.6908660000000e-04
+429 394 -6.0313590000000e-01
+430 394 -1.1914260000000e+00
+431 394 -2.0901010000000e-01
+432 394 -2.3236640000000e-01
+126 395 -1.5881990000000e+00
+430 395  1.0000000000000e+00
+436 395 -8.9606730000000e-02
+127 396 -1.7894780000000e+00
+431 396  1.0000000000000e+00
+436 396 -8.2283250000000e-02
+128 397 -4.0128040000000e+00
+432 397  1.0000000000000e+00
+436 397 -9.9680420000000e-05
+433 398  1.1868740000000e+00
+435 398 -8.7134320000000e-01
+434 399  9.9186010000000e-01
+435 399 -7.3414950000000e-01
+126 400 -1.0000000000000e+00
+127 400 -1.0000000000000e+00
+128 400 -1.0000000000000e+00
+435 400  8.9782490000000e-01
+436 400 -1.0242690000000e-01
+185 401  2.6330250000000e+02
+188 401  1.6710230000000e+01
+186 402  2.5231250000000e+02
+189 402  1.5091380000000e+01
+187 403  2.3604250000000e+02
+190 403  1.1440290000000e+01
+191 404  6.8429330000000e-03
+192 404  9.6227440000000e-01
+193 404 -1.0000000000000e+00
+192 405  9.5486020000000e-01
+197 405  3.5042120000000e+01
+198 405  2.8167190000000e+01
+199 405  1.3668540000000e+01
+193 406  1.0077050000000e+00
+197 406  8.5846760000000e+01
+198 406  1.4416210000000e+02
+199 406  1.3040540000000e+02
+194 407  1.0000000000000e+00
+197 407  1.6589050000000e+00
+195 408  1.0000000000000e+00
+198 408  2.1064970000000e+00
+196 409  1.0000000000000e+00
+199 409  2.0009090000000e+00
+197 410  3.5042120000000e+01
+200 410  1.0000000000000e+00
+198 411  2.8167190000000e+01
+201 411  9.7782690000000e-01
+199 412  1.3668540000000e+01
+202 412  9.1623940000000e-01
+203 413 -1.0000000000000e+00
+206 413 -1.0000000000000e+00
+209 413  3.4351900000000e-03
+210 413  3.4351900000000e-03
+211 413  3.4351900000000e-03
+204 414 -1.0000000000000e+00
+207 414 -1.0000000000000e+00
+209 414  4.3016970000000e-02
+210 414  4.3016970000000e-02
+211 414  4.3016970000000e-02
+205 415 -1.0000000000000e+00
+208 415 -1.0000000000000e+00
+209 415  9.5354780000000e-01
+210 415  9.5354780000000e-01
+211 415  9.5354780000000e-01
+206 416  1.0000000000000e+00
+209 416 -1.0000000000000e+00
+207 417  1.0000000000000e+00
+210 417 -1.0000000000000e+00
+208 418  1.0000000000000e+00
+211 418 -1.0000000000000e+00
+209 419  1.0000000000000e+00
+212 419  1.0000000000000e+00
+210 420  1.0000000000000e+00
+213 420  1.0000000000000e+00
+211 421  1.0000000000000e+00
+214 421  1.0000000000000e+00
+90 422 -4.7613130000000e-02
+461 422  1.0000000000000e+00
+467 422 -2.3334700000000e-05
+91 423 -5.7464350000000e-02
+462 423  1.0000000000000e+00
+467 423 -3.5266560000000e-04
+92 424 -1.2956040000000e-01
+463 424  1.0000000000000e+00
+467 424 -1.7625420000000e-02
+464 425  2.7046250000000e+02
+465 425 -2.8000670000000e+00
+465 426  1.0000000000000e+00
+466 426 -1.6856930000000e+00
+90 427 -1.0000000000000e+00
+91 427 -1.0000000000000e+00
+92 427 -1.0000000000000e+00
+466 427  1.6856930000000e+00
+467 427 -1.4266740000000e-01
+114 428  1.2149740000000e-01
+115 428  1.2149740000000e-01
+116 428  1.2149740000000e-01
+468 428 -1.1383520000000e+00
+479 428  2.1230520000000e-02
+114 429  6.0555750000000e-01
+469 429 -1.9490180000000e-02
+479 429  3.6349630000000e-04
+115 430  3.3579270000000e-01
+470 430 -1.3533830000000e-01
+479 430  2.5240900000000e-03
+116 431  1.0673090000000e-01
+471 431 -9.5354780000000e-01
+479 431  1.7783880000000e-02
+472 432 -9.0759220000000e-01
+473 432 -5.7118220000000e+00
+474 432 -9.3568410000000e-01
+475 432 -1.0346550000000e+00
+114 433 -4.3240930000000e-02
+473 433  1.0000000000000e+00
+479 433 -2.5956110000000e-05
+115 434 -5.2174910000000e-02
+474 434  1.0000000000000e+00
+479 434 -3.9218900000000e-04
+116 435 -1.1763140000000e-01
+475 435  1.0000000000000e+00
+479 435 -1.9600160000000e-02
+476 436  5.3140780000000e+00
+478 436 -1.0021840000000e+00
+477 437  3.4483720000000e-01
+478 437 -2.6478620000000e-01
+114 438 -1.0000000000000e+00
+115 438 -1.0000000000000e+00
+116 438 -1.0000000000000e+00
+478 438  1.7669710000000e+00
+479 438 -1.7474060000000e-01
+438 439  9.9149730000000e+01
+444 439 -1.0000000000000e+00
+447 439 -3.3113980000000e-05
+439 440  1.7263960000000e+02
+445 440 -1.0000000000000e+00
+448 440 -4.1108120000000e-05
+440 441  3.5663980000000e+02
+446 441 -1.0000000000000e+00
+449 441 -8.4587180000000e-05
+441 442  2.0000080000000e+02
+444 442  2.5000000000000e+00
+447 442  3.3113980000000e-05
+442 443  3.4900330000000e+02
+445 443  2.5000000000000e+00
+448 443  4.1108120000000e-05
+443 444  7.2206780000000e+02
+446 444  2.5000000000000e+00
+449 444  8.4587180000000e-05
+444 445  1.0000000000000e+00
+453 445 -1.4485650000000e-06
+445 446  1.0000000000000e+00
+453 446 -5.1132920000000e-04
+446 447  1.0000000000000e+00
+453 447 -9.5438870000000e-01
+447 448  1.0050250000000e+00
+454 448 -3.4351900000000e-03
+448 449  1.0028740000000e+00
+454 449 -4.3016970000000e-02
+449 450  1.0013870000000e+00
+454 450 -9.5354780000000e-01
+450 451  1.0000000000000e+00
+453 451 -4.9455600000000e-05
+451 452  1.0000000000000e+00
+453 452 -2.1775570000000e-03
+452 453  1.0000000000000e+00
+453 453 -4.2871530000000e-02
+453 454  1.0000000000000e+00
+455 454 -1.0000000000000e+00
+466 454  1.5000000000000e+00
+478 454  5.0000000000000e-01
+454 455  1.0000000000000e+00
+456 455 -3.1622000000000e+05
+459 455 -1.2132580000000e+04
+460 455 -1.0000000000000e+00
+466 455 -2.0451810000000e+04
+477 455  9.1527510000000e+03
+455 456  9.1463570000000e+00
+457 456  3.7734920000000e-03
+456 457  2.2487060000000e+03
+457 457 -1.2505330000000e-01
+457 458  6.7588380000000e-02
+458 458  6.5087120000000e+01
+466 458 -1.8859040000000e-01
+458 459 -9.1527510000000e+03
+460 459  7.5439430000000e-01
+476 459 -9.1527510000000e+03
+477 459 -6.9047830000000e+03
+459 460  1.0000000000000e+00
+466 460  1.8569290000000e-01
+478 460 -5.0000000000000e-01
+460 461  1.9167940000000e-04
+466 461  2.6684520000000e+00
+478 461  8.8948400000000e-01
+266 462  5.2397100000000e-01
+269 462  2.5902730000000e+00
+267 463  1.2090360000000e-01
+270 463  1.0000000000000e+00
+268 464  3.6607730000000e-01
+271 464  1.8323330000000e-02
+288 465  5.3070830000000e-01
+291 465  2.6120320000000e+00
+289 466  1.2143810000000e-01
+292 466  1.0000000000000e+00
+290 467  3.6327480000000e-01
+293 467  1.9398480000000e-02
+310 468  5.3114850000000e-01
+313 468  2.6134470000000e+00
+311 469  1.2147310000000e-01
+314 469  1.0000000000000e+00
+312 470  3.6309170000000e-01
+315 470  1.9470450000000e-02
+332 471  5.3131620000000e-01
+335 471  2.6139860000000e+00
+333 472  1.2148640000000e-01
+336 472  1.0000000000000e+00
+334 473  3.6302190000000e-01
+337 473  1.9497930000000e-02
+354 474  5.3753340000000e-01
+357 474  2.6338800000000e+00
+355 475  1.2197960000000e-01
+358 475  1.0000000000000e+00
+356 476  3.6043580000000e-01
+359 476  2.0538460000000e-02
+376 477  7.1092830000000e-01
+379 477  3.1304670000000e+00
+377 478  1.3573580000000e-01
+380 478  1.0000000000000e+00
+378 479  2.8830910000000e-01
+381 479  7.1489880000000e-02
--- a/examples/module.mk	Tue Jul 07 18:34:23 2020 -0400
+++ b/examples/module.mk	Tue Jul 07 19:40:20 2020 -0400
@@ -1,84 +1,9 @@
 %canon_reldir%_EXTRA_DIST =
 
-%canon_reldir%_CLEANFILES =
-%canon_reldir%_DISTCLEANFILES =
-%canon_reldir%_MAINTAINERCLEANFILES =
-
-%canon_reldir%_data_SRC = \
-   %reldir%/data/penny.mat
-
-octdata_DATA += \
-  $(%canon_reldir%_data_SRC)
-
-%canon_reldir%_code_SRC = \
-  %reldir%/code/@FIRfilter/FIRfilter.m \
-  %reldir%/code/@FIRfilter/FIRfilter_aggregation.m \
-  %reldir%/code/@FIRfilter/display.m \
-  %reldir%/code/@FIRfilter/subsasgn.m \
-  %reldir%/code/@FIRfilter/subsref.m \
-  %reldir%/code/@polynomial/disp.m \
-  %reldir%/code/@polynomial/double.m \
-  %reldir%/code/@polynomial/end.m \
-  %reldir%/code/@polynomial/get.m \
-  %reldir%/code/@polynomial/mtimes.m \
-  %reldir%/code/@polynomial/numel.m \
-  %reldir%/code/@polynomial/plot.m \
-  %reldir%/code/@polynomial/polynomial.m \
-  %reldir%/code/@polynomial/polynomial_superiorto.m \
-  %reldir%/code/@polynomial/polyval.m \
-  %reldir%/code/@polynomial/roots.m \
-  %reldir%/code/@polynomial/set.m \
-  %reldir%/code/@polynomial/subsasgn.m \
-  %reldir%/code/@polynomial/subsref.m \
-  %reldir%/code/addtwomatrices.cc \
-  %reldir%/code/celldemo.cc \
-  %reldir%/code/embedded.cc \
-  %reldir%/code/fortrandemo.cc \
-  %reldir%/code/fortransub.f \
-  %reldir%/code/funcdemo.cc \
-  %reldir%/code/globaldemo.cc \
-  %reldir%/code/helloworld.cc \
-  %reldir%/code/make_int.cc \
-  %reldir%/code/mex_demo.c \
-  %reldir%/code/mycell.c \
-  %reldir%/code/myfeval.c \
-  %reldir%/code/myfevalf.f \
-  %reldir%/code/myfunc.c \
-  %reldir%/code/myhello.c \
-  %reldir%/code/mypow2.c \
-  %reldir%/code/myprop.c \
-  %reldir%/code/myset.c \
-  %reldir%/code/mysparse.c \
-  %reldir%/code/mystring.c \
-  %reldir%/code/mystruct.c \
-  %reldir%/code/oct_demo.cc \
-  %reldir%/code/oregonator.cc \
-  %reldir%/code/oregonator.m \
-  %reldir%/code/paramdemo.cc \
-  %reldir%/code/polynomial2.m \
-  %reldir%/code/standalone.cc \
-  %reldir%/code/standalonebuiltin.cc \
-  %reldir%/code/stringdemo.cc \
-  %reldir%/code/structdemo.cc \
-  %reldir%/code/unwinddemo.cc
+include %reldir%/code/module.mk
+include %reldir%/data/module.mk
 
 %canon_reldir%_EXTRA_DIST += \
-  $(%canon_reldir%_data_SRC) \
-  $(%canon_reldir%_code_SRC) \
-  %reldir%/code/COPYING \
-  %reldir%/module.mk
+  %reldir%/code/COPYING
 
 EXTRA_DIST += $(%canon_reldir%_EXTRA_DIST)
-
-CLEANFILES += $(%canon_reldir%_CLEANFILES)
-DISTCLEANFILES += $(%canon_reldir%_DISTCLEANFILES)
-MAINTAINERCLEANFILES += $(%canon_reldir%_MAINTAINERCLEANFILES)
-
-examples-clean:
-	rm -f $(%canon_reldir%_CLEANFILES)
-
-examples-distclean: examples-clean
-	rm -f $(%canon_reldir%_DISTCLEANFILES)
-
-examples-maintainer-clean: examples-distclean
-	rm -f $(%canon_reldir%_MAINTAINERCLEANFILES)
--- a/libgui/graphics/BaseControl.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libgui/graphics/BaseControl.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -50,18 +50,30 @@
     if (props.style_is ("edit")
         || props.style_is ("listbox"))
       {
-        p.setColor (QPalette::Base,
-                    Utils::fromRgb (props.get_backgroundcolor_rgb ()));
-        p.setColor (QPalette::Text,
+        Matrix bg_color = props.get_backgroundcolor_rgb ();
+        // Matlab compatibility: Default color is ignored, and rendered as
+        // white ([1.0, 1.0, 1.0]).  See bug #58261.
+        if (bg_color(0) == bg_color(1) && bg_color(0) == bg_color(2)
+            && (std::abs (bg_color(1) - 0.94) < .005))
+          bg_color.fill (1.0);
+
+        p.setColor (QPalette::Active, QPalette::Base,
+                    Utils::fromRgb (bg_color));
+        p.setColor (QPalette::Inactive, QPalette::Base,
+                    Utils::fromRgb (bg_color));
+        p.setColor (QPalette::Active, QPalette::Text,
+                    Utils::fromRgb (props.get_foregroundcolor_rgb ()));
+        p.setColor (QPalette::Inactive, QPalette::Text,
                     Utils::fromRgb (props.get_foregroundcolor_rgb ()));
       }
     else if (props.style_is ("popupmenu"))
       {
-        // popumenu (QComboBox) is a listbox with a button, so needs set colors for both
+        // popupmenu (QComboBox) is a listbox with a button.
+        // This requires setting colors for both.
         QColor bcol = Utils::fromRgb (props.get_backgroundcolor_rgb ());
         QColor fcol = Utils::fromRgb (props.get_foregroundcolor_rgb ());
-        QString qss = QString ("background: %1 none;\n"
-                               "color: %2;")
+        QString qss = QString (":enabled { background: %1 none;\n"
+                                          "color: %2; }")
                       .arg(bcol.name ()).arg (fcol.name ());
         w->setStyleSheet(qss);
         return;
@@ -69,9 +81,13 @@
     else if (props.style_is ("radiobutton")
              || props.style_is ("checkbox"))
       {
-        p.setColor (QPalette::Button,
+        p.setColor (QPalette::Active, QPalette::Button,
+                    Utils::fromRgb (props.get_backgroundcolor_rgb ()));
+        p.setColor (QPalette::Inactive, QPalette::Button,
                     Utils::fromRgb (props.get_backgroundcolor_rgb ()));
-        p.setColor (QPalette::WindowText,
+        p.setColor (QPalette::Active, QPalette::WindowText,
+                    Utils::fromRgb (props.get_foregroundcolor_rgb ()));
+        p.setColor (QPalette::Inactive, QPalette::WindowText,
                     Utils::fromRgb (props.get_foregroundcolor_rgb ()));
       }
     else if (props.style_is ("pushbutton")
@@ -79,17 +95,21 @@
       {
         QColor bcol = Utils::fromRgb (props.get_backgroundcolor_rgb ());
         QColor fcol = Utils::fromRgb (props.get_foregroundcolor_rgb ());
-        QString qss = QString ("background: %1 none;\n"
-                               "color: %2;")
+        QString qss = QString (":enabled { background: %1 none;\n"
+                                          "color: %2; }")
                       .arg(bcol.name ()).arg (fcol.name ());
         w->setStyleSheet(qss);
         return;
       }
     else
       {
-        p.setColor (QPalette::Window,
+        p.setColor (QPalette::Active, QPalette::Window,
+                    Utils::fromRgb (props.get_backgroundcolor_rgb ()));
+        p.setColor (QPalette::Inactive, QPalette::Window,
                     Utils::fromRgb (props.get_backgroundcolor_rgb ()));
-        p.setColor (QPalette::WindowText,
+        p.setColor (QPalette::Active, QPalette::WindowText,
+                    Utils::fromRgb (props.get_foregroundcolor_rgb ()));
+        p.setColor (QPalette::Inactive, QPalette::WindowText,
                     Utils::fromRgb (props.get_foregroundcolor_rgb ()));
       }
 
@@ -119,7 +139,10 @@
                     octave::math::round (bb(2)), octave::math::round (bb(3)));
     w->setFont (Utils::computeFont<uicontrol> (up, bb(3)));
     updatePalette (up, w);
-    w->setEnabled (up.enable_is ("on"));
+    if (up.enable_is ("inactive"))
+      w->blockSignals (true);
+    else
+      w->setEnabled (up.enable_is ("on"));
     w->setToolTip (Utils::fromStdString (up.get_tooltipstring ()));
     w->setVisible (up.is_visible ());
     m_keyPressHandlerDefined = ! up.get_keypressfcn ().isempty ();
@@ -174,7 +197,16 @@
         break;
 
       case uicontrol::properties::ID_ENABLE:
-        w->setEnabled (up.enable_is ("on"));
+        if (up.enable_is ("inactive"))
+          {
+            w->blockSignals (true);
+            w->setEnabled (true);
+          }
+        else
+          {
+            w->blockSignals (false);
+            w->setEnabled (up.enable_is ("on"));
+          }
         break;
 
       case uicontrol::properties::ID_TOOLTIPSTRING:
--- a/libgui/graphics/Canvas.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libgui/graphics/Canvas.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -371,11 +371,7 @@
 
             r.adjust (-5, -5, 5, 5);
 
-#if defined (HAVE_QMOUSEEVENT_LOCALPOS)
             bool rect_contains_pos = r.contains (event->localPos ());
-#else
-            bool rect_contains_pos = r.contains (event->posF ());
-#endif
             if (rect_contains_pos)
               {
                 currentObj = childObj;
@@ -429,11 +425,7 @@
                 // the axes and still select it.
                 r.adjust (-20, -20, 20, 20);
 
-#if defined (HAVE_QMOUSEEVENT_LOCALPOS)
                 bool rect_contains_pos = r.contains (event->localPos ());
-#else
-                bool rect_contains_pos = r.contains (event->posF ());
-#endif
                 if (rect_contains_pos)
                   axesObj = *it;
               }
--- a/libgui/graphics/CheckBoxControl.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libgui/graphics/CheckBoxControl.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -61,10 +61,37 @@
                                     const graphics_object& go, QCheckBox *box)
     : ButtonControl (oct_obj, interp, go, box)
   {
+    uicontrol::properties& up = properties<uicontrol> ();
+
     box->setAutoFillBackground (true);
+    if (up.enable_is ("inactive"))
+      box->setCheckable (false);
   }
 
   CheckBoxControl::~CheckBoxControl (void)
   { }
 
+  void
+  CheckBoxControl::update (int pId)
+  {
+    uicontrol::properties& up = properties<uicontrol> ();
+    QCheckBox *box = qWidget<QCheckBox> ();
+
+    switch (pId)
+      {
+      case uicontrol::properties::ID_ENABLE:
+        {
+          if (up.enable_is ("inactive"))
+            box->setCheckable (false);
+          else
+            box->setCheckable (true);
+          ButtonControl::update (pId);
+        }
+        break;
+
+      default:
+        ButtonControl::update (pId);
+        break;
+      }
+  }
 };
--- a/libgui/graphics/CheckBoxControl.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libgui/graphics/CheckBoxControl.h	Tue Jul 07 19:40:20 2020 -0400
@@ -50,6 +50,9 @@
     static CheckBoxControl *
     create (octave::base_qobject& oct_qobj, octave::interpreter& interp,
             const graphics_object& go);
+
+  protected:
+    void update (int pId);
   };
 
 }
--- a/libgui/graphics/EditControl.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libgui/graphics/EditControl.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -85,6 +85,10 @@
 
     uicontrol::properties& up = properties<uicontrol> ();
 
+    if (up.enable_is ("inactive"))
+      edit->setReadOnly (true);
+    else
+      edit->setEnabled (up.enable_is ("on"));
     edit->setText (Utils::fromStdString (up.get_string_string ()));
     edit->setAlignment (Utils::fromHVAlign (up.get_horizontalalignment (),
                                             up.get_verticalalignment ()));
@@ -117,9 +121,15 @@
 
     uicontrol::properties& up = properties<uicontrol> ();
 
+    if (up.enable_is ("inactive"))
+      edit->setReadOnly (true);
+    else
+      edit->setEnabled (up.enable_is ("on"));
     edit->setAcceptRichText (false);
     edit->setPlainText (Utils::fromStringVector
                         (up.get_string_vector ()).join ("\n"));
+    edit->setAlignment (Utils::fromHVAlign (up.get_horizontalalignment (),
+                                            up.get_verticalalignment ()));
 
     connect (edit, SIGNAL (textChanged (void)),
              SLOT (textChanged (void)));
@@ -177,6 +187,16 @@
                                                 up.get_verticalalignment ()));
         return true;
 
+      case uicontrol::properties::ID_ENABLE:
+        if (up.enable_is ("inactive"))
+          edit->setReadOnly (true);
+        else
+          {
+            edit->setReadOnly (false);
+            edit->setEnabled (up.enable_is ("on"));
+          }
+        return true;
+
       case uicontrol::properties::ID_MIN:
       case uicontrol::properties::ID_MAX:
         if ((up.get_max () - up.get_min ()) > 1)
@@ -208,6 +228,22 @@
                             (up.get_string_vector ()).join ("\n"));
         return true;
 
+      case uicontrol::properties::ID_HORIZONTALALIGNMENT:
+      case uicontrol::properties::ID_VERTICALALIGNMENT:
+        edit->setAlignment (Utils::fromHVAlign (up.get_horizontalalignment (),
+                                                up.get_verticalalignment ()));
+        return true;
+
+      case uicontrol::properties::ID_ENABLE:
+        if (up.enable_is ("inactive"))
+          edit->setReadOnly (true);
+        else
+          {
+            edit->setReadOnly (false);
+            edit->setEnabled (up.enable_is ("on"));
+          }
+        return true;
+
       case uicontrol::properties::ID_MIN:
       case uicontrol::properties::ID_MAX:
         if ((up.get_max () - up.get_min ()) <= 1)
--- a/libgui/graphics/PushButtonControl.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libgui/graphics/PushButtonControl.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -71,6 +71,7 @@
     QImage img = Utils::makeImageFromCData (cdat,
                                             cdat.columns (), cdat.rows ());
     btn->setIcon (QIcon (QPixmap::fromImage (img)));
+    btn->setIconSize (QSize (cdat.columns (), cdat.rows ()));
   }
 
   PushButtonControl::~PushButtonControl (void)
--- a/libgui/graphics/QtHandlesUtils.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libgui/graphics/QtHandlesUtils.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -288,8 +288,12 @@
           int w = qMin (dv(1), static_cast<octave_idx_type> (width));
           int h = qMin (dv(0), static_cast<octave_idx_type> (height));
 
-          int x_off = (w < width ? (width - w) / 2 : 0);
-          int y_off = (h < height ? (height - h) / 2 : 0);
+          // If size mismatch, take data from center of CDATA and
+          // place in in center of QImage.
+          int x_img_off = (w < width ? (width - w) / 2 : 0);
+          int y_img_off = (h < height ? (height - h) / 2 : 0);
+          int x_cdat_off = (dv(1) > w ? (dv(1) - w) / 2 : 0);
+          int y_cdat_off = (dv(0) > h ? (dv(0) - h) / 2 : 0);
 
           QImage img (width, height, QImage::Format_ARGB32);
           img.fill (qRgba (0, 0, 0, 0));
@@ -298,23 +302,25 @@
             {
               uint8NDArray d = v.uint8_array_value ();
 
-              for (int i = 0; i < w; i++)
-                for (int j = 0; j < h; j++)
+              for (int i = x_cdat_off; i < w + x_cdat_off; i++)
+                for (int j = y_cdat_off; j < h + y_cdat_off; j++)
                   {
                     int r = d(j, i, 0);
                     int g = d(j, i, 1);
                     int b = d(j, i, 2);
                     int a = 255;
 
-                    img.setPixel (x_off + i, y_off + j, qRgba (r, g, b, a));
+                    img.setPixel (x_img_off + i - x_cdat_off,
+                                  y_img_off + j - y_cdat_off,
+                                  qRgba (r, g, b, a));
                   }
             }
           else if (v.is_single_type ())
             {
               FloatNDArray f = v.float_array_value ();
 
-              for (int i = 0; i < w; i++)
-                for (int j = 0; j < h; j++)
+              for (int i = x_cdat_off; i < w + x_cdat_off; i++)
+                for (int j = y_cdat_off; j < h + y_cdat_off; j++)
                   {
                     float r = f(j, i, 0);
                     float g = f(j, i, 1);
@@ -322,7 +328,8 @@
                     int a = (octave::math::isnan (r) || octave::math::isnan (g)
                              || octave::math::isnan (b) ? 0 : 255);
 
-                    img.setPixel (x_off + i, y_off + j,
+                    img.setPixel (x_img_off + i - x_cdat_off,
+                                  y_img_off + j - y_cdat_off,
                                   qRgba (octave::math::round (r * 255),
                                          octave::math::round (g * 255),
                                          octave::math::round (b * 255),
@@ -333,8 +340,8 @@
             {
               NDArray d = v.array_value ();
 
-              for (int i = 0; i < w; i++)
-                for (int j = 0; j < h; j++)
+              for (int i = x_cdat_off; i < w + x_cdat_off; i++)
+                for (int j = y_cdat_off; j < h + y_cdat_off; j++)
                   {
                     double r = d(j, i, 0);
                     double g = d(j, i, 1);
@@ -342,7 +349,8 @@
                     int a = (octave::math::isnan (r) || octave::math::isnan (g)
                              || octave::math::isnan (b) ? 0 : 255);
 
-                    img.setPixel (x_off + i, y_off + j,
+                    img.setPixel (x_img_off + i - x_cdat_off,
+                                  y_img_off + j - y_cdat_off,
                                   qRgba (octave::math::round (r * 255),
                                          octave::math::round (g * 255),
                                          octave::math::round (b * 255),
@@ -394,12 +402,7 @@
 
       // We assume a standard mouse with 15 degree steps and Qt returns
       // 1/8 of a degree.
-#if defined (HAVE_QWHEELEVENT_ANGLEDELTA)
       int ydelta = -(event->angleDelta().y ());
-#else
-      int ydelta = (event->orientation () == Qt::Vertical
-                    ? -(event->delta ()) : 0);
-#endif
       retval.setfield ("VerticalScrollCount", octave_value (ydelta / 120));
 
       // FIXME: Is there any way to access the number of lines a scroll step
--- a/libgui/graphics/RadioButtonControl.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libgui/graphics/RadioButtonControl.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -69,11 +69,39 @@
     if (btnGroup)
       btnGroup->addButton (radio);
 
+    uicontrol::properties& up = properties<uicontrol> ();
+
     radio->setAutoFillBackground (true);
     radio->setAutoExclusive (false);
+    if (up.enable_is ("inactive"))
+      radio->setCheckable (false);
   }
 
   RadioButtonControl::~RadioButtonControl (void)
   { }
 
+  void
+  RadioButtonControl::update (int pId)
+  {
+    uicontrol::properties& up = properties<uicontrol> ();
+    QRadioButton *btn = qWidget<QRadioButton> ();
+
+    switch (pId)
+      {
+      case uicontrol::properties::ID_ENABLE:
+        {
+          if (up.enable_is ("inactive"))
+            btn->setCheckable (false);
+          else
+            btn->setCheckable (true);
+          ButtonControl::update (pId);
+        }
+        break;
+
+      default:
+        ButtonControl::update (pId);
+        break;
+      }
+  }
+
 };
--- a/libgui/graphics/RadioButtonControl.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libgui/graphics/RadioButtonControl.h	Tue Jul 07 19:40:20 2020 -0400
@@ -50,6 +50,9 @@
     static RadioButtonControl * create (octave::base_qobject& oct_qobj,
                                         octave::interpreter& interp,
                                         const graphics_object& go);
+
+  protected:
+    void update (int pId);
   };
 
 }
--- a/libgui/graphics/Table.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libgui/graphics/Table.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -1321,11 +1321,7 @@
                                      : QAbstractItemView::NoSelection);
 
     // Set rearrangeablecolumns
-    #if defined (HAVE_QT4)
-      m_tableWidget->horizontalHeader ()->setMovable (enabled && rearrangeableColumns);
-    #elif defined (HAVE_QT5)
-      m_tableWidget->horizontalHeader ()->setSectionsMovable (enabled && rearrangeableColumns);
-    #endif
+    m_tableWidget->horizontalHeader ()->setSectionsMovable (enabled && rearrangeableColumns);
     m_tableWidget->horizontalHeader ()->setDragEnabled (enabled && rearrangeableColumns);
     m_tableWidget->horizontalHeader ()->setDragDropMode (QAbstractItemView::InternalMove);
 
@@ -1504,11 +1500,7 @@
     bool rearrangeableColumns = tp.is_rearrangeablecolumns ();
     bool enabled = tp.is_enable ();
 
-  #if defined (HAVE_QT4)
-    m_tableWidget->horizontalHeader ()->setMovable (enabled && rearrangeableColumns);
-  #elif defined (HAVE_QT5)
     m_tableWidget->horizontalHeader ()->setSectionsMovable (enabled && rearrangeableColumns);
-  #endif
     m_tableWidget->horizontalHeader ()->setDragEnabled (enabled && rearrangeableColumns);
     m_tableWidget->horizontalHeader ()->setDragDropMode (QAbstractItemView::InternalMove);
   }
--- a/libgui/graphics/ToggleButtonControl.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libgui/graphics/ToggleButtonControl.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -77,6 +77,7 @@
     QImage img = Utils::makeImageFromCData (cdat,
                                             cdat.columns (), cdat.rows ());
     btn->setIcon (QIcon (QPixmap::fromImage (img)));
+    btn->setIconSize (QSize (cdat.columns (), cdat.rows ()));
   }
 
   ToggleButtonControl::~ToggleButtonControl (void)
--- a/libgui/graphics/ToolBarButton.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libgui/graphics/ToolBarButton.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -49,7 +49,7 @@
     action->setVisible (tp.is_visible ());
 
     // Get the icon data from cdata or as a named icon
-    QImage img = Utils::makeImageFromCData (tp.get_cdata (), 32, 32);
+    QImage img = Utils::makeImageFromCData (tp.get_cdata (), 24, 24);
 
     if (img.width () == 0)
       {
@@ -104,7 +104,7 @@
       case T::properties::ID_CDATA:
         {
           // Get the icon data from cdata or as a named icon
-          QImage img = Utils::makeImageFromCData (tp.get_cdata (), 32, 32);
+          QImage img = Utils::makeImageFromCData (tp.get_cdata (), 24, 24);
 
           if (img.width () == 0)
             {
--- a/libgui/graphics/qt-graphics-toolkit.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libgui/graphics/qt-graphics-toolkit.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -121,7 +121,7 @@
   qt_graphics_toolkit::initialize (const graphics_object& go)
   {
     if (go.isa ("figure")
-        || go.isa ("uicontrol")
+        || (go.isa ("uicontrol") && go.get ("style").string_value () != "frame")
         || go.isa ("uipanel")
         || go.isa ("uibuttongroup")
         || go.isa ("uimenu")
@@ -131,7 +131,7 @@
         || go.isa ("uipushtool")
         || go.isa ("uitoggletool"))
       {
-        // FIXME: We need to unlock the mutex here but we have no way to know if
+        // FIXME: We need to unlock the mutex here but we have no way to know
         // if it was previously locked by this thread, and thus if we should
         // re-lock it.
 
--- a/libgui/src/files-dock-widget.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libgui/src/files-dock-widget.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -245,16 +245,8 @@
         (settings->value (fb_column_state.key).toByteArray ());
 
     // Set header properties for sorting
-#if defined (HAVE_QHEADERVIEW_SETSECTIONSCLICKABLE)
     m_file_tree_view->header ()->setSectionsClickable (true);
-#else
-    m_file_tree_view->header ()->setClickable (true);
-#endif
-#if defined (HAVE_QHEADERVIEW_SETSECTIONSMOVABLE)
     m_file_tree_view->header ()->setSectionsMovable (true);
-#else
-    m_file_tree_view->header ()->setMovable (true);
-#endif
     m_file_tree_view->header ()->setSortIndicatorShown (true);
 
     QStringList mru_dirs =
@@ -720,17 +712,38 @@
     QItemSelectionModel *m = m_file_tree_view->selectionModel ();
     QModelIndexList rows = m->selectedRows ();
 
+    int file_cnt = rows.size ();
+    bool multiple_files = (file_cnt > 1);
+
     for (auto it = rows.begin (); it != rows.end (); it++)
       {
         QModelIndex index = *it;
 
         QFileInfo info = m_file_system_model->fileInfo (index);
 
-        if (QMessageBox::question (this, tr ("Delete file/directory"),
-                                   tr ("Are you sure you want to delete\n")
-                                   + info.filePath (),
-                                   QMessageBox::Yes | QMessageBox::No)
-            == QMessageBox::Yes)
+        QMessageBox::StandardButton dlg_answer;
+        if (multiple_files)
+          if (it == rows.begin ())
+            {
+               dlg_answer = QMessageBox::question (this,
+                              tr ("Delete file/directory"),
+                              tr ("Are you sure you want to delete all %1 selected files?\n").arg (file_cnt),
+                              QMessageBox::Yes | QMessageBox::No);
+               if (dlg_answer != QMessageBox::Yes)
+                 return;
+            }
+          else
+            dlg_answer = QMessageBox::Yes;
+        else
+          {
+            dlg_answer = QMessageBox::question (this,
+                           tr ("Delete file/directory"),
+                           tr ("Are you sure you want to delete\n")
+                           + info.filePath (),
+                           QMessageBox::Yes | QMessageBox::No);
+          }
+
+        if (dlg_answer)
           {
             if (info.isDir ())
               {
--- a/libgui/src/find-files-dialog.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libgui/src/find-files-dialog.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -126,11 +126,7 @@
     m_file_list->setSortingEnabled (true);
     m_file_list->horizontalHeader ()->restoreState (settings->value (ff_column_state.key).toByteArray ());
     m_file_list->horizontalHeader ()->setSortIndicatorShown (true);
-#if defined (HAVE_QHEADERVIEW_SETSECTIONSCLICKABLE)
     m_file_list->horizontalHeader ()->setSectionsClickable (true);
-#else
-    m_file_list->horizontalHeader ()->setClickable (true);
-#endif
     m_file_list->horizontalHeader ()->setStretchLastSection (true);
     m_file_list->sortByColumn (settings->value (ff_sort_files_by_column).toInt (),
                                static_cast<Qt::SortOrder>
--- a/libgui/src/gui-preferences-ed.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libgui/src/gui-preferences-ed.h	Tue Jul 07 19:40:20 2020 -0400
@@ -215,6 +215,12 @@
 const gui_pref
 ed_notebook_tab_width_max ("editor/notebook_tab_width_max", QVariant (300));
 
+const gui_pref
+ed_force_newline ("editor/force_newline", QVariant (true));
+
+const gui_pref
+ed_rm_trailing_spaces ("editor/rm_trailing_spaces", QVariant (true));
+
 #if defined (HAVE_QSCINTILLA)
 #if defined (Q_OS_WIN32)
 const int os_eol_mode = QsciScintilla::EolWindows;
--- a/libgui/src/gui-preferences-global.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libgui/src/gui-preferences-global.h	Tue Jul 07 19:40:20 2020 -0400
@@ -136,4 +136,13 @@
 const gui_pref
 global_proxy_pass ("proxyPassword", QVariant (QString ()));
 
+const QStringList
+global_proxy_all_types (QStringList ()
+             << "HttpProxy"
+             << "Socks5Proxy"
+             << QT_TRANSLATE_NOOP ("octave::settings_dialog", "Environment Variables")
+);
+const QList<int>
+global_proxy_manual_types (QList<int> () << 0 << 1);
+
 #endif
--- a/libgui/src/m-editor/file-editor-tab.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libgui/src/m-editor/file-editor-tab.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -44,6 +44,7 @@
 #include <QMessageBox>
 #include <QPrintDialog>
 #include <QPushButton>
+#include <QScrollBar>
 #include <QStyle>
 #include <QTextBlock>
 #include <QTextCodec>
@@ -1834,7 +1835,23 @@
     QApplication::setOverrideCursor (Qt::WaitCursor);
 
     // read the file binary, decoding later
-    const QByteArray text_data = file.readAll ();
+    QByteArray text_data = file.readAll ();
+
+    // remove newline at end of file if we add one again when saving
+    resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
+    gui_settings *settings = rmgr.get_settings ();
+
+    if (settings->value (ed_force_newline).toBool ())
+      {
+        const QByteArray eol_lf = QByteArray (1,0x0a);
+        const QByteArray eol_cr = QByteArray (1,0x0d);
+
+        if (text_data.endsWith (eol_lf))
+          text_data.chop (1);   // remove LF
+
+        if (text_data.endsWith (eol_cr)) // remove CR (altogether CRLF, too)
+          text_data.chop (1);
+      }
 
     // decode
     QTextCodec::ConverterState st;
@@ -2256,10 +2273,23 @@
     if (! codec)
       return;   // No valid codec
 
+    // Remove trailing white spaces if desired
+    resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
+    gui_settings *settings = rmgr.get_settings ();
+
+    if (settings->value (ed_rm_trailing_spaces).toBool ())
+      m_edit_area->replace_all ("[ \\t]+$", "", true, false, false);
+
+    // Save the file
     out.setCodec (codec);
 
     QApplication::setOverrideCursor (Qt::WaitCursor);
+
     out << m_edit_area->text ();
+    if (settings->value (ed_force_newline).toBool ()
+        && m_edit_area->text ().length ())
+      out << m_edit_area->eol_string ();   // Add newline if desired
+
     out.flush ();
     QApplication::restoreOverrideCursor ();
     file.flush ();
@@ -2476,9 +2506,6 @@
 
   void file_editor_tab::handle_save_file_as_answer (const QString& saveFileName)
   {
-    if (m_save_as_desired_eol != m_edit_area->eolMode ())
-      convert_eol (this,m_save_as_desired_eol);
-
     if (saveFileName == m_file_name)
       {
         save_file (saveFileName);
@@ -2495,13 +2522,6 @@
 
   void file_editor_tab::handle_save_file_as_answer_close (const QString& saveFileName)
   {
-    if (m_save_as_desired_eol != m_edit_area->eolMode ())
-      {
-        m_edit_area->setReadOnly (false);  // was set to read-only in save_file_as
-        convert_eol (this,m_save_as_desired_eol);
-        m_edit_area->setReadOnly (true);   // restore read-only mode
-      }
-
     // saveFileName == m_file_name can not happen, because we only can get here
     // when we close a tab and m_file_name is not a valid filename yet
 
@@ -3152,7 +3172,7 @@
 
                 // remember first visible line and x-offset for restoring the view afterwards
                 int first_line = m_edit_area->firstVisibleLine ();
-                int x_offset = m_edit_area->SendScintilla(QsciScintillaBase::SCI_GETXOFFSET);
+                int x_offset = m_edit_area->SendScintilla (QsciScintillaBase::SCI_GETXOFFSET);
 
                 // search for first occurrence of the detected word
                 bool find_result_available
@@ -3187,7 +3207,7 @@
                 // restore the visible area of the file, the cursor position,
                 // and the selection
                 m_edit_area->setFirstVisibleLine (first_line);
-                m_edit_area->SendScintilla(QsciScintillaBase::SCI_SETXOFFSET, x_offset);
+                m_edit_area->SendScintilla (QsciScintillaBase::SCI_SETXOFFSET, x_offset);
                 m_edit_area->setCursorPosition (line, col);
                 m_edit_area->setSelection (line, col - wlen, line, col);
                 m_edit_area->set_word_selection (word);
--- a/libgui/src/m-editor/file-editor.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libgui/src/m-editor/file-editor.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -75,9 +75,7 @@
 
     setTabsClosable (true);
     setUsesScrollButtons (true);
-#if defined (HAVE_QTABWIDGET_SETMOVABLE)
     setMovable (true);
-#endif
   }
 
   tab_bar * file_editor_tab_widget::get_tab_bar (void) const
--- a/libgui/src/m-editor/find-dialog.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libgui/src/m-editor/find-dialog.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -381,21 +381,7 @@
         int lbeg, lend, cbeg, cend;
         _edit_area->getSelection (&lbeg,&cbeg,&lend,&cend);
         if (lbeg == lend)
-#if defined (HAVE_QCOMBOBOX_SETCURRENTTEXT)
           _search_line_edit->setCurrentText (_edit_area->selectedText ());
-#else
-          if (_search_line_edit->isEditable ())
-            {
-              _search_line_edit->setEditText (_edit_area->selectedText ());
-            }
-          else
-            {
-              int i = _search_line_edit->findText (_edit_area->selectedText ());
-
-              if (i > -1)
-                _search_line_edit->setCurrentIndex (i);
-            }
-#endif
       }
 
     // set focus to "Find what" and select all text
--- a/libgui/src/m-editor/octave-qscintilla.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libgui/src/m-editor/octave-qscintilla.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -381,6 +381,22 @@
     markerDeleteAll (marker::selection);
   }
 
+  QString octave_qscintilla::eol_string (void)
+  {
+    switch (eolMode ())
+      {
+      case QsciScintilla::EolWindows:
+        return ("\r\n");
+      case QsciScintilla::EolMac:
+        return ("\r");
+      case QsciScintilla::EolUnix:
+        return ("\n");
+      }
+
+    // Last resort, if the above goes wrong (should never happen)
+    return ("\r\n");
+  }
+
   // Function returning the true cursor position where the tab length
   // is taken into account.
   void octave_qscintilla::get_current_position (int *pos, int *line, int *col)
@@ -1062,6 +1078,47 @@
     QToolTip::showText (global_pos, msg);
   }
 
+  void octave_qscintilla::replace_all (const QString& o_str, const QString& n_str,
+                                       bool re, bool cs, bool wo)
+  {
+    // get the resulting cursor position
+    int pos, line, col, nline, ncol;
+    get_current_position (&pos, &line, &col);
+
+    // remember first visible line for restoring the view afterwards
+    int first_line = firstVisibleLine ();
+
+    // search for first occurrence of the detected word
+    bool find_result_available = findFirst (o_str, re, cs, wo,
+                                            false, true, 0, 0);
+    // replace and find more occurrences in a loop
+    beginUndoAction ();
+    while (find_result_available)
+      {
+        // findNext doesn't work properly if the length of the replacement
+        // text is different from the original
+        replace (n_str);
+        get_current_position (&pos, &nline, &ncol);
+
+        find_result_available = findFirst (o_str, re, cs, wo,
+                                           false, true, nline, ncol);
+      }
+    endUndoAction ();
+
+      // restore the visible area
+      setFirstVisibleLine (first_line);
+
+      // fix cursor column if outside of new line length
+      int eol_len = eol_string ().length ();
+      if (line == lines () - 1)
+        eol_len = 0;
+      const int col_max = text (line).length () - eol_len;
+      if (col_max < col)
+        col = col_max;
+
+      setCursorPosition (line, col);
+  }
+
   void octave_qscintilla::keyPressEvent (QKeyEvent *key_event)
   {
     if (m_selection.isEmpty ())
@@ -1073,59 +1130,8 @@
 
         if (key == Qt::Key_Return && modifiers == Qt::ShiftModifier)
           {
-            // get the resulting cursor position
-            // (required if click was beyond a line ending)
-            int pos, line, col;
-            get_current_position (&pos, &line, &col);
-
-            // remember first visible line for restoring the view afterwards
-            int first_line = firstVisibleLine ();
-
-            // search for first occurrence of the detected word
-            bool find_result_available
-              = findFirst (m_selection,
-                           false,   // no regexp
-                           true,    // case sensitive
-                           true,    // whole words only
-                           false,   // do not wrap
-                           true,    // forward
-                           0, 0,    // from the beginning
-                           false
-#if defined (HAVE_QSCI_VERSION_2_6_0)
-                           , true
-#endif
-                          );
-
-            while (find_result_available)
-              {
-                replace (m_selection_replacement);
-
-                // FIXME: is this the right thing to do?  findNext doesn't
-                // work properly if the length of the replacement text is
-                // different from the original.
-
-                int new_line, new_col;
-                get_current_position (&pos, &new_line, &new_col);
-
-                find_result_available
-                  = findFirst (m_selection,
-                               false,   // no regexp
-                               true,    // case sensitive
-                               true,    // whole words only
-                               false,   // do not wrap
-                               true,    // forward
-                               new_line, new_col,    // from new pos
-                               false
-#if defined (HAVE_QSCI_VERSION_2_6_0)
-                               , true
-#endif
-                              );
-              }
-
-            // restore the visible area of the file, the cursor position,
-            // and the selection
-            setFirstVisibleLine (first_line);
-            setCursorPosition (line, col);
+            replace_all (m_selection, m_selection_replacement,
+                         false, true, true);
 
             // Clear the selection.
             set_word_selection ();
--- a/libgui/src/m-editor/octave-qscintilla.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libgui/src/m-editor/octave-qscintilla.h	Tue Jul 07 19:40:20 2020 -0400
@@ -65,6 +65,7 @@
     void get_global_textcursor_pos (QPoint *global_pos, QPoint *local_pos);
     bool get_actual_word (void);
     void clear_selection_markers (void);
+    QString eol_string (void);
     void get_current_position (int *pos, int *line, int *col);
     QStringList comment_string (bool comment = true);
     int get_style (int pos = -1);
@@ -80,6 +81,9 @@
 
     void set_selection_marker_color (const QColor& c);
 
+    void replace_all (const QString& o_str, const QString& n_str,
+                      bool re, bool cs, bool wo);
+
   signals:
 
     void execute_command_in_terminal_signal (const QString&);
--- a/libgui/src/main-window.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libgui/src/main-window.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -765,9 +765,7 @@
         QTextBrowser *browser
 
           = m_community_news_window->findChild<QTextBrowser *>("OctaveNews"
-#if defined (QOBJECT_FINDCHILDREN_ACCEPTS_FINDCHILDOPTIONS)
                                                                , Qt::FindDirectChildrenOnly
-#endif
                                                               );
         if (browser)
           browser->setHtml (news);
--- a/libgui/src/octave-qobject.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libgui/src/octave-qobject.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -119,11 +119,7 @@
   // Disable all Qt messages by default.
 
   static void
-#if defined (QTMESSAGEHANDLER_ACCEPTS_QMESSAGELOGCONTEXT)
   message_handler (QtMsgType, const QMessageLogContext &, const QString &)
-#else
-  message_handler (QtMsgType, const char *)
-#endif
   { }
 
   //! Reimplement QApplication::notify.  Octave's own exceptions are
@@ -177,11 +173,7 @@
 
     if (show_gui_msgs.empty ())
       {
-#if defined (HAVE_QINSTALLMESSAGEHANDLER)
         qInstallMessageHandler (message_handler);
-#else
-        qInstallMsgHandler (message_handler);
-#endif
       }
 
     // Set the codec for all strings (before wizard or any GUI object)
@@ -189,10 +181,6 @@
     QTextCodec::setCodecForLocale (QTextCodec::codecForName ("UTF-8"));
 #endif
 
-#if defined (HAVE_QT4)
-    QTextCodec::setCodecForCStrings (QTextCodec::codecForName ("UTF-8"));
-#endif
-
     // Initialize global Qt application metadata.
 
     QCoreApplication::setApplicationName ("GNU Octave");
@@ -202,7 +190,6 @@
 
     qRegisterMetaType<octave_value_list> ("octave_value_list");
 
-
 // Bug #55940 (Disable App Nap on Mac)
 #if defined (Q_OS_MAC)
     // Mac App Nap feature causes pause() and sleep() to misbehave.
--- a/libgui/src/resource-manager.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libgui/src/resource-manager.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -27,6 +27,7 @@
 #  include "config.h"
 #endif
 
+#include <array>
 #include <string>
 
 #include <QDir>
@@ -216,13 +217,9 @@
   QString resource_manager::get_default_font_family (void)
   {
     // Get the default monospaced font
-#if defined (HAVE_QFONT_MONOSPACE)
     QFont fixed_font;
     fixed_font.setStyleHint (QFont::Monospace);
     QString default_family = fixed_font.defaultFamily ();
-#else
-    QString default_family = global_font_family;
-#endif
 
     std::string env_default_family = sys::env::getenv ("OCTAVE_DEFAULT_FONT");
     if (! env_default_family.empty ())
@@ -340,39 +337,108 @@
 
   void resource_manager::update_network_settings (void)
   {
-    if (m_settings)
+    if (! m_settings)
+      return;
+
+    QNetworkProxy proxy;
+
+    // Assume no proxy and empty proxy data
+    QNetworkProxy::ProxyType proxy_type = QNetworkProxy::NoProxy;
+    QString scheme;
+    QString host;
+    int port = 0;
+    QString user;
+    QString pass;
+    QUrl proxy_url = QUrl ();
+
+    if (m_settings->value (global_use_proxy.key, global_use_proxy.def).toBool ())
       {
-        QNetworkProxy::ProxyType proxyType = QNetworkProxy::NoProxy;
+        // Use a proxy, collect all required information
+        QString proxy_type_string
+            = m_settings->value (global_proxy_type.key, global_proxy_type.def).toString ();
 
-        if (m_settings->value (global_use_proxy.key, global_use_proxy.def).toBool ())
+        // The proxy type for the Qt proxy settings
+        if (proxy_type_string == "Socks5Proxy")
+          proxy_type = QNetworkProxy::Socks5Proxy;
+        else if (proxy_type_string == "HttpProxy")
+          proxy_type = QNetworkProxy::HttpProxy;
+
+        // The proxy data from the settings
+        if (proxy_type_string == "HttpProxy"
+            || proxy_type_string == "Socks5Proxy")
           {
-            QString proxyTypeString
-              = m_settings->value (global_proxy_type.key, global_proxy_type.def).toString ();
+            host = m_settings->value (global_proxy_host.key,
+                                      global_proxy_host.def).toString ();
+            port = m_settings->value (global_proxy_port.key,
+                                      global_proxy_port.def).toInt ();
+            user = m_settings->value (global_proxy_user.key,
+                                      global_proxy_user.def).toString ();
+            pass = m_settings->value (global_proxy_pass.key,
+                                      global_proxy_pass.def).toString ();
+            if (proxy_type_string == "HttpProxy")
+              scheme = "http";
+            else if (proxy_type_string == "Socks5Proxy")
+              scheme = "socks5";
 
-            if (proxyTypeString == "Socks5Proxy")
-              proxyType = QNetworkProxy::Socks5Proxy;
-            else if (proxyTypeString == "HttpProxy")
-              proxyType = QNetworkProxy::HttpProxy;
+            QUrl env_var_url = QUrl ();
+            proxy_url.setScheme (scheme);
+            proxy_url.setHost (host);
+            proxy_url.setPort (port);
+            if (! user.isEmpty ())
+              proxy_url.setUserName (user);
+            if (! pass.isEmpty ())
+              proxy_url.setPassword (pass);
           }
 
-        QNetworkProxy proxy;
+        // The proxy data from environment variables
+        if (proxy_type_string == global_proxy_all_types.at (2))
+          {
+            const std::array<std::string, 6> env_vars =
+                { "ALL_PROXY", "all_proxy",
+                  "HTTP_PROXY", "http_proxy",
+                  "HTTPS_PROXY", "https_proxy" };
+
+            unsigned int count = 0;
+            while (! proxy_url.isValid () && count < env_vars.size ())
+              {
+                proxy_url = QUrl (QString::fromStdString
+                                    (sys::env::getenv (env_vars[count])));
+                count++;
+              }
+
+            if (proxy_url.isValid ())
+              {
+                // Found an entry, get the data from the string
+                scheme = proxy_url.scheme ();
 
-        proxy.setType (proxyType);
-        proxy.setHostName (m_settings->value (global_proxy_host.key,
-                                              global_proxy_host.def).toString ());
-        proxy.setPort (m_settings->value (global_proxy_port.key,
-                                          global_proxy_port.def).toInt ());
-        proxy.setUser (m_settings->value (global_proxy_user.key,
-                                          global_proxy_user.def).toString ());
-        proxy.setPassword (m_settings->value (global_proxy_pass.key,
-                                              global_proxy_pass.def).toString ());
+                if (scheme.contains ("socks", Qt::CaseInsensitive))
+                  proxy_type = QNetworkProxy::Socks5Proxy;
+                else
+                  proxy_type = QNetworkProxy::HttpProxy;
+
+                host = proxy_url.host ();
+                port = proxy_url.port ();
+                user = proxy_url.userName ();
+                pass = proxy_url.password ();
+              }
+          }
+      }
 
-        QNetworkProxy::setApplicationProxy (proxy);
-      }
-    else
-      {
-        // FIXME: Is this an error?  If so, what should we do?
-      }
+    // Set proxy for Qt framework
+    proxy.setType (proxy_type);
+    proxy.setHostName (host);
+    proxy.setPort (port);
+    proxy.setUser (user);
+    proxy.setPassword (pass);
+
+    QNetworkProxy::setApplicationProxy (proxy);
+
+    // Set proxy for curl library if not based on environment variables
+    std::string proxy_url_str = proxy_url.toString().toStdString ();
+    sys::env::putenv ("http_proxy", proxy_url_str);
+    sys::env::putenv ("HTTP_PROXY", proxy_url_str);
+    sys::env::putenv ("https_proxy", proxy_url_str);
+    sys::env::putenv ("HTTPS_PROXY", proxy_url_str);
   }
 
   QIcon resource_manager::icon (const QString& icon_name, bool fallback)
--- a/libgui/src/settings-dialog.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libgui/src/settings-dialog.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -350,6 +350,8 @@
     editor_restoreSession->setChecked (settings->value (ed_restore_session).toBool ());
     editor_create_new_file->setChecked (settings->value (ed_create_new_file).toBool ());
     editor_reload_changed_files->setChecked (settings->value (ed_always_reload_changed_files).toBool ());
+    editor_force_newline->setChecked (settings->value (ed_force_newline).toBool ());
+    editor_remove_trailing_spaces->setChecked (settings->value (ed_rm_trailing_spaces).toBool ());
     editor_hiding_closes_files->setChecked (settings->value (ed_hiding_closes_files).toBool ());
     editor_show_dbg_file->setChecked (settings->value (ed_show_dbg_file).toBool ());
 
@@ -395,21 +397,33 @@
     le_file_browser_extensions->setText (settings->value (fb_txt_file_ext).toString ());
 
     checkbox_allow_web_connect->setChecked (settings->value (nr_allow_connection).toBool ());
-    useProxyServer->setChecked (
-        settings->value (global_use_proxy.key, global_use_proxy.def).toBool ());
-    proxyHostName->setText (settings->value (global_proxy_host.key, global_proxy_host.def).toString ());
 
-    int currentIndex = 0;
-    QString proxyTypeString = settings->value (global_proxy_type.key, global_proxy_type.def).toString ();
-    while ((currentIndex < proxyType->count ())
-           && (proxyType->currentText () != proxyTypeString))
+    // Proxy
+    bool use_proxy = settings->value (global_use_proxy.key, global_use_proxy.def).toBool ();
+    use_proxy_server->setChecked (use_proxy);
+    // Fill combo box and activate current one
+    QString proxy_type_string = settings->value (global_proxy_type.key, global_proxy_type.def).toString ();
+    proxy_type->addItems (global_proxy_all_types);
+    for (int i = 0; i < global_proxy_all_types.length (); i++)
       {
-        currentIndex++;
-        proxyType->setCurrentIndex (currentIndex);
+        if (proxy_type->itemText (i) == proxy_type_string)
+          {
+            proxy_type->setCurrentIndex (i);
+            break;
+          }
       }
-    proxyPort->setText (settings->value (global_proxy_port.key, global_proxy_port.def).toString ());
-    proxyUserName->setText (settings->value (global_proxy_user.key, global_proxy_user.def).toString ());
-    proxyPassword->setText (settings->value (global_proxy_pass.key, global_proxy_pass.def).toString ());
+    // Fill all line edits
+    proxy_host_name->setText (settings->value (global_proxy_host.key, global_proxy_host.def).toString ());
+    proxy_port->setText (settings->value (global_proxy_port.key, global_proxy_port.def).toString ());
+    proxy_username->setText (settings->value (global_proxy_user.key, global_proxy_user.def).toString ());
+    proxy_password->setText (settings->value (global_proxy_pass.key, global_proxy_pass.def).toString ());
+    // Connect relevant signals for dis-/enabling some elements
+    connect (proxy_type, SIGNAL (currentIndexChanged (int)),
+             this, SLOT (proxy_items_update (void)));
+    connect (use_proxy_server, SIGNAL (toggled (bool)),
+             this, SLOT (proxy_items_update (void)));
+    // Check whehter line edits have to be enabled
+    proxy_items_update ();
 
     // Workspace
     read_workspace_colors (settings);
@@ -594,6 +608,32 @@
       }
   }
 
+  // slot for updating enabled state of proxy settings
+  void settings_dialog::proxy_items_update (void)
+  {
+    bool use_proxy = use_proxy_server->isChecked ();
+
+    bool manual = false;
+    for (int i = 0; i < global_proxy_manual_types.length (); i++)
+      {
+        if (proxy_type->currentIndex () == global_proxy_manual_types.at (i))
+          {
+            manual = true;
+            break;
+          }
+      }
+
+    proxy_type->setEnabled (use_proxy);
+    proxy_host_name_label->setEnabled (use_proxy && manual);
+    proxy_host_name->setEnabled (use_proxy && manual);
+    proxy_port_label->setEnabled (use_proxy && manual);
+    proxy_port->setEnabled (use_proxy && manual);
+    proxy_username_label->setEnabled (use_proxy && manual);
+    proxy_username->setEnabled (use_proxy && manual);
+    proxy_password_label->setEnabled (use_proxy && manual);
+    proxy_password->setEnabled (use_proxy && manual);
+  }
+
   // slots for import/export of shortcut sets
 
   void settings_dialog::import_shortcut_set (void)
@@ -935,6 +975,8 @@
     settings->setValue (ed_create_new_file.key, editor_create_new_file->isChecked ());
     settings->setValue (ed_hiding_closes_files.key, editor_hiding_closes_files->isChecked ());
     settings->setValue (ed_always_reload_changed_files.key, editor_reload_changed_files->isChecked ());
+    settings->setValue (ed_force_newline.key, editor_force_newline->isChecked ());
+    settings->setValue (ed_rm_trailing_spaces.key, editor_remove_trailing_spaces->isChecked ());
     settings->setValue (ed_show_dbg_file.key, editor_show_dbg_file->isChecked ());
 
     settings->setValue (cs_font_size.key, terminal_fontSize->value ());
@@ -947,12 +989,12 @@
     settings->setValue (fb_txt_file_ext.key, le_file_browser_extensions->text ());
 
     settings->setValue (nr_allow_connection.key, checkbox_allow_web_connect->isChecked ());
-    settings->setValue (global_use_proxy.key, useProxyServer->isChecked ());
-    settings->setValue (global_proxy_type.key, proxyType->currentText ());
-    settings->setValue (global_proxy_host.key, proxyHostName->text ());
-    settings->setValue (global_proxy_port.key, proxyPort->text ());
-    settings->setValue (global_proxy_user.key, proxyUserName->text ());
-    settings->setValue (global_proxy_pass.key, proxyPassword->text ());
+    settings->setValue (global_use_proxy.key, use_proxy_server->isChecked ());
+    settings->setValue (global_proxy_type.key, proxy_type->currentText ());
+    settings->setValue (global_proxy_host.key, proxy_host_name->text ());
+    settings->setValue (global_proxy_port.key, proxy_port->text ());
+    settings->setValue (global_proxy_user.key, proxy_username->text ());
+    settings->setValue (global_proxy_pass.key, proxy_password->text ());
     settings->setValue (cs_cursor_use_fgcol.key, terminal_cursorUseForegroundColor->isChecked ());
     settings->setValue (mw_dir_list.key, terminal_focus_command->isChecked ());
     settings->setValue (cs_dbg_location.key, terminal_print_dbg_location->isChecked ());
--- a/libgui/src/settings-dialog.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libgui/src/settings-dialog.h	Tue Jul 07 19:40:20 2020 -0400
@@ -65,6 +65,7 @@
     void get_file_browser_dir (void);
     void get_dir (QLineEdit*, const QString&);
     void set_disabled_pref_file_browser_dir (bool disable);
+    void proxy_items_update (void);
 
     // slots for dialog's buttons
     void button_clicked (QAbstractButton *button);
--- a/libgui/src/settings-dialog.ui	Tue Jul 07 18:34:23 2020 -0400
+++ b/libgui/src/settings-dialog.ui	Tue Jul 07 19:40:20 2020 -0400
@@ -32,7 +32,7 @@
       </size>
      </property>
      <property name="currentIndex">
-      <number>5</number>
+      <number>7</number>
      </property>
      <widget class="QWidget" name="tab_general">
       <property name="enabled">
@@ -843,7 +843,7 @@
             <x>0</x>
             <y>0</y>
             <width>1021</width>
-            <height>1467</height>
+            <height>1529</height>
            </rect>
           </property>
           <layout class="QVBoxLayout" name="verticalLayout_16">
@@ -2053,7 +2053,7 @@
                     </property>
                    </widget>
                   </item>
-                  <item row="8" column="0">
+                  <item row="10" column="0">
                    <layout class="QHBoxLayout" name="horizontalLayout_2">
                     <property name="topMargin">
                      <number>0</number>
@@ -2111,7 +2111,7 @@
                     </item>
                    </layout>
                   </item>
-                  <item row="10" column="0">
+                  <item row="12" column="0">
                    <layout class="QHBoxLayout" name="horizontalLayout_16">
                     <item>
                      <widget class="QLabel" name="label_16">
@@ -2138,7 +2138,7 @@
                     </item>
                    </layout>
                   </item>
-                  <item row="7" column="0">
+                  <item row="9" column="0">
                    <widget class="QCheckBox" name="editor_hiding_closes_files">
                     <property name="text">
                      <string>Close all files when the editor widget is closed/hidden</string>
@@ -2148,6 +2148,26 @@
                     </property>
                    </widget>
                   </item>
+                  <item row="5" column="0">
+                   <widget class="QCheckBox" name="editor_force_newline">
+                    <property name="text">
+                     <string>Force newline at end when saving file</string>
+                    </property>
+                    <property name="checked">
+                     <bool>true</bool>
+                    </property>
+                   </widget>
+                  </item>
+                  <item row="6" column="0">
+                   <widget class="QCheckBox" name="editor_remove_trailing_spaces">
+                    <property name="text">
+                     <string>Remove trailing spaces when saving file</string>
+                    </property>
+                    <property name="checked">
+                     <bool>true</bool>
+                    </property>
+                   </widget>
+                  </item>
                  </layout>
                 </item>
                </layout>
@@ -2809,124 +2829,151 @@
           </property>
           <layout class="QVBoxLayout" name="verticalLayout_20">
            <item>
-            <layout class="QVBoxLayout" name="verticalLayout">
-             <item>
-              <widget class="QCheckBox" name="checkbox_allow_web_connect">
-               <property name="text">
-                <string>Allow Octave to connect to the Octave web site to display current news and information</string>
-               </property>
-              </widget>
-             </item>
-             <item>
-              <layout class="QGridLayout" name="gridLayout_5">
-               <item row="1" column="1">
-                <widget class="QLabel" name="label_4">
-                 <property name="enabled">
-                  <bool>false</bool>
-                 </property>
-                 <property name="text">
-                  <string>Hostname:</string>
-                 </property>
-                </widget>
-               </item>
-               <item row="0" column="2">
-                <widget class="QComboBox" name="proxyType">
-                 <property name="enabled">
-                  <bool>false</bool>
-                 </property>
-                 <item>
-                  <property name="text">
-                   <string>HttpProxy</string>
-                  </property>
-                 </item>
-                 <item>
-                  <property name="text">
-                   <string>Socks5Proxy</string>
-                  </property>
-                 </item>
-                </widget>
-               </item>
-               <item row="3" column="1">
-                <widget class="QLabel" name="label_6">
-                 <property name="enabled">
-                  <bool>false</bool>
-                 </property>
-                 <property name="text">
-                  <string>Username:</string>
-                 </property>
-                </widget>
-               </item>
-               <item row="0" column="0">
-                <widget class="QCheckBox" name="useProxyServer">
-                 <property name="text">
-                  <string>Use proxy server</string>
-                 </property>
-                </widget>
-               </item>
-               <item row="0" column="1">
-                <widget class="QLabel" name="label_3">
-                 <property name="enabled">
-                  <bool>false</bool>
-                 </property>
-                 <property name="text">
-                  <string>Proxy type:</string>
-                 </property>
-                </widget>
-               </item>
-               <item row="2" column="1">
-                <widget class="QLabel" name="label_5">
-                 <property name="enabled">
-                  <bool>false</bool>
-                 </property>
-                 <property name="text">
-                  <string>Port:</string>
-                 </property>
-                </widget>
-               </item>
-               <item row="4" column="1">
-                <widget class="QLabel" name="label_7">
-                 <property name="enabled">
-                  <bool>false</bool>
-                 </property>
-                 <property name="text">
-                  <string>Password:</string>
-                 </property>
-                </widget>
-               </item>
-               <item row="1" column="2">
-                <widget class="QLineEdit" name="proxyHostName">
-                 <property name="enabled">
-                  <bool>false</bool>
-                 </property>
-                </widget>
-               </item>
-               <item row="2" column="2">
-                <widget class="QLineEdit" name="proxyPort">
-                 <property name="enabled">
-                  <bool>false</bool>
-                 </property>
-                </widget>
-               </item>
-               <item row="3" column="2">
-                <widget class="QLineEdit" name="proxyUserName">
-                 <property name="enabled">
-                  <bool>false</bool>
-                 </property>
-                </widget>
-               </item>
-               <item row="4" column="2">
-                <widget class="QLineEdit" name="proxyPassword">
-                 <property name="enabled">
-                  <bool>false</bool>
-                 </property>
-                 <property name="echoMode">
-                  <enum>QLineEdit::Password</enum>
-                 </property>
-                </widget>
-               </item>
-              </layout>
-             </item>
-            </layout>
+            <widget class="QGroupBox" name="groupBox_12">
+             <property name="title">
+              <string>General</string>
+             </property>
+             <layout class="QVBoxLayout" name="verticalLayout_33">
+              <item>
+               <widget class="QCheckBox" name="checkbox_allow_web_connect">
+                <property name="text">
+                 <string>Allow Octave to connect to the Octave web site to display current news and information</string>
+                </property>
+               </widget>
+              </item>
+             </layout>
+            </widget>
+           </item>
+           <item>
+            <widget class="QGroupBox" name="groupBox_13">
+             <property name="title">
+              <string>Proxy Server</string>
+             </property>
+             <layout class="QVBoxLayout" name="verticalLayout_34">
+              <item>
+               <layout class="QVBoxLayout" name="verticalLayout">
+                <item>
+                 <layout class="QGridLayout" name="gridLayout_5">
+                  <item row="1" column="2">
+                   <widget class="QLabel" name="proxy_host_name_label">
+                    <property name="enabled">
+                     <bool>false</bool>
+                    </property>
+                    <property name="text">
+                     <string>Hostname:</string>
+                    </property>
+                   </widget>
+                  </item>
+                  <item row="0" column="3">
+                   <widget class="QComboBox" name="proxy_type">
+                    <property name="enabled">
+                     <bool>true</bool>
+                    </property>
+                    <property name="toolTip">
+                     <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select &lt;span style=&quot; font-style:italic;&quot;&gt;HttpProxy&lt;/span&gt;, &lt;span style=&quot; font-style:italic;&quot;&gt;Sock5Proxy&lt;/span&gt; or &lt;span style=&quot; font-style:italic;&quot;&gt;Environment Variables&lt;/span&gt;. With the last selection, the proxy is taken from the first non-empty environment variable ALL_PROXY, HTTP_PROXY or HTTPS_PROXY .&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+                    </property>
+                   </widget>
+                  </item>
+                  <item row="3" column="2">
+                   <widget class="QLabel" name="proxy_username_label">
+                    <property name="enabled">
+                     <bool>false</bool>
+                    </property>
+                    <property name="text">
+                     <string>Username:</string>
+                    </property>
+                   </widget>
+                  </item>
+                  <item row="0" column="2">
+                   <widget class="QLabel" name="proxy_type_label">
+                    <property name="enabled">
+                     <bool>true</bool>
+                    </property>
+                    <property name="text">
+                     <string>Proxy type:</string>
+                    </property>
+                   </widget>
+                  </item>
+                  <item row="2" column="2">
+                   <widget class="QLabel" name="proxy_port_label">
+                    <property name="enabled">
+                     <bool>false</bool>
+                    </property>
+                    <property name="text">
+                     <string>Port:</string>
+                    </property>
+                   </widget>
+                  </item>
+                  <item row="4" column="2">
+                   <widget class="QLabel" name="proxy_password_label">
+                    <property name="enabled">
+                     <bool>false</bool>
+                    </property>
+                    <property name="text">
+                     <string>Password:</string>
+                    </property>
+                   </widget>
+                  </item>
+                  <item row="1" column="3">
+                   <widget class="QLineEdit" name="proxy_host_name">
+                    <property name="enabled">
+                     <bool>false</bool>
+                    </property>
+                   </widget>
+                  </item>
+                  <item row="2" column="3">
+                   <widget class="QLineEdit" name="proxy_port">
+                    <property name="enabled">
+                     <bool>false</bool>
+                    </property>
+                   </widget>
+                  </item>
+                  <item row="3" column="3">
+                   <widget class="QLineEdit" name="proxy_username">
+                    <property name="enabled">
+                     <bool>false</bool>
+                    </property>
+                   </widget>
+                  </item>
+                  <item row="4" column="3">
+                   <widget class="QLineEdit" name="proxy_password">
+                    <property name="enabled">
+                     <bool>false</bool>
+                    </property>
+                    <property name="echoMode">
+                     <enum>QLineEdit::Password</enum>
+                    </property>
+                   </widget>
+                  </item>
+                  <item row="0" column="0">
+                   <widget class="QCheckBox" name="use_proxy_server">
+                    <property name="text">
+                     <string>Use proxy server</string>
+                    </property>
+                   </widget>
+                  </item>
+                  <item row="0" column="1">
+                   <spacer name="horizontalSpacer_30">
+                    <property name="orientation">
+                     <enum>Qt::Horizontal</enum>
+                    </property>
+                    <property name="sizeType">
+                     <enum>QSizePolicy::Fixed</enum>
+                    </property>
+                    <property name="sizeHint" stdset="0">
+                     <size>
+                      <width>20</width>
+                      <height>20</height>
+                     </size>
+                    </property>
+                   </spacer>
+                  </item>
+                 </layout>
+                </item>
+               </layout>
+              </item>
+             </layout>
+            </widget>
            </item>
            <item>
             <spacer name="verticalSpacer_5">
@@ -2961,102 +3008,6 @@
  <resources/>
  <connections>
   <connection>
-   <sender>useProxyServer</sender>
-   <signal>toggled(bool)</signal>
-   <receiver>label_4</receiver>
-   <slot>setEnabled(bool)</slot>
-   <hints>
-    <hint type="sourcelabel">
-     <x>249</x>
-     <y>59</y>
-    </hint>
-    <hint type="destinationlabel">
-     <x>69</x>
-     <y>122</y>
-    </hint>
-   </hints>
-  </connection>
-  <connection>
-   <sender>useProxyServer</sender>
-   <signal>toggled(bool)</signal>
-   <receiver>label_3</receiver>
-   <slot>setEnabled(bool)</slot>
-   <hints>
-    <hint type="sourcelabel">
-     <x>249</x>
-     <y>59</y>
-    </hint>
-    <hint type="destinationlabel">
-     <x>59</x>
-     <y>91</y>
-    </hint>
-   </hints>
-  </connection>
-  <connection>
-   <sender>useProxyServer</sender>
-   <signal>toggled(bool)</signal>
-   <receiver>proxyHostName</receiver>
-   <slot>setEnabled(bool)</slot>
-   <hints>
-    <hint type="sourcelabel">
-     <x>249</x>
-     <y>59</y>
-    </hint>
-    <hint type="destinationlabel">
-     <x>291</x>
-     <y>124</y>
-    </hint>
-   </hints>
-  </connection>
-  <connection>
-   <sender>useProxyServer</sender>
-   <signal>toggled(bool)</signal>
-   <receiver>label_5</receiver>
-   <slot>setEnabled(bool)</slot>
-   <hints>
-    <hint type="sourcelabel">
-     <x>249</x>
-     <y>59</y>
-    </hint>
-    <hint type="destinationlabel">
-     <x>44</x>
-     <y>152</y>
-    </hint>
-   </hints>
-  </connection>
-  <connection>
-   <sender>useProxyServer</sender>
-   <signal>toggled(bool)</signal>
-   <receiver>proxyType</receiver>
-   <slot>setEnabled(bool)</slot>
-   <hints>
-    <hint type="sourcelabel">
-     <x>249</x>
-     <y>59</y>
-    </hint>
-    <hint type="destinationlabel">
-     <x>291</x>
-     <y>91</y>
-    </hint>
-   </hints>
-  </connection>
-  <connection>
-   <sender>useProxyServer</sender>
-   <signal>toggled(bool)</signal>
-   <receiver>proxyPort</receiver>
-   <slot>setEnabled(bool)</slot>
-   <hints>
-    <hint type="sourcelabel">
-     <x>249</x>
-     <y>59</y>
-    </hint>
-    <hint type="destinationlabel">
-     <x>364</x>
-     <y>154</y>
-    </hint>
-   </hints>
-  </connection>
-  <connection>
    <sender>useCustomFileEditor</sender>
    <signal>toggled(bool)</signal>
    <receiver>customFileEditor</receiver>
@@ -3073,70 +3024,6 @@
    </hints>
   </connection>
   <connection>
-   <sender>useProxyServer</sender>
-   <signal>toggled(bool)</signal>
-   <receiver>label_7</receiver>
-   <slot>setEnabled(bool)</slot>
-   <hints>
-    <hint type="sourcelabel">
-     <x>249</x>
-     <y>59</y>
-    </hint>
-    <hint type="destinationlabel">
-     <x>67</x>
-     <y>212</y>
-    </hint>
-   </hints>
-  </connection>
-  <connection>
-   <sender>useProxyServer</sender>
-   <signal>toggled(bool)</signal>
-   <receiver>label_6</receiver>
-   <slot>setEnabled(bool)</slot>
-   <hints>
-    <hint type="sourcelabel">
-     <x>249</x>
-     <y>59</y>
-    </hint>
-    <hint type="destinationlabel">
-     <x>68</x>
-     <y>182</y>
-    </hint>
-   </hints>
-  </connection>
-  <connection>
-   <sender>useProxyServer</sender>
-   <signal>toggled(bool)</signal>
-   <receiver>proxyPassword</receiver>
-   <slot>setEnabled(bool)</slot>
-   <hints>
-    <hint type="sourcelabel">
-     <x>249</x>
-     <y>59</y>
-    </hint>
-    <hint type="destinationlabel">
-     <x>364</x>
-     <y>214</y>
-    </hint>
-   </hints>
-  </connection>
-  <connection>
-   <sender>useProxyServer</sender>
-   <signal>toggled(bool)</signal>
-   <receiver>proxyUserName</receiver>
-   <slot>setEnabled(bool)</slot>
-   <hints>
-    <hint type="sourcelabel">
-     <x>249</x>
-     <y>59</y>
-    </hint>
-    <hint type="destinationlabel">
-     <x>364</x>
-     <y>184</y>
-    </hint>
-   </hints>
-  </connection>
-  <connection>
    <sender>useCustomFileEditor</sender>
    <signal>toggled(bool)</signal>
    <receiver>customEditorLabel</receiver>
--- a/libgui/src/shortcut-manager.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libgui/src/shortcut-manager.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -75,11 +75,7 @@
         if (key == Qt::Key_unknown || key == 0)
           return;
 
-#if defined (HAVE_QGUIAPPLICATION)
         Qt::KeyboardModifiers modifiers = QGuiApplication::keyboardModifiers (); //e->modifiers ();
-#else
-        Qt::KeyboardModifiers modifiers = QApplication::keyboardModifiers (); //e->modifiers ();
-#endif
 
         if (m_shift_modifier || (modifiers & Qt::ShiftModifier))
           key += Qt::SHIFT;
@@ -372,11 +368,7 @@
     m_dialog = nullptr;
     m_level_hash.clear ();
 
-#if defined (HAVE_QHEADERVIEW_SETSECTIONRESIZEMODE)
     tree_view->header ()->setSectionResizeMode (QHeaderView::ResizeToContents);
-#else
-    tree_view->header ()->setResizeMode (QHeaderView::ResizeToContents);
-#endif
 
     QTreeWidgetItem *main = new QTreeWidgetItem (tree_view);
     main->setText (0, tr ("Global"));
--- a/libgui/src/tab-bar.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libgui/src/tab-bar.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -56,16 +56,12 @@
 
   void tab_bar::move_tab_left (void)
   {
-#if defined (HAVE_QTABWIDGET_SETMOVABLE)
     switch_tab (-1, true);
-#endif
   }
 
   void tab_bar::move_tab_right (void)
   {
-#if defined (HAVE_QTABWIDGET_SETMOVABLE)
     switch_tab (1, true);
-#endif
   }
 
   void tab_bar::switch_tab (int direction, bool movetab)
@@ -83,11 +79,9 @@
 
     if (movetab)
       {
-#if defined (HAVE_QTABWIDGET_SETMOVABLE)
         moveTab (old_pos, new_pos);
         setCurrentIndex (old_pos);
         setCurrentIndex (new_pos);
-#endif
       }
     else
       setCurrentIndex (new_pos);
--- a/libgui/src/variable-editor-model.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libgui/src/variable-editor-model.h	Tue Jul 07 19:40:20 2020 -0400
@@ -263,11 +263,21 @@
       return rep->display_rows ();
     }
 
+    octave_idx_type data_rows (void) const
+    {
+      return rep->data_rows ();
+    }
+
     int display_columns (void) const
     {
       return rep->display_columns ();
     }
 
+    octave_idx_type data_columns (void) const
+    {
+      return rep->data_columns ();
+    }
+
     void maybe_resize_rows (int rows);
 
     void maybe_resize_columns (int cols);
@@ -318,16 +328,6 @@
       return rep->is_valid ();
     }
 
-    octave_idx_type data_rows (void) const
-    {
-      return rep->data_rows ();
-    }
-
-    octave_idx_type data_columns (void) const
-    {
-      return rep->data_columns ();
-    }
-
     void change_display_size (int old_rows, int old_cols,
                               int new_rows, int new_cols);
 
--- a/libgui/src/variable-editor.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libgui/src/variable-editor.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -39,7 +39,6 @@
 #include <QPalette>
 #include <QScreen>
 #include <QScrollBar>
-#include <QSignalMapper>
 #include <QStackedWidget>
 #include <QTabWidget>
 #include <QTableView>
@@ -61,14 +60,6 @@
 {
   // Code reuse functions
 
-  static QString
-  idx_to_expr (int32_t from, int32_t to)
-  {
-    return (from == to
-            ? QString ("%1").arg (from)
-            : QString ("%1:%2").arg (from).arg (to));
-  }
-
   static QSignalMapper *
   make_plot_mapper (QMenu *menu)
   {
@@ -78,11 +69,8 @@
     QSignalMapper *plot_mapper = new QSignalMapper (menu);
 
     for (int i = 0; i < list.size(); ++i)
-      {
-        plot_mapper->setMapping
-          (menu->addAction (list.at (i), plot_mapper, SLOT (map ())),
-           "figure (); " + list.at (i) + " (%1); title (\"%1\");");
-      }
+      plot_mapper->setMapping
+        (menu->addAction (list.at (i), plot_mapper, SLOT (map ())), list.at (i));
 
     return plot_mapper;
   }
@@ -110,7 +98,6 @@
     connect (p, SIGNAL (visibilityChanged (bool)),
              this, SLOT (setVisible (bool)));
 
-#if defined (HAVE_QGUIAPPLICATION)
 #define DOCKED_FULLSCREEN_BUTTON_TOOLTIP "Fullscreen undock"
 #define UNDOCKED_FULLSCREEN_BUTTON_TOOLTIP "Fullscreen"
     // Add a fullscreen button
@@ -140,7 +127,6 @@
     if (first != nullptr)
       index = h_layout->indexOf (first);
     h_layout->insertWidget (index, fullscreen_button);
-#endif
 
     // Custom title bars cause loss of decorations, add a frame
     m_frame = new QFrame (this);
@@ -152,7 +138,6 @@
   void
   variable_dock_widget::change_floating (bool)
   {
-#if defined (HAVE_QGUIAPPLICATION)
     if (isFloating ())
       {
         if (m_full_screen)
@@ -166,7 +151,6 @@
       }
     else
       m_fullscreen_action->setToolTip (tr (UNDOCKED_FULLSCREEN_BUTTON_TOOLTIP));
-#endif
 
     setFloating (! isFloating ());
   }
@@ -216,7 +200,6 @@
   void
   variable_dock_widget::change_fullscreen (void)
   {
-#if defined (HAVE_QGUIAPPLICATION)
     resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
 
     if (! m_full_screen)
@@ -256,7 +239,6 @@
       }
 #undef DOCKED_FULLSCREEN_BUTTON_TOOLTIP
 #undef UNDOCKED_FULLSCREEN_BUTTON_TOOLTIP
-#endif
   }
 
   void
@@ -500,11 +482,7 @@
     setHorizontalScrollMode (QAbstractItemView::ScrollPerPixel);
     setVerticalScrollMode (QAbstractItemView::ScrollPerPixel);
 
-#if defined (HAVE_QHEADERVIEW_SETSECTIONRESIZEMODE)
     verticalHeader ()->setSectionResizeMode (QHeaderView::Interactive);
-#else
-    verticalHeader ()->setResizeMode (QHeaderView::Interactive);
-#endif
   }
 
   void
@@ -512,11 +490,7 @@
   {
     QTableView::setModel (model);
 
-#if defined (HAVE_QHEADERVIEW_SETSECTIONRESIZEMODE)
     horizontalHeader ()->setSectionResizeMode (QHeaderView::Interactive);
-#else
-    horizontalHeader ()->setResizeMode (QHeaderView::Interactive);
-#endif
 
     m_var_model = parent ()->findChild<variable_editor_model *> ();
 
@@ -564,30 +538,39 @@
     return range;
   }
 
-  QString
-  variable_editor_view::selected_to_octave (void)
-  {
-    QList<int> range = range_selected ();
-    if (range.isEmpty ())
-      return objectName ();
-
-    QString rows = idx_to_expr (range.at (0), range.at (1));
-    QString cols = idx_to_expr (range.at (2), range.at (3));
-
-    // FIXME: Does cell need separate handling?  Maybe use '{.,.}'?
-
-    return QString ("%1(%2, %3)").arg (objectName ()).arg (rows).arg (cols);
-  }
-
   void
   variable_editor_view::selected_command_requested (const QString& cmd)
   {
     if (! hasFocus ())
       return;
 
-    QString selarg = selected_to_octave ();
-    if (! selarg.isEmpty ())
-      emit command_signal (cmd.arg (selarg));
+    QList<int> range = range_selected ();
+    if (range.isEmpty ())
+      return;
+
+    int s1 = m_var_model->data_rows ();
+    int s2 = m_var_model->data_columns ();
+    if (s1 < range.at (0) || s2 < range.at (2))
+      return; // Selected range does not contain data
+
+    s1 = std::min (s1, range.at (1));
+    s2 = std::min (s2, range.at (3));
+
+    // Variable with desired range as string
+    QString variable = QString ("%1(%2:%3,%4:%5)")
+                                .arg (objectName ())
+                                .arg (range.at (0)).arg (s1)
+                                .arg (range.at (2)).arg (s2);
+
+    // Desired command as string
+    QString command;
+    if (cmd == "create")
+      command = QString ("unnamed = %1;").arg (variable);
+    else
+      command = QString ("figure (); %1 (%2); title ('%2');")
+                          .arg (cmd).arg (variable);
+
+    emit command_signal (command);
   }
 
   void
@@ -762,7 +745,7 @@
   {
     // FIXME: Create unnamed1..n if exist ('unnamed', 'var') is true.
 
-    selected_command_requested ("unnamed = %1");
+    selected_command_requested ("create");
   }
 
   void
@@ -1061,6 +1044,7 @@
       m_table_colors (),
       m_current_focus_vname (""),
       m_hovered_focus_vname (""),
+      m_plot_mapper (nullptr),
       m_focus_widget (nullptr),
       m_focus_widget_vdw (nullptr)
   {
@@ -1139,29 +1123,6 @@
       }
   }
 
-  // Add an action to a menu or the widget itself.
-
-  QAction*
-  variable_editor::add_action (QMenu *menu, const QIcon& icon,
-                               const QString& text,
-                               const char *member)
-  {
-    QAction *a;
-
-    if (menu)
-      a = menu->addAction (icon, text, this, member);
-    else
-      {
-        a = new QAction (this);
-        connect (a, SIGNAL (triggered ()), this, member);
-      }
-
-    addAction (a);  // important for shortcut context
-    a->setShortcutContext (Qt::WidgetWithChildrenShortcut);
-
-    return a;
-  }
-
   void
   variable_editor::edit_variable (const QString& name, const octave_value& val)
   {
@@ -1241,6 +1202,9 @@
     edit_view->verticalHeader ()->setDefaultSectionSize (m_default_height
                                                          + m_add_font_height);
 
+    connect (m_plot_mapper, SIGNAL (mapped (const QString&)),
+             edit_view, SLOT (selected_command_requested (const QString&)));
+
     connect (edit_view, SIGNAL (command_signal (const QString&)),
              this, SIGNAL (command_signal (const QString&)));
     connect (this, SIGNAL (delete_selected_signal ()),
@@ -1251,8 +1215,6 @@
              edit_view, SLOT (copyClipboard ()));
     connect (this, SIGNAL (paste_clipboard_signal ()),
              edit_view, SLOT (pasteClipboard ()));
-    connect (this, SIGNAL (selected_command_signal (const QString&)),
-             edit_view, SLOT (selected_command_requested (const QString&)));
     connect (edit_view->horizontalHeader (),
              SIGNAL (customContextMenuRequested (const QPoint&)),
              edit_view, SLOT (createColumnMenu (const QPoint&)));
@@ -1520,12 +1482,6 @@
     emit level_up_signal ();
   }
 
-  void
-  variable_editor::relay_selected_command (const QString& cmd)
-  {
-    emit selected_command_signal (cmd);
-  }
-
   // Also updates the font.
 
   void variable_editor::update_colors (void)
@@ -1644,10 +1600,7 @@
     plot_menu->setTitle (tr ("Plot"));
     plot_menu->setSeparatorsCollapsible (false);
 
-    QSignalMapper *plot_mapper = make_plot_mapper (plot_menu);
-
-    connect (plot_mapper, SIGNAL (mapped (const QString&)),
-             this, SLOT (relay_selected_command (const QString&)));
+    m_plot_mapper = make_plot_mapper (plot_menu);
 
     plot_tool_button->setMenu (plot_menu);
 
@@ -1664,9 +1617,7 @@
     // that restores active window and focus before acting.
     QList<HoverToolButton *> hbuttonlist
       = m_tool_bar->findChildren<HoverToolButton *> (""
-#if defined (QOBJECT_FINDCHILDREN_ACCEPTS_FINDCHILDOPTIONS)
                                                      , Qt::FindDirectChildrenOnly
-#endif
                                                     );
     for (int i = 0; i < hbuttonlist.size (); i++)
       {
@@ -1678,9 +1629,7 @@
 
     QList<ReturnFocusToolButton *> rfbuttonlist
       = m_tool_bar->findChildren<ReturnFocusToolButton *> (""
-#if defined (QOBJECT_FINDCHILDREN_ACCEPTS_FINDCHILDOPTIONS)
                                                            , Qt::FindDirectChildrenOnly
-#endif
                                                           );
     for (int i = 0; i < rfbuttonlist.size (); i++)
       {
--- a/libgui/src/variable-editor.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libgui/src/variable-editor.h	Tue Jul 07 19:40:20 2020 -0400
@@ -27,6 +27,7 @@
 #define octave_variable_editor_h 1
 
 #include <QHeaderView>
+#include <QSignalMapper>
 #include <QStackedWidget>
 #include <QTableView>
 
@@ -86,8 +87,6 @@
 
     QFrame *m_frame;
 
-#if defined (HAVE_QGUIAPPLICATION)
-
     QAction *m_fullscreen_action;
 
     bool m_full_screen;
@@ -96,8 +95,6 @@
 
     QRect m_prev_geom;
 
-#endif
-
 // See Octave bug #53807 and https://bugreports.qt.io/browse/QTBUG-44813
 #define QTBUG_44813_FIX_VERSION 0x999999
   signals:
@@ -207,9 +204,6 @@
 
     void createRowMenu (const QPoint& pt);
 
-    // Convert selection to an Octave expression.
-    QString selected_to_octave (void);
-
     void selected_command_requested (const QString& cmd);
 
   private:
@@ -321,8 +315,6 @@
 
     void delete_selected_signal (void);
 
-    void selected_command_signal (const QString& cmd);
-
   public slots:
 
     void callUpdate (const QModelIndex&, const QModelIndex&);
@@ -353,19 +345,12 @@
 
     void levelUp (void);
 
-    // Send command to Octave interpreter.
-    // %1 in CMD is replaced with the value of selected_to_octave.
-    void relay_selected_command (const QString& cmd);
-
   protected:
 
     void focusInEvent (QFocusEvent *ev);
 
   private:
 
-    QAction * add_action (QMenu *menu, const QIcon& icon, const QString& text,
-                          const char *member);
-
     dw_main_window *m_main;
 
     QToolBar *m_tool_bar;
@@ -401,6 +386,8 @@
 
     QString m_hovered_focus_vname;
 
+    QSignalMapper *m_plot_mapper;
+
     QWidget *m_focus_widget;
 
     variable_dock_widget *m_focus_widget_vdw;
--- a/libgui/src/workspace-view.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libgui/src/workspace-view.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -120,16 +120,8 @@
           (settings->value (ws_column_state.key).toByteArray ());
 
         // Set header properties for sorting
-#if defined (HAVE_QHEADERVIEW_SETSECTIONSCLICKABLE)
         m_view->horizontalHeader ()->setSectionsClickable (true);
-#else
-        m_view->horizontalHeader ()->setClickable (true);
-#endif
-#if defined (HAVE_QHEADERVIEW_SETSECTIONSMOVABLE)
         m_view->horizontalHeader ()->setSectionsMovable (true);
-#else
-        m_view->horizontalHeader ()->setMovable (true);
-#endif
         m_view->horizontalHeader ()->setSortIndicator (
           settings->value (ws_sort_column).toInt (),
           static_cast<Qt::SortOrder> (settings->value (ws_sort_order).toUInt ()));
--- a/libinterp/corefcn/__ftp__.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/corefcn/__ftp__.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -424,11 +424,10 @@
         }
       else
         {
-          std::string ascii_fname = octave::sys::get_ASCII_filename (file);
-
           // FIXME: Does ascii mode need to be flagged here?
-          std::ifstream ifile (ascii_fname.c_str (),
-                               std::ios::in | std::ios::binary);
+          std::ifstream ifile = 
+            octave::sys::ifstream (file.c_str (),
+                                   std::ios::in | std::ios::binary);
 
           if (! ifile.is_open ())
             error ("__ftp_mput__: unable to open file");
@@ -497,9 +496,9 @@
             url_xfer.mget_directory (sv(i), target);
           else
             {
-              std::ofstream ofile ((target + sv(i)).c_str (),
-                                   std::ios::out |
-                                   std::ios::binary);
+              std::ofstream ofile =
+                octave::sys::ofstream ((target + sv(i)).c_str (),
+                                       std::ios::out | std::ios::binary);
 
               if (! ofile.is_open ())
                 error ("__ftp_mget__: unable to open file");
--- a/libinterp/corefcn/__magick_read__.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/corefcn/__magick_read__.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -28,6 +28,7 @@
 #endif
 
 #include "file-stat.h"
+#include "lo-sysdep.h"
 #include "oct-env.h"
 #include "oct-time.h"
 
@@ -754,9 +755,15 @@
 void static
 read_file (const std::string& filename, std::vector<Magick::Image>& imvec)
 {
+  // FIXME: We need this on Windows because GraphicsMagick uses the ANSI API
+  // to open files on disc.  In contrast, the API of ImageMagick uses UTF-8
+  // encoded strings.  Should we somehow detect which is used on runtime and
+  // pass the file names accordingly? (See also bug #58493.)
+  std::string ascii_fname = octave::sys::get_ASCII_filename (filename, true);
+
   try
     {
-      Magick::readImages (&imvec, filename);
+      Magick::readImages (&imvec, ascii_fname);
     }
   catch (Magick::Warning& w)
     {
@@ -1687,9 +1694,16 @@
   Magick::Image img;
   img.subImage (idx); // start ping from this image (in case of multi-page)
   img.subRange (1);   // ping only one of them
+
+  // FIXME: We need this on Windows because GraphicsMagick uses the ANSI API
+  // to open files on disc.  In contrast, the API of ImageMagick uses UTF-8
+  // encoded strings.  Should we somehow detect which is used on runtime and
+  // pass the file names accordingly? (See also bug #58493.)
+  std::string ascii_fname = octave::sys::get_ASCII_filename (filename, true);
+
   try
     {
-      img.ping (filename);
+      img.ping (ascii_fname);
     }
   catch (Magick::Warning& w)
     {
--- a/libinterp/corefcn/colamd.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/corefcn/colamd.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -692,6 +692,15 @@
       ridx = scm.xridx ();
       cidx = scm.xcidx ();
     }
+  else if (args(0).islogical ())
+    {
+      SparseBoolMatrix sbm = args(0).sparse_bool_matrix_value ();
+
+      n_row = sbm.rows ();
+      n_col = sbm.cols ();
+      ridx = sbm.xridx ();
+      cidx = sbm.xcidx ();
+    }
   else
     {
       SparseMatrix sm = args(0).sparse_matrix_value ();
@@ -763,7 +772,9 @@
 }
 
 /*
-%!assert (etree (speye (2)), [0, 0]);
+%!assert (etree (sparse ([1,2], [1,2], [1,1], 2, 2)), [0, 0]);
+%!assert (etree (sparse ([1,2], [1,2], [true, true], 2, 2)), [0, 0]);
+%!assert (etree (sparse ([1,2], [1,2], [i,i], 2, 2)), [0, 0]);
 %!assert (etree (gallery ("poisson", 16)), [2:256, 0]);
 
 %!error etree ()
--- a/libinterp/corefcn/data.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/corefcn/data.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -4248,6 +4248,18 @@
 
   dim_vector dims (1, 1);
 
+  // The TYPE argument is required to be "logical" if present.  This
+  // feature appears to be undocumented in Matlab.
+
+  if (nargin > 0 && args(nargin-1).is_string ())
+    {
+      std::string nm = args(nargin-1).string_value ();
+      nargin--;
+
+      if (oct_data_conv::string_to_data_type (nm) != oct_data_conv::dt_logical)
+        error ("%s: invalid data type '%s'", fcn, nm.c_str ());
+    }
+
   switch (nargin)
     {
     case 0:
@@ -4908,6 +4920,12 @@
   return fill_matrix (args, false, "false");
 }
 
+/*
+%!assert (false (2, 3), logical (zeros (2, 3)))
+%!assert (false (2, 3, "logical"), logical (zeros (2, 3)))
+%!error false (2, 3, "double")
+*/
+
 DEFUN (true, args, ,
        doc: /* -*- texinfo -*-
 @deftypefn  {} {} true (@var{x})
@@ -4926,6 +4944,12 @@
   return fill_matrix (args, true, "true");
 }
 
+/*
+%!assert (true (2, 3), logical (ones (2, 3)))
+%!assert (true (2, 3, "logical"), logical (ones (2, 3)))
+%!error true (2, 3, "double")
+*/
+
 template <typename MT>
 octave_value
 identity_matrix (int nr, int nc)
--- a/libinterp/corefcn/debug.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/corefcn/debug.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -582,9 +582,7 @@
     os << "dbtype: unknown function " << name << "\n";
   else
     {
-      std::string ascii_fname = octave::sys::get_ASCII_filename (ff);
-
-      std::ifstream fs (ascii_fname.c_str (), std::ios::in);
+      std::ifstream fs = octave::sys::ifstream (ff.c_str (), std::ios::in);
 
       if (! fs)
         os << "dbtype: unable to open '" << ff << "' for reading!\n";
--- a/libinterp/corefcn/dirfns.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/corefcn/dirfns.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -224,7 +224,7 @@
     }
 }
 
-DEFMETHODX ("rmdir", Frmdir, interp, args, ,
+DEFMETHODX ("rmdir", Frmdir, interp, args, nargout,
             doc: /* -*- texinfo -*-
 @deftypefn  {} {} rmdir @var{dir}
 @deftypefnx {} {} rmdir (@var{dir}, "s")
@@ -250,6 +250,7 @@
   std::string dirname = args(0).xstring_value ("rmdir: DIR must be a string");
 
   std::string fulldir = octave::sys::file_ops::tilde_expand (dirname);
+  octave_value_list retval;
   int status = -1;
   std::string msg;
 
@@ -287,20 +288,30 @@
 
   evmgr.file_renamed (status >= 0);
 
-  if (status < 0)
-    return ovl (false, msg, "rmdir");
+  if (nargout == 0)
+    {
+      if (status < 0)
+        error ("rmdir: operation failed: %s", msg.c_str ());
+    }
   else
-    return ovl (true, "", "");
+    {
+      if (status < 0)
+        retval = ovl (0.0, msg, "rmdir");
+      else
+        retval = ovl (1.0, "", "");
+    }
+
+  return retval;
 }
 
-DEFUNX ("link", Flink, args, ,
+DEFUNX ("link", Flink, args, nargout,
         doc: /* -*- texinfo -*-
 @deftypefn  {} {} link @var{old} @var{new}
-@deftypefnx {} {[@var{err}, @var{msg}] =} link (@var{old}, @var{new})
+@deftypefnx {} {[@var{status}, @var{msg}] =} link (@var{old}, @var{new})
 Create a new link (also known as a hard link) to an existing file.
 
-If successful, @var{err} is 0 and @var{msg} is an empty string.
-Otherwise, @var{err} is nonzero and @var{msg} contains a system-dependent
+If successful, @var{status} is 0 and @var{msg} is an empty string.
+Otherwise, @var{status} is -1 and @var{msg} contains a system-dependent
 error message.
 @seealso{symlink, unlink, readlink, lstat}
 @end deftypefn */)
@@ -314,24 +325,35 @@
   from = octave::sys::file_ops::tilde_expand (from);
   to = octave::sys::file_ops::tilde_expand (to);
 
+  octave_value_list retval;
   std::string msg;
 
   int status = octave::sys::link (from, to, msg);
 
-  if (status < 0)
-    return ovl (-1.0, msg);
+  if (nargout == 0)
+    {
+      if (status < 0)
+        error ("link: operation failed: %s", msg.c_str ());
+    }
   else
-    return ovl (status, "");
+    {
+      if (status < 0)
+        retval = ovl (-1.0, msg);
+      else
+        retval = ovl (0.0, "");
+    }
+
+  return retval;
 }
 
-DEFUNX ("symlink", Fsymlink, args, ,
+DEFUNX ("symlink", Fsymlink, args, nargout,
         doc: /* -*- texinfo -*-
 @deftypefn  {} {} symlink @var{old} @var{new}
-@deftypefnx {} {[@var{err}, @var{msg}] =} symlink (@var{old}, @var{new})
+@deftypefnx {} {[@var{status}, @var{msg}] =} symlink (@var{old}, @var{new})
 Create a symbolic link @var{new} which contains the string @var{old}.
 
-If successful, @var{err} is 0 and @var{msg} is an empty string.
-Otherwise, @var{err} is nonzero and @var{msg} contains a system-dependent
+If successful, @var{status} is 0 and @var{msg} is an empty string.
+Otherwise, @var{status} is -1 and @var{msg} contains a system-dependent
 error message.
 @seealso{link, unlink, readlink, lstat}
 @end deftypefn */)
@@ -345,14 +367,25 @@
   from = octave::sys::file_ops::tilde_expand (from);
   to = octave::sys::file_ops::tilde_expand (to);
 
+  octave_value_list retval;
   std::string msg;
 
   int status = octave::sys::symlink (from, to, msg);
 
-  if (status < 0)
-    return ovl (-1.0, msg);
+  if (nargout == 0)
+    {
+      if (status < 0)
+        error ("symlink: operation failed: %s", msg.c_str ());
+    }
   else
-    return ovl (status, "");
+    {
+      if (status < 0)
+        retval = ovl (-1.0, msg);
+      else
+        retval = ovl (0.0, "");
+    }
+
+  return retval;
 }
 
 DEFUNX ("readlink", Freadlink, args, ,
@@ -385,14 +418,14 @@
     return ovl (result, status, "");
 }
 
-DEFMETHODX ("rename", Frename, interp, args, ,
+DEFMETHODX ("rename", Frename, interp, args, nargout,
             doc: /* -*- texinfo -*-
 @deftypefn  {} {} rename @var{old} @var{new}
-@deftypefnx {} {[@var{err}, @var{msg}] =} rename (@var{old}, @var{new})
+@deftypefnx {} {[@var{status}, @var{msg}] =} rename (@var{old}, @var{new})
 Change the name of file @var{old} to @var{new}.
 
-If successful, @var{err} is 0 and @var{msg} is an empty string.
-Otherwise, @var{err} is nonzero and @var{msg} contains a system-dependent
+If successful, @var{status} is 0 and @var{msg} is an empty string.
+Otherwise, @var{status} is -1 and @var{msg} contains a system-dependent
 error message.
 @seealso{movefile, copyfile, ls, dir}
 @end deftypefn */)
@@ -406,6 +439,7 @@
   from = octave::sys::file_ops::tilde_expand (from);
   to = octave::sys::file_ops::tilde_expand (to);
 
+  octave_value_list retval;
   std::string msg;
 
   octave::event_manager& evmgr = interp.get_event_manager ();
@@ -414,16 +448,22 @@
 
   int status = octave::sys::rename (from, to, msg);
 
-  if (status < 0)
+  evmgr.file_renamed (status >= 0);
+
+  if (nargout == 0)
     {
-      evmgr.file_renamed (false);
-      return ovl (-1.0, msg);
+      if (status < 0)
+        error ("rename: operation failed: %s", msg.c_str ());
     }
   else
     {
-      evmgr.file_renamed (true);
-      return ovl (status, "");
+      if (status < 0)
+        retval = ovl (-1.0, msg);
+      else
+        retval = ovl (0.0, "");
     }
+
+  return retval;
 }
 
 DEFUN (glob, args, ,
@@ -567,8 +607,8 @@
 %!       save (filename{n}, "a");
 %!     endfor
 %!   else
-%!     rmdir (tmpdir);
-%!     error ("Couldn't change to temporary dir");
+%!     sts = rmdir (tmpdir);
+%!     error ("Couldn't change to temporary directory");
 %!   endif
 %! else
 %!   error ("Couldn't create temporary directory");
@@ -580,7 +620,7 @@
 %!   delete (filename{n});
 %! endfor
 %! cd (cwd);
-%! rmdir (tmpdir);
+%! sts = rmdir (tmpdir);
 %! assert (result1, {"file1"; "myfile1"});
 %! assert (result2, {"myfile1"});
 %! assert (result3, {"file1"; "file2"});
--- a/libinterp/corefcn/dlmread.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/corefcn/dlmread.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -228,9 +228,12 @@
 
       tname = octave::find_data_file_in_load_path ("dlmread", tname);
 
-      std::string ascii_fname = octave::sys::get_ASCII_filename (tname);
-
-      input_file.open (ascii_fname.c_str (), std::ios::in);
+#if defined (OCTAVE_USE_WINDOWS_API)
+      std::wstring wname = octave::sys::u8_to_wstring (tname);
+      input_file.open (wname.c_str (), std::ios::in);
+#else
+      input_file.open (tname.c_str (), std::ios::in);
+#endif
 
       if (! input_file)
         error ("dlmread: unable to open file '%s'", fname.c_str ());
--- a/libinterp/corefcn/dmperm.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/corefcn/dmperm.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -103,10 +103,9 @@
     {
       CXSPARSE_NAME (d) *dm = CXSPARSE_NAME(_dmperm) (&csm, 0);
 
-      //retval(5) = put_int (dm->rr, 5);
-      //retval(4) = put_int (dm->cc, 5);
       retval = ovl (put_int (dm->p, nr), put_int (dm->q, nc),
-                    put_int (dm->r, dm->nb+1), put_int (dm->s, dm->nb+1));
+                    put_int (dm->r, dm->nb+1), put_int (dm->s, dm->nb+1),
+                    put_int (dm->cc, 5), put_int (dm->rr, 5));
 
       CXSPARSE_NAME (_dfree) (dm);
     }
@@ -116,23 +115,70 @@
 
 #endif
 
+// NOTE: the docstring for dmperm is adapted from the text found in the
+// file cs_dmperm.m that is distributed with the CSparse portion of the
+// SuiteSparse library, version 5.6.0.  CSparse is distributed under the
+// terms of the LGPL v2.1 or any later version.
+
 DEFUN (dmperm, args, nargout,
        doc: /* -*- texinfo -*-
-@deftypefn  {} {@var{p} =} dmperm (@var{S})
-@deftypefnx {} {[@var{p}, @var{q}, @var{r}, @var{S}] =} dmperm (@var{S})
+@deftypefn  {} {@var{p} =} dmperm (@var{A})
+@deftypefnx {} {[@var{p}, @var{q}, @var{r}, @var{s}, @var{cc}, @var{rr}] =} dmperm (@var{A})
 
 @cindex @nospell{Dulmage-Mendelsohn} decomposition
 Perform a @nospell{Dulmage-Mendelsohn} permutation of the sparse matrix
-@var{S}.
+@var{A}.
+
+With a single output argument @code{dmperm} return a maximum matching
+@var{p} such that @code{p(j) = i} if column @var{j}
+is matched to row @var{i}, or 0 if column @var{j} is unmatched.  If
+@var{A} is square and full structural rank, @var{p} is a row permutation
+and @code{A(p,:)} has a zero-free diagonal.  The structural
+rank of @var{A} is @code{sprank(A) = sum(p>0)}.
+
+Called with two or more output arguments, return the Dulmage-Mendelsohn
+decomposition of @var{A}.  @var{p} and @var{q} are permutation vectors.
+@var{cc} and @var{rr} are vectors of length 5.  @code{c = A(p,q)} is
+split into a 4-by-4 set of coarse blocks:
+
+@example
+@group
+   A11 A12 A13 A14
+    0  0   A23 A24
+    0  0    0  A34
+    0  0    0  A44
+@end group
+@end example
 
-With a single output argument @code{dmperm} performs the row permutations
-@var{p} such that @code{@var{S}(@var{p},:)} has no zero elements on the
-diagonal.
+@noindent
+where @code{A12}, @code{A23}, and @code{A34} are square with zero-free
+diagonals.  The columns of @code{A11} are the unmatched columns, and the
+rows of @code{A44} are the unmatched rows.  Any of these blocks can be
+empty.  In the "coarse" decomposition, the (i,j)-th block is
+@code{C(rr(i):rr(i+1)-1,cc(j):cc(j+1)-1)}.  In terms of a linear system,
+@code{[A11 A12]} is the underdetermined part of the system (it is always
+rectangular and with more columns and rows, or 0-by-0), @code{A23} is
+the well-determined part of the system (it is always square), and
+@code{[A34 ; A44]} is the over-determined part of the system (it is
+always rectangular with more rows than columns, or 0-by-0).
 
-Called with two or more output arguments, returns the row and column
-permutations, such that @code{@var{S}(@var{p}, @var{q})} is in block
-triangular form.  The values of @var{r} and @var{S} define the boundaries
-of the blocks.  If @var{S} is square then @code{@var{r} == @var{S}}.
+The structural rank of @var{A} is @code{sprank (A) = rr(4)-1}, which is
+an upper bound on the numerical rank of @var{A}.
+@code{sprank(A) = rank(full(sprand(A)))} with probability 1 in exact
+arithmetic.
+
+The @code{A23} submatrix is further subdivided into block upper
+triangular form via the "fine" decomposition (the strongly-connected
+components of @code{A23}).  If @var{A} is square and structurally
+non-singular, @code{A23} is the entire matrix.
+
+@code{C(r(i):r(i+1)-1,s(j):s(j+1)-1)} is the (i,j)-th block of
+the fine decomposition.  The (1,1) block is the rectangular block
+@code{[A11 A12]}, unless this block is 0-by-0.  The (b,b) block is the
+rectangular block @code{[A34 ; A44]}, unless this block is 0-by-0, where
+@code{b = length(r)-1}.  All other blocks of the form
+@code{C(r(i):r(i+1)-1,s(i):s(i+1)-1)} are diagonal blocks of
+@code{A23}, and are square with a zero-free diagonal.
 
 The method used is described in: @nospell{A. Pothen & C.-J. Fan.}
 @cite{Computing the Block Triangular Form of a Sparse Matrix}.
--- a/libinterp/corefcn/dynamic-ld.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/corefcn/dynamic-ld.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -199,13 +199,41 @@
     return retval;
   }
 
+  void *
+  dynamic_loader::try_load_mex (dynamic_library& mex_file,
+                                const std::string& fcn_name, bool& have_fmex)
+  {
+    // FCN_NAME is not used here, the mangler functions always return
+    // some form of "mexFunction".
+
+    have_fmex = false;
+
+    void *function = mex_file.search (fcn_name, mex_mangler);
+
+    if (! function)
+      {
+        // FIXME: Can we determine this C mangling scheme
+        //        automatically at run time or configure time?
+
+        function = mex_file.search (fcn_name, mex_uscore_mangler);
+
+        if (! function)
+          {
+            function = mex_file.search (fcn_name, mex_f77_mangler);
+
+            if (function)
+              have_fmex = true;
+          }
+      }
+
+    return function;
+  }
+
   octave_function *
   dynamic_loader::load_mex (const std::string& fcn_name,
                             const std::string& file_name,
                             bool /*relative*/)
   {
-    octave_function *retval = nullptr;
-
     unwind_protect frame;
 
     frame.protect_var (m_doing_load);
@@ -230,29 +258,17 @@
 
     bool have_fmex = false;
 
-    void *function = mex_file.search (fcn_name, mex_mangler);
-
-    if (! function)
-      {
-        // FIXME: Can we determine this C mangling scheme
-        //        automatically at run time or configure time?
-        function = mex_file.search (fcn_name, mex_uscore_mangler);
-
-        if (! function)
-          {
-            function = mex_file.search (fcn_name, mex_f77_mangler);
-
-            if (function)
-              have_fmex = true;
-          }
-      }
+    void *function = try_load_mex (mex_file, fcn_name, have_fmex);
 
     if (! function)
       error ("failed to install .mex file function '%s'", fcn_name.c_str ());
 
-    retval = new octave_mex_function (function, have_fmex, mex_file, fcn_name);
+    void *symbol = mex_file.search ("__mx_has_interleaved_complex__");
 
-    return retval;
+    bool interleaved = symbol != nullptr;
+
+    return new octave_mex_function (function, interleaved, have_fmex,
+                                    mex_file, fcn_name);
   }
 
   bool
--- a/libinterp/corefcn/dynamic-ld.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/corefcn/dynamic-ld.h	Tue Jul 07 19:40:20 2020 -0400
@@ -128,6 +128,9 @@
     static std::string mex_uscore_mangler (const std::string& name);
 
     static std::string mex_f77_mangler (const std::string& name);
+
+    static void * try_load_mex (dynamic_library& mex_file,
+                                const std::string& fcn_name, bool& have_fmex);
   };
 }
 
--- a/libinterp/corefcn/error.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/corefcn/error.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -751,9 +751,13 @@
       panic_impossible ();
 
     if (nel > 1)
-      os << "\n\n";
+      {
+        os << "\n";
+        os << "Non-default warning states are:\n\n";
+        os << "  State  Warning ID\n";
+      }
 
-    // The state for all is always supposed to be first in the list.
+    // The state for "all" is always supposed to be first in the list.
 
     for (octave_idx_type i = 1; i < nel; i++)
       {
@@ -1525,7 +1529,6 @@
                   octave_value curr_state = val.contents ("state");
 
                   // FIXME: this might be better with a dictionary object.
-
                   octave::tree_evaluator& tw = interp.get_evaluator ();
 
                   octave_value curr_warning_states
@@ -1579,39 +1582,28 @@
 
                   tw.set_auto_fcn_var (octave::stack_frame::SAVED_WARNING_STATES, m);
 
-                  // Now ignore the "local" argument and continue to
-                  // handle the current setting.
+                  // Now ignore the "local" argument,
+                  // and continue to handle the current setting.
                   nargin--;
                 }
             }
 
-          if (nargin >= 2 && arg2_lc == "all")
+          if ((nargin == 1
+               && (arg1 == "on" || arg1 == "off" || arg1 == "error"))
+              || (nargin >= 2 && arg2_lc == "all"))
             {
-              // If "all" is explicitly given as ID.
+              // If "all" is given implicitly or explicitly as ID.
+              if (arg1 == "error")
+                error ("warning: cannot specify \"all\" warning ID with state \"error\"");
 
               octave_map tmp;
-              int is_error = (arg1 == "error");
 
-              Cell id (1, 1 + 2*is_error);
-              Cell st (1, 1 + 2*is_error);
+              Cell id (1, 1);
+              Cell st (1, 1);
 
               id(0) = "all";
               st(0) = arg1;
 
-              // Since internal Octave functions are not compatible,
-              // and "all"=="error" causes any "on" to throw an error,
-              // turning all warnings into errors should disable
-              // Octave:language-extension.
-
-              if (is_error)
-                {
-                  id(1) = "Octave:language-extension";
-                  st(1) = "off";
-
-                  id(2) = "Octave:single-quote-string";
-                  st(2) = "off";
-                }
-
               tmp.assign ("identifier", id);
               tmp.assign ("state", st);
 
@@ -1667,25 +1659,63 @@
       else if (arg1 == "query")
         {
           if (arg2_lc == "all")
-            retval = es.warning_options ();
+            {
+              if (nargout > 0)
+                retval = es.warning_options ();
+              else
+                es.display_warning_options (octave_stdout);
+            }
           else if (arg2_lc == "backtrace" || arg2_lc == "debug"
                    || arg2_lc == "verbose" || arg2_lc == "quiet")
             {
-              octave_scalar_map tmp;
-              tmp.assign ("identifier", arg2_lc);
-              if (arg2_lc == "backtrace")
-                tmp.assign ("state", es.backtrace_on_warning () ? "on" : "off");
-              else if (arg2_lc == "debug")
-                tmp.assign ("state", es.debug_on_warning () ? "on" : "off");
-              else if (arg2_lc == "verbose")
-                tmp.assign ("state", es.verbose_warning () ? "on" : "off");
+              if (nargout > 0)
+                {
+                  octave_scalar_map tmp;
+                  tmp.assign ("identifier", arg2_lc);
+                  if (arg2_lc == "backtrace")
+                    tmp.assign ("state", es.backtrace_on_warning () ? "on" : "off");
+                  else if (arg2_lc == "debug")
+                    tmp.assign ("state", es.debug_on_warning () ? "on" : "off");
+                  else if (arg2_lc == "verbose")
+                    tmp.assign ("state", es.verbose_warning () ? "on" : "off");
+                  else
+                    tmp.assign ("state", es.quiet_warning () ? "on" : "off");
+
+                  retval = tmp;
+                }
               else
-                tmp.assign ("state", es.quiet_warning () ? "on" : "off");
-
-              retval = tmp;
+                {
+                  if (arg2_lc == "backtrace")
+                    octave_stdout << "\"backtrace\" warning state is \"" <<
+                                  (es.backtrace_on_warning () ? "on" : "off") <<
+                                  "\"\n";
+                  else if (arg2_lc == "debug")
+                    octave_stdout << "\"debug\" warning state is \"" <<
+                                  (es.debug_on_warning () ? "on" : "off") <<
+                                  "\"\n";
+                  else if (arg2_lc == "verbose")
+                    octave_stdout << "\"verbose\" warning state is \"" <<
+                                  (es.verbose_warning () ? "on" : "off") <<
+                                  "\"\n";
+                  else
+                    octave_stdout << "\"quiet\" warning state is \"" <<
+                                  (es.quiet_warning () ? "on" : "off") <<
+                                  "\"\n";
+                }
             }
           else
-            retval = es.warning_query (arg2);
+            {
+              if (nargout > 0)
+                retval = es.warning_query (arg2);
+              else
+                {
+                  octave_scalar_map tmp = es.warning_query (arg2);
+
+                  octave_stdout << "\"" << arg2 << "\" warning state is \"" <<
+                                   tmp.getfield ("state").string_value () <<
+                                   "\"\n";
+                }
+            }
 
           done = true;
         }
@@ -1768,9 +1798,6 @@
 }
 
 /*
-%!test <*45753>
-%! warning ("error");
-%! assert (! isempty (help ("warning")));
 
 %!test <*51997>
 %! id = "Octave:logical-conversion";
@@ -1793,6 +1820,8 @@
 %! idx = strcmp ({warnst.identifier}, "Octave:test-57290-ID");
 %! assert (warnst(idx).state, "off");
 
+%!error <cannot specify "all" warning ID> warning ("error")
+
 */
 
 octave_value_list
--- a/libinterp/corefcn/file-io.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/corefcn/file-io.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -1641,8 +1641,10 @@
 %! c = textscan (str, "%4f %f", "delimiter", ";", "collectOutput", 1);
 %! assert (c, {[12, 34; 1234, 56789; 7, NaN]});
 
+## FIXME: Not Matlab compatible.  Matlab prioritizes precision over field width
+## so "12.234e+2", when read with "%10.2f %f", yields "12.23" and "4e+2".
 ## Ignore trailing delimiter, but use leading one
-%!test
+%!#test
 %! str = "12.234e+2,34, \n12345.789-9876j,78\n,10|3";
 %! c = textscan (str, "%10.2f %f", "delimiter", ",", "collectOutput", 1,
 %!                    "expChars", "e|");
@@ -2285,7 +2287,46 @@
 %! obs = textscan (str, "%q", "delimiter", ",");
 %! assert (obs, { { "a,b"; "c" } });
 
+%!test <*58008>
+%! txt = sprintf ('literal_other_1_1;literal_other_1_2\nliteral_other_2_1;literal_other_2_2\nliteral_other_3_1;literal_other_3_2');
+%! nm1 = textscan (txt, 'literal%s literal%s', 'Delimiter', ';');
+%! assert (nm1{1}, {"_other_1_1" ; "_other_2_1" ; "_other_3_1"});
+%! assert (nm1{2}, {"_other_1_2" ; "_other_2_2" ; "_other_3_2"});
+%! nm2 = textscan (txt, 'literal%s;literal%s', 'Delimiter', ';');
+%! assert (nm1, nm2);
+
+%!test <*57612>
+%! str = sprintf (['101,' '\n' '201,']);
+%! C = textscan (str, '%s%q', 'Delimiter', ',');
+%! assert (size (C), [1, 2]);
+%! assert (C{1}, { "101"; "201" });
+%! assert (C{2}, { ""; "" });
+
+%!test <*57612>
+%! str = sprintf (['101,' '\n' '201,']);
+%! C = textscan (str, '%s%f', 'Delimiter', ',');
+%! assert (size (C), [1, 2]);
+%! assert (C{1}, { "101"; "201" });
+%! assert (C{2}, [ NaN; NaN ]);
+
+%!test <*57612>
+%! str = sprintf (['101,' '\n' '201,']);
+%! C = textscan (str, '%s%d', 'Delimiter', ',');
+%! assert (size (C), [1, 2]);
+%! assert (C{1}, { "101"; "201" });
+%! assert (C{2}, int32 ([ 0; 0 ]));
+
+%!test <*51093>
+%! str = sprintf ('a\t\tb\tc');
+%! C = textscan (str, '%s', 'Delimiter', '\t', 'MultipleDelimsAsOne', false);
+%! assert (C{1}, {'a'; ''; 'b'; 'c'});
+
+%!xtest <50743>
+%! C = textscan ('5973459727478852968', '%u64');
+%! assert (C{1}, uint64 (5973459727478852968));
+
 */
+
 // These tests have end-comment sequences, so can't just be in a comment
 #if 0
 ## Test unfinished comment
@@ -2890,7 +2931,7 @@
 %!   assert (tmpdir, tmp_tmpdir);
 %!   assert (tmpfname (1:4), "file");
 %! unwind_protect_cleanup
-%!   rmdir (tmp_tmpdir);
+%!   sts = rmdir (tmp_tmpdir);
 %!   for i = 1:numel (envvar)
 %!     if (isempty (envdir{i}))
 %!       unsetenv (envvar{i});
--- a/libinterp/corefcn/gl-render.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/corefcn/gl-render.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -734,6 +734,8 @@
       draw_surface (dynamic_cast<const surface::properties&> (props));
     else if (go.isa ("patch"))
       draw_patch (dynamic_cast<const patch::properties&> (props));
+    else if (go.isa ("scatter"))
+      draw_scatter (dynamic_cast<const scatter::properties&> (props));
     else if (go.isa ("light"))
       draw_light (dynamic_cast<const light::properties&> (props));
     else if (go.isa ("hggroup"))
@@ -3695,6 +3697,116 @@
   }
 
   void
+  opengl_renderer::draw_scatter (const scatter::properties& props)
+  {
+#if defined (HAVE_OPENGL)
+
+    // Do not render if the scatter object has incoherent data
+    std::string msg;
+    if (props.has_bad_data (msg))
+      {
+        warning ("opengl_renderer: %s.  Not rendering.", msg.c_str ());
+        return;
+      }
+
+    bool draw_all = selecting;
+
+    if (draw_all || (! props.marker_is ("none")
+                     && ! (props.markeredgecolor_is ("none")
+                           && props.markerfacecolor_is ("none"))))
+      {
+        bool do_edge = draw_all || ! props.markeredgecolor_is ("none");
+        bool do_face = draw_all || ! props.markerfacecolor_is ("none");
+
+        const Matrix x = props.get_xdata ().matrix_value ();
+        const Matrix y = props.get_ydata ().matrix_value ();
+        const Matrix z = props.get_zdata ().matrix_value ();
+        const Matrix c = props.get_color_data ().matrix_value ();
+        const Matrix s = props.get_sizedata ().matrix_value ();
+
+        int np = x.rows ();
+        bool has_z = ! z.isempty ();
+
+        // If markeredgecolor is "flat", mecolor is empty
+        Matrix mecolor = (draw_all ? Matrix (1, 3, 0.0) :
+                          props.get_markeredgecolor_rgb ());
+        Matrix mfcolor = (draw_all ? Matrix (1, 3, 0.0) :
+                          props.get_markerfacecolor_rgb ());
+        const double mea = props.get_markeredgealpha ();
+        const double mfa = props.get_markerfacealpha ();
+
+        if (props.markerfacecolor_is ("auto"))
+          {
+            gh_manager& gh_mgr
+              = octave::__get_gh_manager__ ("opengl_renderer::draw_scatter");
+            graphics_object go = gh_mgr.get_object (props.get___myhandle__ ());
+            graphics_object ax = go.get_ancestor ("axes");
+            const axes::properties& ax_props
+              = dynamic_cast<const axes::properties&> (ax.get_properties ());
+
+            mfcolor = ax_props.get_color ().matrix_value ();
+          }
+
+        init_marker (props.get_marker (), std::sqrt (s(0)),
+                     props.get_linewidth ());
+
+        uint8_t clip_mask = (props.is_clipping () ? 0x7F : 0x40);
+        uint8_t clip_ok = 0x40;
+
+        Matrix cc;
+        if (! c.isempty ())
+          {
+            if (c.rows () == 1)
+              cc = c;
+            else
+              {
+                cc.resize (1, 3);
+                cc(0) = c(0,0);
+                cc(1) = c(0,1);
+                cc(2) = c(0,2);
+              }
+          }
+
+        for (int i = 0; i < np; i++)
+          {
+            if ((clip_code (x(i), y(i), (has_z ? z(i) : 0.0)) & clip_mask)
+                 != clip_ok)
+              continue;
+
+            if (c.rows () > 1)
+              {
+                cc(0) = c(i,0);
+                cc(1) = c(i,1);
+                cc(2) = c(i,2);
+              }
+
+            Matrix lc = (do_edge ? (mecolor.isempty () ? cc : mecolor)
+                                 : Matrix ());
+            Matrix fc = (do_face ? (mfcolor.isempty () ? cc : mfcolor)
+                                 : Matrix ());
+
+            if (s.numel () > 1)
+              change_marker (props.get_marker (), std::sqrt (s(i)));
+
+            draw_marker (x(i), y(i), (has_z ? z(i) : 0.0), lc, fc, mea, mfa);
+          }
+
+        end_marker ();
+      }
+
+#else
+
+    octave_unused_parameter (props);
+
+    // This shouldn't happen because construction of opengl_renderer
+    // objects is supposed to be impossible if OpenGL is not available.
+
+    panic_impossible ();
+
+#endif
+  }
+
+  void
   opengl_renderer::draw_light (const light::properties& props)
   {
 #if defined (HAVE_OPENGL)
@@ -4275,6 +4387,27 @@
   }
 
   void
+  opengl_renderer::change_marker (const std::string& m, double size)
+  {
+#if defined (HAVE_OPENGL)
+
+    marker_id = make_marker_list (m, size, false);
+    filled_marker_id = make_marker_list (m, size, true);
+
+#else
+
+    octave_unused_parameter (m);
+    octave_unused_parameter (size);
+
+    // This shouldn't happen because construction of opengl_renderer
+    // objects is supposed to be impossible if OpenGL is not available.
+
+    panic_impossible ();
+
+#endif
+  }
+
+  void
   opengl_renderer::end_marker (void)
   {
 #if defined (HAVE_OPENGL)
@@ -4300,7 +4433,8 @@
 
   void
   opengl_renderer::draw_marker (double x, double y, double z,
-                                const Matrix& lc, const Matrix& fc)
+                                const Matrix& lc, const Matrix& fc,
+                                const double la, const double fa)
   {
 #if defined (HAVE_OPENGL)
 
@@ -4311,12 +4445,12 @@
 
     if (filled_marker_id > 0 && fc.numel () > 0)
       {
-        m_glfcns.glColor3dv (fc.data ());
+        m_glfcns.glColor4d (fc(0), fc(1), fc(2), fa);
         set_polygon_offset (true, -1.0);
         m_glfcns.glCallList (filled_marker_id);
         if (lc.numel () > 0)
           {
-            m_glfcns.glColor3dv (lc.data ());
+            m_glfcns.glColor4d (lc(0), lc(1), lc(2), la);
             m_glfcns.glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
             m_glfcns.glEdgeFlag (GL_TRUE);
             set_polygon_offset (true, -2.0);
@@ -4327,7 +4461,7 @@
       }
     else if (marker_id > 0 && lc.numel () > 0)
       {
-        m_glfcns.glColor3dv (lc.data ());
+        m_glfcns.glColor4d (lc(0), lc(1), lc(2), la);
         m_glfcns.glCallList (marker_id);
       }
 
@@ -4338,6 +4472,8 @@
     octave_unused_parameter (z);
     octave_unused_parameter (lc);
     octave_unused_parameter (fc);
+    octave_unused_parameter (la);
+    octave_unused_parameter (fa);
 
     // This shouldn't happen because construction of opengl_renderer
     // objects is supposed to be impossible if OpenGL is not available.
--- a/libinterp/corefcn/gl-render.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/corefcn/gl-render.h	Tue Jul 07 19:40:20 2020 -0400
@@ -81,6 +81,7 @@
     virtual void draw_line (const line::properties& props);
     virtual void draw_surface (const surface::properties& props);
     virtual void draw_patch (const patch::properties& props);
+    virtual void draw_scatter (const scatter::properties& props);
     virtual void draw_light (const light::properties& props);
     virtual void draw_hggroup (const hggroup::properties& props);
     virtual void draw_text (const text::properties& props);
@@ -115,9 +116,11 @@
     }
 
     virtual void init_marker (const std::string& m, double size, float width);
+    virtual void change_marker (const std::string& m, double size);
     virtual void end_marker (void);
     virtual void draw_marker (double x, double y, double z,
-                              const Matrix& lc, const Matrix& fc);
+                              const Matrix& lc, const Matrix& fc,
+                              const double la = 1.0, const double fa = 1.0);
 
     virtual void text_to_pixels (const std::string& txt,
                                  uint8NDArray& pixels,
--- a/libinterp/corefcn/gl2ps-print.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/corefcn/gl2ps-print.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -39,6 +39,7 @@
 
 #include <gl2ps.h>
 
+#include "file-ops.h"
 #include "lo-mappers.h"
 #include "oct-locbuf.h"
 #include "tmpfile-wrapper.h"
@@ -128,6 +129,13 @@
               && fa.double_value () < 1)
             retval = true;
         }
+      else if (go.isa ("scatter"))
+        {
+          octave_value fa = go.get ("markerfacealpha");
+          if (fa.is_scalar_type () && fa.is_double_type ()
+              && fa.double_value () < 1)
+            retval = true;
+        }
 
       return retval;
     }
@@ -410,9 +418,13 @@
 
             if (n_begin != std::string::npos)
               {
+                // Strip any quote characters characters around filename
                 size_t n_end = include_graph.find_last_not_of (" \"'");
                 include_graph = include_graph.substr (n_begin,
                                                       n_end - n_begin + 1);
+                // Strip path from filename
+                n_begin = include_graph.find_last_of (octave::sys::file_ops::dir_sep_chars ());
+                include_graph = include_graph.substr (n_begin + 1);
               }
             else
               include_graph = "foobar-inc";
--- a/libinterp/corefcn/graphics.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/corefcn/graphics.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -1157,8 +1157,9 @@
                 {
                   pfx = name.substr (0, 7);
 
-                  if (pfx.compare ("surface") || pfx.compare ("hggroup")
-                      || pfx.compare ("uipanel") || pfx.compare ("uitable"))
+                  if (pfx.compare ("surface") || pfx.compare ("scatter")
+                      || pfx.compare ("hggroup") || pfx.compare ("uipanel")
+                      || pfx.compare ("uitable"))
                     offset = 7;
                   else if (len >= 9)
                     {
@@ -1226,6 +1227,8 @@
     go = new light (h, p);
   else if (type.compare ("patch"))
     go = new patch (h, p);
+  else if (type.compare ("scatter"))
+    go = new scatter (h, p);
   else if (type.compare ("surface"))
     go = new surface (h, p);
   else if (type.compare ("hggroup"))
@@ -1784,18 +1787,18 @@
 }
 
 /*
-## Test validation of uicontextmenu property
+## Test validation of contextmenu property
 %!test
 %! hf = figure ("visible", "off");
 %! unwind_protect
 %!   hax = axes ("parent", hf);
 %!   hpa = patch ("parent", hax);
 %!   try
-%!     set (hax, "uicontextmenu", hpa);
+%!     set (hax, "contextmenu", hpa);
 %!   catch
 %!     err = lasterr ();
 %!   end_try_catch
-%!   assert (err, 'set: invalid graphics object type for property "uicontextmenu"');
+%!   assert (err, 'set: invalid graphics object type for property "contextmenu"');
 %! unwind_protect_cleanup
 %!   delete (hf);
 %! end_unwind_protect
@@ -2297,8 +2300,9 @@
                 {
                   pfx = name.substr (0, 7);
 
-                  if (pfx.compare ("surface") || pfx.compare ("hggroup")
-                      || pfx.compare ("uipanel") || pfx.compare ("uitable"))
+                  if (pfx.compare ("surface") || pfx.compare ("scatter")
+                      || pfx.compare ("hggroup")|| pfx.compare ("uipanel")
+                      || pfx.compare ("uitable"))
                     offset = 7;
                   else if (len > 9)
                     {
@@ -2357,6 +2361,8 @@
             has_property = image::properties::has_core_property (pname);
           else if (pfx == "patch")
             has_property = patch::properties::has_core_property (pname);
+          else if (pfx == "scatter")
+            has_property = scatter::properties::has_core_property (pname);
           else if (pfx == "surface")
             has_property = surface::properties::has_core_property (pname);
           else if (pfx == "hggroup")
@@ -2439,8 +2445,9 @@
                 {
                   pfx = name.substr (0, 7);
 
-                  if (pfx.compare ("surface") || pfx.compare ("hggroup")
-                      || pfx.compare ("uipanel") || pfx.compare ("uitable"))
+                  if (pfx.compare ("surface") || pfx.compare ("scatter")
+                      || pfx.compare ("hggroup") || pfx.compare ("uipanel")
+                      || pfx.compare ("uitable"))
                     offset = 7;
                   else if (len > 9)
                     {
@@ -3483,15 +3490,15 @@
 }
 
 void
-base_properties::update_uicontextmenu (void) const
-{
-  if (uicontextmenu.get ().isempty ())
+base_properties::update_contextmenu (void) const
+{
+  if (contextmenu.get ().isempty ())
     return;
 
   gh_manager& gh_mgr
-    = octave::__get_gh_manager__ ("base_properties::update_uicontextmenu");
-
-  graphics_object go = gh_mgr.get_object (uicontextmenu.get ());
+    = octave::__get_gh_manager__ ("base_properties::update_contextmenu");
+
+  graphics_object go = gh_mgr.get_object (contextmenu.get ());
 
   if (go && go.isa ("uicontextmenu"))
     {
@@ -5267,7 +5274,7 @@
 axes::properties::sync_positions (void)
 {
   // First part is equivalent to 'update_tightinset ()'
-  if (activepositionproperty.is ("position"))
+  if (positionconstraint.is ("innerposition"))
     update_position ();
   else
     update_outerposition ();
@@ -5284,7 +5291,7 @@
   tightinset = tinset;
   set_units (old_units);
   update_transform ();
-  if (activepositionproperty.is ("position"))
+  if (positionconstraint.is ("innerposition"))
     update_position ();
   else
     update_outerposition ();
@@ -5335,7 +5342,7 @@
 %! hf = figure ("visible", "off");
 %! graphics_toolkit (hf, "qt");
 %! fpos = get (hf, "position");
-%! set (gca, "activepositionproperty", "position");
+%! set (gca, "positionconstraint", "innerposition");
 %! unwind_protect
 %!   plot (rand (3));
 %!   position = get (gca, "position");
@@ -7503,7 +7510,7 @@
 void
 axes::properties::update_outerposition (void)
 {
-  set_activepositionproperty ("outerposition");
+  set_positionconstraint ("outerposition");
   caseless_str old_units = get_units ();
   set_units ("normalized");
 
@@ -7562,7 +7569,7 @@
 void
 axes::properties::update_position (void)
 {
-  set_activepositionproperty ("position");
+  set_positionconstraint ("innerposition");
   caseless_str old_units = get_units ();
   set_units ("normalized");
 
@@ -7621,7 +7628,7 @@
   double right_margin = std::max (linset(2), tinset(2));
   double top_margin = std::max (linset(3), tinset(3));
 
-  if (activepositionproperty.is ("position"))
+  if (positionconstraint.is ("innerposition"))
     {
       Matrix innerbox = position.get ().matrix_value ();
 
@@ -8721,6 +8728,11 @@
           xproperties.set_has3Dkids ((max_val - min_val) >
                                      std::numeric_limits<double>::epsilon ());
 
+          // FIXME: How to correctly handle (positive or negative) log scale?
+          if ((! octave::math::isfinite (min_val)
+               || ! octave::math::isfinite (max_val))
+              && ! xproperties.zscale_is ("log"))
+            min_val = max_val = 0.;
 
           limits = xproperties.get_axis_limits (min_val, max_val,
                                                 min_pos, max_neg,
@@ -10206,6 +10218,122 @@
 // ---------------------------------------------------------------------
 
 octave_value
+scatter::properties::get_color_data (void) const
+{
+  octave_value c = get_cdata ();
+  if (c.is_undefined () || c.isempty ())
+    return Matrix ();
+  else
+    return convert_cdata (*this, c, c.columns () == 1, 2);
+}
+
+void
+scatter::properties::update_data (void)
+{
+  Matrix xd = get_xdata ().matrix_value ();
+  Matrix yd = get_ydata ().matrix_value ();
+  Matrix zd = get_zdata ().matrix_value ();
+  Matrix cd = get_cdata ().matrix_value ();
+  Matrix sd = get_sizedata ().matrix_value ();
+
+  bad_data_msg = "";
+  if (xd.dims () != yd.dims ()
+      || (xd.dims () != zd.dims () && ! zd.isempty ()))
+    {
+      bad_data_msg = "x/y/zdata must have the same dimensions";
+      return;
+    }
+
+  octave_idx_type x_rows = xd.rows ();
+  octave_idx_type c_cols = cd.columns ();
+  octave_idx_type c_rows = cd.rows ();
+
+  if (! cd.isempty () && (c_rows != 1 || c_cols != 3)
+      && (c_rows != x_rows || (c_cols != 1 && c_cols != 3)))
+    {
+      bad_data_msg = "cdata must be an rgb triplet or have the same number of "
+                     "rows as X and one or three columns";
+      return;
+    }
+
+  octave_idx_type s_rows = sd.rows ();
+  if (s_rows != 1 && s_rows != x_rows)
+    {
+      bad_data_msg = "sizedata must be a scalar or a vector with the same "
+                     "dimensions as X";
+      return;
+    }
+}
+
+static bool updating_scatter_cdata = false;
+
+void
+scatter::properties::update_color (void)
+{
+  if (updating_scatter_cdata)
+    return;
+
+  Matrix series_idx = get_seriesindex ().matrix_value ();
+  if (series_idx.isempty ())
+    return;
+
+  gh_manager& gh_mgr
+    = octave::__get_gh_manager__ ("scatter::properties::update_color");
+
+  graphics_object go = gh_mgr.get_object (get___myhandle__ ());
+
+  axes::properties& parent_axes_prop
+    = dynamic_cast<axes::properties&>
+        (go.get_ancestor ("axes").get_properties ());
+
+  Matrix color_order = parent_axes_prop.get_colororder ().matrix_value ();
+  octave_idx_type s = (static_cast<octave_idx_type> (series_idx(0)) - 1)
+                      % color_order.rows ();
+
+  Matrix color = Matrix (1, 3, 0.);
+  color(0) = color_order(s,0);
+  color(1) = color_order(s,1);
+  color(2) = color_order(s,2);
+
+  octave::unwind_protect frame;
+  frame.protect_var (updating_scatter_cdata);
+  updating_scatter_cdata = true;
+
+  set_cdata (color);
+  set_cdatamode ("auto");
+}
+
+void
+scatter::initialize (const graphics_object& go)
+{
+  base_graphics_object::initialize (go);
+
+  Matrix series_idx = xproperties.get_seriesindex ().matrix_value ();
+  if (series_idx.isempty ())
+    {
+      // Increment series index counter in parent axes
+      axes::properties& parent_axes_prop
+        = dynamic_cast<axes::properties&>
+            (go.get_ancestor ("axes").get_properties ());
+
+      if (! parent_axes_prop.nextplot_is ("add"))
+        parent_axes_prop.set_nextseriesindex (1);
+
+      series_idx.resize (1, 1);
+      series_idx(0) = parent_axes_prop.get_nextseriesindex ();
+      xproperties.set_seriesindex (series_idx);
+
+      parent_axes_prop.set_nextseriesindex
+        (parent_axes_prop.get_nextseriesindex () + 1);
+    }
+
+  if (xproperties.cdatamode_is ("auto"))
+    xproperties.update_color ();
+}
+
+// ---------------------------------------------------------------------
+
+octave_value
 surface::properties::get_color_data (void) const
 {
   return convert_cdata (*this, get_cdata (), cdatamapping_is ("scaled"), 3);
@@ -10795,8 +10923,8 @@
       graphics_object go = gh_mgr.get_object (*it);
 
       if (go.valid_object ()
-          && go.get ("uicontextmenu") == xproperties.get___myhandle__ ())
-        go.set ("uicontextmenu", Matrix ());
+          && go.get ("contextmenu") == xproperties.get___myhandle__ ())
+        go.set ("contextmenu", Matrix ());
     }
 }
 
@@ -12429,6 +12557,7 @@
   plist_map["text"] = text::properties::factory_defaults ();
   plist_map["image"] = image::properties::factory_defaults ();
   plist_map["patch"] = patch::properties::factory_defaults ();
+  plist_map["scatter"] = scatter::properties::factory_defaults ();
   plist_map["surface"] = surface::properties::factory_defaults ();
   plist_map["light"] = light::properties::factory_defaults ();
   plist_map["hggroup"] = hggroup::properties::factory_defaults ();
@@ -13224,7 +13353,7 @@
 
   if (go.isa ("surface"))
     nd = 3;
-  else if ((go.isa ("line") || go.isa ("patch"))
+  else if ((go.isa ("line") || go.isa ("patch") || go.isa ("scatter"))
            && ! go.get ("zdata").isempty ())
     nd = 3;
   else
@@ -13327,6 +13456,15 @@
   GO_BODY (patch);
 }
 
+DEFMETHOD (__go_scatter__, interp, args, ,
+           doc: /* -*- texinfo -*-
+@deftypefn {} {} __go_scatter__ (@var{parent})
+Undocumented internal function.
+@end deftypefn */)
+{
+  GO_BODY (scatter);
+}
+
 DEFMETHOD (__go_light__, interp, args, ,
            doc: /* -*- texinfo -*-
 @deftypefn {} {} __go_light__ (@var{parent})
@@ -14524,6 +14662,42 @@
   return ovl (go.get_toolkit ().get_pixels (go));
 }
 
+DEFMETHOD (__get_position__, interp, args, ,
+           doc: /* -*- texinfo -*-
+@deftypefn {} {@var{pos} =} __get_position__ (@var{h}, @var{units})
+Internal function.
+
+Return the position of the graphics object @var{h} in the specified
+@var{units}.
+@end deftypefn */)
+{
+  if (args.length () != 2)
+    print_usage ();
+
+  double h
+    = args(0).xdouble_value ("__get_position__: H must be a graphics handle");
+
+  std::string units
+    = args(1).xstring_value ("__get_position__: UNITS must be a string");
+
+  gh_manager& gh_mgr = interp.get_gh_manager ();
+
+  graphics_object go = gh_mgr.get_object (h);
+
+  if (h == 0 || ! go)
+    error ("__get_position__: H must be a handle to a valid graphics object");
+
+  graphics_object parent_go = gh_mgr.get_object (go.get_parent ());
+  Matrix bbox = parent_go.get_properties ().get_boundingbox (true)
+                .extract_n (0, 2, 1, 2);
+
+  Matrix pos = convert_position (go.get ("position").matrix_value (),
+                                 go.get ("units").string_value (),
+                                 units, bbox);
+
+  return ovl (pos);
+}
+
 DEFUN (__get_system_fonts__, args, ,
        doc: /* -*- texinfo -*-
 @deftypefn {} {@var{font_struct} =} __get_system_fonts__ ()
--- a/libinterp/corefcn/graphics.in.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/corefcn/graphics.in.h	Tue Jul 07 19:40:20 2020 -0400
@@ -2311,6 +2311,18 @@
 
   void set___modified__ (const octave_value& val) { __modified__ = val; }
 
+  // Redirect calls to "uicontextmenu" to "contextmenu".
+
+  graphics_handle get_uicontextmenu (void) const
+  {
+    return get_contextmenu ();
+  }
+
+  void set_uicontextmenu (const octave_value& val)
+  {
+    set_contextmenu (val);
+  }
+
   void reparent (const graphics_handle& new_parent) { parent = new_parent; }
 
   // Update data limits for AXIS_TYPE (xdata, ydata, etc.) in the parent
@@ -2321,7 +2333,7 @@
   virtual void update_axis_limits (const std::string& axis_type,
                                    const graphics_handle& h) const;
 
-  virtual void update_uicontextmenu (void) const;
+  virtual void update_contextmenu (void) const;
 
   virtual void delete_children (bool clear = false, bool from_root = false)
   {
@@ -2381,6 +2393,7 @@
     callback_property buttondownfcn , Matrix ()
     children_property children gf , Matrix ()
     bool_property clipping , "on"
+    handle_property contextmenu u , graphics_handle ()
     callback_property createfcn , Matrix ()
     callback_property deletefcn , Matrix ()
     radio_property handlevisibility u , "{on}|callback|off"
@@ -2392,7 +2405,7 @@
     bool_property selectionhighlight , "on"
     string_property tag s , ""
     string_property type frs , ty
-    handle_property uicontextmenu u , graphics_handle ()
+    handle_property uicontextmenu gsh , graphics_handle ()
     any_property userdata , Matrix ()
     bool_property visible u , "on"
 
@@ -2428,7 +2441,7 @@
 
   virtual void init (void)
   {
-    uicontextmenu.add_constraint ("uicontextmenu");
+    contextmenu.add_constraint ("uicontextmenu");
   }
 };
 
@@ -3468,6 +3481,43 @@
 
     void sync_positions (void);
 
+    // Redirect calls to "activepositionproperty" to "positionconstraint".
+
+    std::string get_activepositionproperty (void) const 
+    {
+      std::string cur_val;
+
+      if (positionconstraint.is ("innerposition"))
+        cur_val = "position";
+      else
+        cur_val = "outerposition";
+
+      return cur_val;
+    }
+
+    void set_activepositionproperty (const octave_value& val)
+    {
+      // call set method to validate the input
+      activepositionproperty.set (val);
+
+      if (val.char_matrix_value ().row_as_string (0) == "position")
+        set_positionconstraint ("innerposition");
+      else
+        set_positionconstraint (val);
+    }
+
+    // Redirect calls to "innerposition" to "position".
+
+    octave_value get_innerposition (void) const
+    {
+      return get_position ();
+    }
+
+    void set_innerposition (const octave_value& val)
+    {
+      set_position (val);
+    }
+
     void update_autopos (const std::string& elem_type);
     void update_xlabel_position (void);
     void update_ylabel_position (void);
@@ -3637,9 +3687,12 @@
     // Programming note: Keep property list sorted if new ones are added.
 
     BEGIN_PROPERTIES (axes)
-      radio_property activepositionproperty , "{outerposition}|position"
+      radio_property activepositionproperty gsh , "{outerposition}|position"
       row_vector_property alim m , default_lim ()
       radio_property alimmode , "{auto}|manual"
+      // FIXME: not yet implemented
+      array_property alphamap , Matrix ()
+      radio_property alphascale , "{linear}|log"
       color_property ambientlightcolor , color_values (1, 1, 1)
       bool_property box u , "off"
       radio_property boxstyle , "{back}|full"
@@ -3658,12 +3711,15 @@
       array_property colormap sg , Matrix ()
       array_property colororder , default_colororder ()
       double_property colororderindex , 1.0
+      radio_property colorscale , "{linear}|log"
       array_property currentpoint , Matrix (2, 3, 0.0)
       row_vector_property dataaspectratio mu , Matrix (1, 3, 1.0)
       radio_property dataaspectratiomode u , "{auto}|manual"
       radio_property fontangle u , "{normal}|italic"
       string_property fontname u , OCTAVE_DEFAULT_FONTNAME
-      double_property fontsize u , 10
+      double_property fontsize mu , 10
+      // FIXME: not yet implemented
+      radio_property fontsizemode , "{auto}|manual"
       bool_property fontsmoothing u , "on"
       radio_property fontunits SU , "{points}|inches|centimeters|normalized|pixels"
       radio_property fontweight u , "{normal}|bold"
@@ -3672,8 +3728,15 @@
       color_property gridcolor m , color_property (color_values (0.15, 0.15, 0.15), radio_values ("none"))
       radio_property gridcolormode , "{auto}|manual"
       radio_property gridlinestyle , "{-}|--|:|-.|none"
+      array_property innerposition sg , default_axes_position ()
+      // FIXME: Should be an array of "interaction objects". Make it read-only for now.
+      any_property interactions r , Matrix ()
       double_property labelfontsizemultiplier u , 1.1
       radio_property layer u , "{bottom}|top"
+      // FIXME: Should be a "layoutoptions" object. Make it read-only for now.
+      handle_property layout r , graphics_handle ()
+      // FIXME: Should be a "legend" object. Make it read-only for now.
+      handle_property legend r , graphics_handle ()
       // FIXME: should be kind of string array.
       any_property linestyleorder S , "-"
       double_property linestyleorderindex , 1.0
@@ -3684,10 +3747,12 @@
       radio_property minorgridcolormode , "{auto}|manual"
       radio_property minorgridlinestyle , "{:}|-|--|-.|none"
       radio_property nextplot , "{replace}|add|replacechildren"
+      double_property nextseriesindex r , 1.0
       array_property outerposition u , default_axes_outerposition ()
       row_vector_property plotboxaspectratio mu , Matrix (1, 3, 1.0)
       radio_property plotboxaspectratiomode u , "{auto}|manual"
       array_property position u , default_axes_position ()
+      radio_property positionconstraint , "{outerposition}|innerposition"
       radio_property projection , "{orthographic}|perspective"
       radio_property sortmethod , "{depth}|childorder"
       radio_property tickdir mu , "{in}|out"
@@ -3699,9 +3764,12 @@
       handle_property title SOf , make_graphics_handle ("text", __myhandle__, false, false, false)
       double_property titlefontsizemultiplier u , 1.1
       radio_property titlefontweight u , "{bold}|normal"
-      // FIXME: uicontextmenu should be moved here.
+      // FIXME: Should be a "axestoolbar" object. Make it read-only for now.
+      handle_property toolbar r , graphics_handle ()
       radio_property units SU , "{normalized}|inches|centimeters|points|pixels|characters"
       array_property view u , default_axes_view ()
+      // FIXME: Should be a "ruler" object. Make it read-only for now.
+      handle_property xaxis r , graphics_handle ()
       radio_property xaxislocation u , "{bottom}|top|origin"
       color_property xcolor mu , color_property (color_values (0.15, 0.15, 0.15), radio_values ("none"))
       radio_property xcolormode , "{auto}|manual"
@@ -3719,6 +3787,8 @@
       radio_property xticklabelmode u , "{auto}|manual"
       double_property xticklabelrotation , 0.0
       radio_property xtickmode u , "{auto}|manual"
+      // FIXME: Should be a "ruler" object. Make it read-only for now.
+      handle_property yaxis r , graphics_handle ()
       radio_property yaxislocation u , "{left}|right|origin"
       color_property ycolor mu , color_property (color_values (0.15, 0.15, 0.15), radio_values ("none"))
       radio_property ycolormode , "{auto}|manual"
@@ -3735,6 +3805,8 @@
       radio_property yticklabelmode u , "{auto}|manual"
       double_property yticklabelrotation , 0.0
       radio_property ytickmode u , "{auto}|manual"
+      // FIXME: Should be a "ruler" object. Make it read-only for now.
+      handle_property zaxis r , graphics_handle ()
       color_property zcolor mu , color_property (color_values (0.15, 0.15, 0.15), radio_values ("none"))
       radio_property zcolormode , "{auto}|manual"
       radio_property zdir u , "{normal}|reverse"
@@ -4379,8 +4451,7 @@
       color_property edgecolor , color_property (radio_values ("{none}"), color_values (0, 0, 0))
       bool_property editing , "off"
       array_property extent rG , Matrix (1, 4, 0.0)
-      // FIXME: DEPRECATED: Remove "oblique" in version 7.
-      radio_property fontangle u , "{normal}|italic|oblique"
+      radio_property fontangle u , "{normal}|italic"
       string_property fontname u , OCTAVE_DEFAULT_FONTNAME
       double_property fontsize u , 10
       bool_property fontsmoothing u , "on"
@@ -4487,11 +4558,6 @@
     {
       update_font ();
       update_text_extent ();
-      // FIXME: DEPRECATED: Remove warning for "oblique" in version 7.
-      if (fontangle.is ("oblique"))
-        warning_with_id ("Octave:deprecated-property",
-                         "Setting 'fontangle' to '%s' is deprecated, \
-use 'italic' or 'normal'.", fontangle.current_value ().c_str ());
     }
     void update_fontweight (void) { update_font (); update_text_extent (); }
 
@@ -5075,6 +5141,238 @@
 
 // ---------------------------------------------------------------------
 
+class OCTINTERP_API scatter : public base_graphics_object
+{
+public:
+  class OCTINTERP_API properties : public base_properties
+  {
+  public:
+    octave_value get_color_data (void) const;
+
+    // Matlab allows incoherent data to be stored in scatter properties.
+    // The scatter object should then be ignored by the renderer.
+    bool has_bad_data (std::string& msg) const
+    {
+      msg = bad_data_msg;
+      return ! msg.empty ();
+    }
+
+    bool is_aliminclude (void) const
+    { return aliminclude.is_on (); }
+    std::string get_aliminclude (void) const
+    { return aliminclude.current_value (); }
+
+    bool is_climinclude (void) const
+    { return climinclude.is_on (); }
+    std::string get_climinclude (void) const
+    { return climinclude.current_value (); }
+
+    // See the genprops.awk script for an explanation of the
+    // properties declarations.
+    // Programming note: Keep property list sorted if new ones are added.
+
+    BEGIN_PROPERTIES (scatter)
+      array_property annotation , Matrix ()
+      array_property cdata mu , Matrix ()
+      radio_property cdatamode u , "{auto}|manual"
+      string_property cdatasource , ""
+      array_property datatiptemplate , Matrix ()
+      string_property displayname , ""
+      array_property latitudedata , Matrix ()
+      string_property latitudedatasource , ""
+      double_property linewidth , 0.5
+      array_property longitudedata , Matrix ()
+      string_property longitudedatasource , ""
+      radio_property marker , "{o}|+|*|.|x|s|square|d|diamond|^|v|>|<|p|pentagram|h|hexagram|none"
+      double_property markeredgealpha , 1.0
+      color_property markeredgecolor , color_property (radio_values ("{flat}|none"), color_values (0, 0, 0))
+      double_property markerfacealpha , 1.0
+      color_property markerfacecolor , color_property (radio_values ("{none}|auto|flat"), color_values (0, 0, 0))
+      array_property rdata , Matrix ()
+      string_property rdatasource , ""
+      array_property seriesindex u , Matrix ()
+      array_property sizedata u , Matrix ()
+      string_property sizedatasource , ""
+      array_property thetadata , Matrix ()
+      string_property thetadatasource , ""
+      array_property xdata u , Matrix ()
+      string_property xdatasource , ""
+      array_property ydata u , Matrix ()
+      string_property ydatasource , ""
+      array_property zdata u , Matrix ()
+      string_property zdatasource , ""
+
+      // hidden properties for limit computation
+      row_vector_property alim hlr , Matrix ()
+      row_vector_property clim hlr , Matrix ()
+      row_vector_property xlim hlr , Matrix ()
+      row_vector_property ylim hlr , Matrix ()
+      row_vector_property zlim hlr , Matrix ()
+      bool_property aliminclude hlg , "on"
+      bool_property climinclude hlg , "on"
+      bool_property xliminclude hl , "on"
+      bool_property yliminclude hl , "on"
+      bool_property zliminclude hl , "on"
+    END_PROPERTIES
+
+  protected:
+    void init (void)
+    {
+      xdata.add_constraint (dim_vector (-1, 1));
+      xdata.add_constraint (dim_vector (1, -1));
+      xdata.add_constraint (dim_vector (-1, 0));
+      xdata.add_constraint (dim_vector (0, -1));
+      ydata.add_constraint (dim_vector (-1, 1));
+      ydata.add_constraint (dim_vector (1, -1));
+      ydata.add_constraint (dim_vector (-1, 0));
+      ydata.add_constraint (dim_vector (0, -1));
+      zdata.add_constraint (dim_vector (-1, 1));
+      zdata.add_constraint (dim_vector (1, -1));
+      zdata.add_constraint (dim_vector (-1, 0));
+      zdata.add_constraint (dim_vector (0, -1));
+      sizedata.add_constraint ("min", 0.0, false);
+      sizedata.add_constraint (dim_vector (-1, 1));
+      sizedata.add_constraint (dim_vector (1, -1));
+      sizedata.add_constraint (dim_vector (-1, 0));
+      sizedata.add_constraint (dim_vector (0, -1));
+      cdata.add_constraint ("double");
+      cdata.add_constraint ("single");
+      cdata.add_constraint ("logical");
+      cdata.add_constraint ("int8");
+      cdata.add_constraint ("int16");
+      cdata.add_constraint ("int32");
+      cdata.add_constraint ("int64");
+      cdata.add_constraint ("uint8");
+      cdata.add_constraint ("uint16");
+      cdata.add_constraint ("uint32");
+      cdata.add_constraint ("uint64");
+      cdata.add_constraint ("real");
+      cdata.add_constraint (dim_vector (-1, 1));
+      cdata.add_constraint (dim_vector (-1, 3));
+      cdata.add_constraint (dim_vector (-1, 0));
+      cdata.add_constraint (dim_vector (0, -1));
+
+      linewidth.add_constraint ("min", 0.0, false);
+      seriesindex.add_constraint (dim_vector (1, 1));
+      seriesindex.add_constraint (dim_vector (-1, 0));
+      seriesindex.add_constraint (dim_vector (0, -1));
+    }
+
+  public:
+    void update_color (void);
+
+  private:
+    std::string bad_data_msg;
+
+    void update_xdata (void)
+    {
+      if (get_xdata ().isempty ())
+        {
+          // For compatibility with Matlab behavior,
+          // if x/ydata are set empty, silently empty other *data properties.
+          set_ydata (Matrix ());
+          set_zdata (Matrix ());
+          bool cdatamode_auto = cdatamode.is ("auto");
+          set_cdata (Matrix ());
+          if (cdatamode_auto)
+            set_cdatamode ("auto");
+        }
+
+      set_xlim (xdata.get_limits ());
+
+      update_data ();
+    }
+
+    void update_ydata (void)
+    {
+      if (get_ydata ().isempty ())
+        {
+          set_xdata (Matrix ());
+          set_zdata (Matrix ());
+          bool cdatamode_auto = cdatamode.is ("auto");
+          set_cdata (Matrix ());
+          if (cdatamode_auto)
+            set_cdatamode ("auto");
+        }
+
+      set_ylim (ydata.get_limits ());
+
+      update_data ();
+    }
+
+    void update_zdata (void)
+    {
+      set_zlim (zdata.get_limits ());
+
+      update_data ();
+    }
+
+    void update_sizedata (void)
+    {
+      update_data ();
+    }
+
+    void update_cdata (void)
+    {
+      if (get_cdata ().matrix_value ().rows () == 1)
+        set_clim (cdata.get_limits ());
+      else
+        clim = cdata.get_limits ();
+
+      update_data ();
+    }
+
+    void update_cdatamode (void)
+    {
+      if (cdatamode.is ("auto"))
+        update_color ();
+    }
+
+    void update_seriesindex (void)
+    {
+      if (cdatamode.is ("auto"))
+        update_color ();
+    }
+
+    void update_data (void);
+
+  };
+
+private:
+  properties xproperties;
+  property_list default_properties;
+
+public:
+  scatter (const graphics_handle& mh, const graphics_handle& p)
+    : base_graphics_object (), xproperties (mh, p)
+  {
+    // FIXME: seriesindex should increment by one each time a new scatter
+    // object is added to the axes.
+  }
+
+  ~scatter (void) = default;
+
+  base_properties& get_properties (void) { return xproperties; }
+
+  const base_properties& get_properties (void) const { return xproperties; }
+
+  bool valid_object (void) const { return true; }
+
+  bool has_readonly_property (const caseless_str& pname) const
+  {
+    bool retval = xproperties.has_readonly_property (pname);
+    if (! retval)
+      retval = base_properties::has_readonly_property (pname);
+    return retval;
+  }
+
+protected:
+  void initialize (const graphics_object& go);
+
+};
+
+// ---------------------------------------------------------------------
+
 class OCTINTERP_API surface : public base_graphics_object
 {
 public:
@@ -5427,6 +5725,7 @@
 
 // ---------------------------------------------------------------------
 
+// FIXME: This class has been renamed to "contextmenu" in Matlab R2020a.
 class OCTINTERP_API uicontextmenu : public base_graphics_object
 {
 public:
@@ -5517,8 +5816,7 @@
       bool_property clipping , "on"
       radio_property enable , "{on}|inactive|off"
       array_property extent rG , Matrix (1, 4, 0.0)
-      // FIXME: DEPRECATED: Remove "oblique" in version 7.
-      radio_property fontangle u , "{normal}|italic|oblique"
+      radio_property fontangle u , "{normal}|italic"
       string_property fontname u , OCTAVE_DEFAULT_FONTNAME
       double_property fontsize u , 10
       radio_property fontunits S , "inches|centimeters|normalized|{points}|pixels"
@@ -5568,11 +5866,6 @@
     void update_fontangle (void)
     {
       update_text_extent ();
-      // FIXME: DEPRECATED: Remove warning for "oblique" in version 7.
-      if (fontangle.is ("oblique"))
-        warning_with_id ("Octave:deprecated-property",
-                         "Setting 'fontangle' to '%s' is deprecated, \
-use 'italic' or 'normal'.", fontangle.current_value ().c_str ());
     }
     void update_fontweight (void) { update_text_extent (); }
 
@@ -5633,8 +5926,7 @@
       radio_property bordertype , "none|{etchedin}|etchedout|beveledin|beveledout|line"
       double_property borderwidth , 1
       bool_property clipping , "on"
-      // FIXME: DEPRECATED: Remove "oblique" in version 7.
-      radio_property fontangle , "{normal}|italic|oblique"
+      radio_property fontangle , "{normal}|italic"
       string_property fontname , OCTAVE_DEFAULT_FONTNAME
       double_property fontsize , 10
       radio_property fontunits S , "inches|centimeters|normalized|{points}|pixels"
@@ -5725,8 +6017,7 @@
       color_property backgroundcolor , color_values (0.94, 0.94, 0.94)
       radio_property bordertype , "none|{etchedin}|etchedout|beveledin|beveledout|line"
       double_property borderwidth , 1
-      // FIXME: DEPRECATED: Remove "oblique" in version 7.
-      radio_property fontangle , "{normal}|italic|oblique"
+      radio_property fontangle , "{normal}|italic"
       string_property fontname , OCTAVE_DEFAULT_FONTNAME
       double_property fontsize , 10
       radio_property fontunits S , "inches|centimeters|normalized|{points}|pixels"
@@ -5819,8 +6110,7 @@
       any_property data u , Matrix ()
       bool_property enable , "on"
       array_property extent rG , Matrix (1, 4, 0.0)
-      // FIXME: DEPRECATED: Remove "oblique" in version 7.
-      radio_property fontangle u , "{normal}|italic|oblique"
+      radio_property fontangle u , "{normal}|italic"
       string_property fontname u , OCTAVE_DEFAULT_FONTNAME
       double_property fontsize u , 10
       radio_property fontunits S , "inches|centimeters|normalized|{points}|pixels"
@@ -5861,11 +6151,6 @@
     void update_fontangle (void)
     {
       update_table_extent ();
-      // FIXME: DEPRECATED: Remove warning for "oblique" in version 7.
-      if (fontangle.is ("oblique"))
-        warning_with_id ("Octave:deprecated-property",
-                         "Setting 'fontangle' to '%s' is deprecated, \
-use 'italic' or 'normal'.", fontangle.current_value ().c_str ());
     }
     void update_fontweight (void) { update_table_extent (); }
   };
--- a/libinterp/corefcn/help.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/corefcn/help.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -600,11 +600,8 @@
 
     if (! initialized)
       {
-        std::string ascii_fname
-          = sys::get_ASCII_filename (m_built_in_docstrings_file);
-
-        std::ifstream file (ascii_fname.c_str (),
-                            std::ios::in | std::ios::binary);
+        std::ifstream file = sys::ifstream (m_built_in_docstrings_file.c_str (),
+                                            std::ios::in | std::ios::binary);
 
         if (! file)
           error ("failed to open docstrings file: %s",
@@ -686,11 +683,8 @@
         std::streampos beg = txt_limits.first;
         std::streamoff len = txt_limits.second;
 
-        std::string ascii_fname
-          = sys::get_ASCII_filename (m_built_in_docstrings_file);
-
-        std::ifstream file (ascii_fname.c_str (),
-                            std::ios::in | std::ios::binary);
+        std::ifstream file = sys::ifstream (m_built_in_docstrings_file.c_str (),
+                                            std::ios::in | std::ios::binary);
 
         if (! file)
           error ("failed to open docstrings file: %s",
--- a/libinterp/corefcn/input.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/corefcn/input.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -1406,40 +1406,3 @@
 
   return input_sys.mfile_encoding (args, nargout);
 }
-
-// Always define these functions.  The macro is intended to allow the
-// declarations to be hidden, not so that Octave will not provide the
-// functions if they are requested.
-
-// #if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-bool
-octave_yes_or_no (const std::string& prompt)
-{
-  octave::input_system& input_sys
-    = octave::__get_input_system__ ("set_default_prompts");
-
-  return input_sys.yes_or_no (prompt);
-}
-
-void
-remove_input_event_hook_functions (void)
-{
-  octave::input_system& input_sys
-    = octave::__get_input_system__ ("remove_input_event_hook_functions");
-
-  input_sys.clear_input_event_hooks ();
-}
-
-// Fix things up so that input can come from the standard input.  This
-// may need to become much more complicated, which is why it's in a
-// separate function.
-
-FILE *
-get_input_from_stdin (void)
-{
-  octave::command_editor::set_input_stream (stdin);
-  return octave::command_editor::get_input_stream ();
-}
-
-// #endif
--- a/libinterp/corefcn/input.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/corefcn/input.h	Tue Jul 07 19:40:20 2020 -0400
@@ -278,17 +278,4 @@
   };
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (5, "use 'octave::input_system::yes_or_no' instead")
-extern bool octave_yes_or_no (const std::string& prompt);
-
-OCTAVE_DEPRECATED (5, "use 'octave::input_system::clear_input_event_hooks' instead")
-extern void remove_input_event_hook_functions (void);
-
-OCTAVE_DEPRECATED (5, "this function will be removed in a future version of Octave")
-extern OCTINTERP_API FILE * get_input_from_stdin (void);
-
 #endif
-
-#endif
--- a/libinterp/corefcn/interpreter.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/corefcn/interpreter.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -295,6 +295,15 @@
   return retval;
 }
 
+DEFMETHOD (__traditional__, interp, , ,
+           doc: /* -*- texinfo -*-
+@deftypefn {} {} __traditional__ ()
+Undocumented internal function.
+@end deftypefn */)
+{
+  return ovl (interp.traditional ());
+}
+
 namespace octave
 {
   temporary_file_list::~temporary_file_list (void)
@@ -463,6 +472,7 @@
       m_read_site_files (true),
       m_read_init_files (m_app_context != nullptr),
       m_verbose (false),
+      m_traditional (false),
       m_inhibit_startup_message (false),
       m_load_path_initialized (false),
       m_history_initialized (false),
@@ -513,7 +523,6 @@
       m_display_info.initialize ();
 
     bool line_editing = false;
-    bool traditional = false;
 
     if (m_app_context)
       {
@@ -565,7 +574,7 @@
             && ! options.forced_line_editing ())
           line_editing = false;
 
-        traditional = options.traditional ();
+        m_traditional = options.traditional ();
 
         // FIXME: if possible, perform the following actions directly
         // instead of using the interpreter-level functions.
@@ -625,7 +634,7 @@
     // This should be done before initializing the load path because
     // some PKG_ADD files might need --traditional behavior.
 
-    if (traditional)
+    if (m_traditional)
       maximum_braindamage ();
 
     octave_interpreter_ready = true;
--- a/libinterp/corefcn/interpreter.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/corefcn/interpreter.h	Tue Jul 07 19:40:20 2020 -0400
@@ -180,6 +180,16 @@
       m_verbose = flag;
     }
 
+    void traditional (bool flag)
+    {
+      m_traditional = flag;
+    }
+
+    bool traditional (void) const
+    {
+      return m_traditional;
+    }
+
     void inhibit_startup_message (bool flag)
     {
       m_inhibit_startup_message = flag;
@@ -554,6 +564,8 @@
 
     bool m_verbose;
 
+    bool m_traditional;
+
     bool m_inhibit_startup_message;
 
     bool m_load_path_initialized;
--- a/libinterp/corefcn/load-save.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/corefcn/load-save.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -167,8 +167,8 @@
 
     std::string ascii_fname = sys::get_ASCII_filename (fname);
 
-    std::ifstream file (ascii_fname.c_str (),
-                        std::ios::in | std::ios::binary);
+    std::ifstream file = sys::ifstream (fname.c_str (),
+                                        std::ios::in | std::ios::binary);
 
     unsigned char magic[2];
     if (file.read (reinterpret_cast<char *> (&magic[0]), 2)
@@ -348,8 +348,8 @@
 
     if (! use_zlib)
       {
-        std::ifstream file (ascii_fname.c_str (),
-                            std::ios::in | std::ios::binary);
+        std::ifstream file = sys::ifstream (fname.c_str (),
+                                            std::ios::in | std::ios::binary);
         if (file)
           {
             retval = get_file_format (file, orig_fname);
@@ -803,7 +803,7 @@
             else
 #endif
               {
-                std::ofstream file (fname, mode);
+                std::ofstream file = sys::ofstream (fname, mode);
 
                 if (file)
                   {
@@ -1352,9 +1352,7 @@
               else
 #endif
                 {
-                  std::string ascii_fname = sys::get_ASCII_filename (fname);
-
-                  std::ifstream file (ascii_fname.c_str (), mode);
+                  std::ifstream file = sys::ifstream (fname.c_str (), mode);
 
                   if (! file)
                     error ("load: unable to open input file '%s'",
@@ -1525,7 +1523,7 @@
             else
 #endif
               {
-                std::ofstream file (fname.c_str (), mode);
+                std::ofstream file = sys::ofstream (fname.c_str (), mode);
 
                 if (! file)
                   err_file_open ("save", fname);
@@ -1820,6 +1818,46 @@
   return load_save_sys.save (args, nargout);
 }
 
+/*
+## Save and load strings with "-v6"
+%!test
+%! A = A2 = ["foo"; "bar"];
+%! B = B2 = "foobar";
+%! C = C2 = {"foo", "bar"};
+%! D = D2 = {"Saint Barthélemy", "Saint Kitts and Nevis"};
+%! mat_file = [tempname(), ".mat"];
+%! unwind_protect
+%!   save (mat_file, "A", "B", "C", "D", "-v6");
+%!   clear ("A", "B", "C", "D");
+%!   load (mat_file);
+%! unwind_protect_cleanup
+%!   unlink (mat_file);
+%! end_unwind_protect
+%! assert (A, A2);
+%! assert (B, B2);
+%! assert (C, C2);
+%! assert (D, D2);
+
+## Save and load strings with "-v7"
+%!testif HAVE_ZLIB
+%! A = A2 = ["foo"; "bar"];
+%! B = B2 = "foobar";
+%! C = C2 = {"foo", "bar"};
+%! D = D2 = {"Saint Barthélemy", "Saint Kitts and Nevis"};
+%! mat_file = [tempname(), ".mat"];
+%! unwind_protect
+%!   save (mat_file, "A", "B", "C", "D", "-v7");
+%!   clear ("A", "B", "C", "D");
+%!   load (mat_file);
+%! unwind_protect_cleanup
+%!   unlink (mat_file);
+%! end_unwind_protect
+%! assert (A, A2);
+%! assert (B, B2);
+%! assert (C, C2);
+%! assert (D, D2);
+*/
+
 DEFMETHOD (crash_dumps_octave_core, interp, args, nargout,
            doc: /* -*- texinfo -*-
 @deftypefn  {} {@var{val} =} crash_dumps_octave_core ()
--- a/libinterp/corefcn/ls-mat5.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/corefcn/ls-mat5.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -50,6 +50,7 @@
 #include "oct-time.h"
 #include "quit.h"
 #include "str-vec.h"
+#include "unistr-wrappers.h"
 
 #include "Cell.h"
 #include "defaults.h"
@@ -1413,58 +1414,84 @@
 
             tc = ctmp;
           }
-        else
+        else if (arrayclass == MAT_FILE_CHAR_CLASS)
           {
-            if (arrayclass == MAT_FILE_CHAR_CLASS)
+            bool converted = false;
+            if (re.isvector () && (type == miUTF16 || type == miUINT16))
               {
-                if (type == miUTF16 || type == miUTF32)
-                  {
-                    bool found_big_char = false;
-                    for (octave_idx_type i = 0; i < n; i++)
-                      {
-                        if (re(i) > 127)
-                          {
-                            re(i) = '?';
-                            found_big_char = true;
-                          }
-                      }
-
-                    if (found_big_char)
-                      warning_with_id ("Octave:load:unsupported-utf-char",
-                               "load: can not read non-ASCII portions of UTF characters; replacing unreadable characters with '?'");
-                  }
-                else if (type == miUTF8)
+                uint16NDArray u16 = re;
+                const uint16_t *u16_str
+                  = reinterpret_cast<const uint16_t *> (u16.data ());
+
+                // Convert to UTF-8.
+                size_t n8;
+                uint8_t *u8_str = octave_u16_to_u8_wrapper (u16_str,
+                                                            u16.numel (),
+                                                            nullptr, &n8);
+                if (u8_str)
                   {
-                    // Search for multi-byte encoded UTF8 characters and
-                    // replace with 0x3F for '?'...  Give the user a warning
-
-                    bool utf8_multi_byte = false;
-                    for (octave_idx_type i = 0; i < n; i++)
+                    // FIXME: Is there a better way to construct a charMatrix
+                    // from a non zero terminated buffer?
+                    tc = charMatrix (std::string (reinterpret_cast<char *> (u8_str), n8));
+                    free (u8_str);
+                    converted = true;
+                  }
+              }
+            else if (re.isvector () && (type == miUTF32 || type == miUINT32))
+              {
+                uint32NDArray u32 = re;
+                const uint32_t *u32_str
+                  = reinterpret_cast<const uint32_t *> (u32.data ());
+
+                // Convert to UTF-8.
+                size_t n8;
+                uint8_t *u8_str = octave_u32_to_u8_wrapper (u32_str,
+                                                            u32.numel (),
+                                                            nullptr, &n8);
+                if (u8_str)
+                  {
+                    // FIXME: Is there a better way to construct a charMatrix
+                    // from a non zero terminated buffer?
+                    tc = charMatrix (std::string (reinterpret_cast<char *> (u8_str), n8));
+                    free (u8_str);
+                    converted = true;
+                  }
+              }
+            else if (type == miUTF8 || type == miUINT8)
+              {
+                // Octave's internal encoding is UTF-8.  So we should be
+                // able to use this natively.
+                tc = re;
+                tc = tc.convert_to_str (false, true, '\'');
+                converted = true;
+              }
+
+            if (! converted)
+              {
+                // Fall back to manually replacing non-ASCII
+                // characters by "?".
+                bool found_big_char = false;
+                for (octave_idx_type i = 0; i < n; i++)
+                  {
+                    if (re(i) > 127)
                       {
-                        unsigned char a = static_cast<unsigned char> (re(i));
-                        if (a > 0x7f)
-                          utf8_multi_byte = true;
-                      }
-
-                    if (utf8_multi_byte)
-                      {
-                        warning_with_id ("Octave:load:unsupported-utf-char",
-                                         "load: can not read multi-byte encoded UTF8 characters; replacing unreadable characters with '?'");
-                        for (octave_idx_type i = 0; i < n; i++)
-                          {
-                            unsigned char a
-                              = static_cast<unsigned char> (re(i));
-                            if (a > 0x7f)
-                              re(i) = '?';
-                          }
+                        re(i) = '?';
+                        found_big_char = true;
                       }
                   }
+
+                if (found_big_char)
+                  warning_with_id ("Octave:load:unsupported-utf-char",
+                    "load: failed to convert from input to UTF-8; "
+                    "replacing non-ASCII characters with '?'");
+
                 tc = re;
                 tc = tc.convert_to_str (false, true, '\'');
               }
-            else
-              tc = re;
+
           }
+        else
+          tc = re;
       }
     }
 
@@ -2066,6 +2093,24 @@
   return ret;
 }
 
+static uint16_t *
+maybe_convert_to_u16 (const charNDArray& chm, size_t& n16_str)
+{
+  uint16_t *u16_str;
+  dim_vector dv = chm.dims ();
+
+  if (chm.ndims () == 2 && dv(0) == 1)
+    {
+      const uint8_t *u8_str = reinterpret_cast<const uint8_t *> (chm.data ());
+      u16_str = octave_u8_to_u16_wrapper (u8_str, chm.numel (),
+                                          nullptr, &n16_str);
+    }
+  else
+    u16_str = nullptr;
+
+  return u16_str;
+}
+
 int
 save_mat5_element_length (const octave_value& tc, const std::string& name,
                           bool save_as_floats, bool mat7_format)
@@ -2083,9 +2128,23 @@
   if (tc.is_string ())
     {
       charNDArray chm = tc.char_array_value ();
+      // convert to UTF-16
+      size_t n16_str;
+      uint16_t *u16_str = maybe_convert_to_u16 (chm, n16_str);
       ret += 8;
-      if (chm.numel () > 2)
-        ret += PAD (2 * chm.numel ());
+
+      octave_idx_type str_len;
+      if (u16_str)
+        {
+          // Count number of elements in converted string
+          str_len = 2 * n16_str;
+          free (u16_str);
+        }
+      else
+        str_len = chm.numel ();
+
+      if (str_len > 2)
+        ret += PAD (str_len);
     }
   else if (tc.issparse ())
     {
@@ -2410,15 +2469,36 @@
 
   write_mat5_tag (os, miINT32, dim_len);
 
-  for (int i = 0; i < nd; i++)
+  // Strings need to be converted here (or dim-vector will be off).
+  charNDArray chm;
+  uint16_t *u16_str;
+  size_t n16_str;
+  bool conv_u16 = false;
+  if (tc.is_string ())
     {
-      int32_t n = dv(i);
+      chm = tc.char_array_value ();
+      u16_str = maybe_convert_to_u16 (chm, n16_str);
+
+      if (u16_str)
+        conv_u16 = true;
+    }
+
+  if (conv_u16)
+    {
+      int32_t n = 1;
       os.write (reinterpret_cast<char *> (&n), 4);
+      os.write (reinterpret_cast<char *> (&n16_str), 4);
     }
+  else
+    for (int i = 0; i < nd; i++)
+      {
+        int32_t n = dv(i);
+        os.write (reinterpret_cast<char *> (&n), 4);
+      }
 
   if (PAD (dim_len) > dim_len)
     {
-      static char buf[9]="\x00\x00\x00\x00\x00\x00\x00\x00";
+      static char buf[9] = "\x00\x00\x00\x00\x00\x00\x00\x00";
       os.write (buf, PAD (dim_len) - dim_len);
     }
 
@@ -2441,24 +2521,35 @@
   // data element
   if (tc.is_string ())
     {
-      charNDArray chm = tc.char_array_value ();
-      octave_idx_type nel = chm.numel ();
-      octave_idx_type len = nel*2;
-      octave_idx_type paddedlength = PAD (len);
-
-      OCTAVE_LOCAL_BUFFER (int16_t, buf, nel+3);
-      write_mat5_tag (os, miUINT16, len);
-
-      const char *s = chm.data ();
-
-      for (octave_idx_type i = 0; i < nel; i++)
-        buf[i] = *s++ & 0x00FF;
-
-      os.write (reinterpret_cast<char *> (buf), len);
+      octave_idx_type len;
+      octave_idx_type paddedlength;
+
+      if (conv_u16)
+        {
+          // converted UTF-16
+          len = n16_str*2;
+          paddedlength = PAD (len);
+
+          write_mat5_tag (os, miUTF16, len);
+
+          os.write (reinterpret_cast<char *> (u16_str), len);
+
+          free (u16_str);
+        }
+      else
+        {
+          // write as UTF-8
+          len = chm.numel ();
+          paddedlength = PAD (len);
+
+          write_mat5_tag (os, miUTF8, len);
+
+          os.write (chm.data (), len);
+        }
 
       if (paddedlength > len)
         {
-          static char padbuf[9]="\x00\x00\x00\x00\x00\x00\x00\x00";
+          static char padbuf[9] = "\x00\x00\x00\x00\x00\x00\x00\x00";
           os.write (padbuf, paddedlength - len);
         }
     }
--- a/libinterp/corefcn/mex.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/corefcn/mex.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -62,6 +62,197 @@
 #include "variables.h"
 #include "graphics.h"
 
+// These must be declared extern "C" but may be omitted from the set of
+// symbols declared in mexproto.h, so we declare them here as well.
+
+extern "C"
+{
+  extern OCTINTERP_API const mxArray *
+  mexGet_interleaved (double handle, const char *property);
+
+  extern OCTINTERP_API mxArray *
+  mxCreateCellArray (mwSize ndims, const mwSize *dims);
+
+  extern OCTINTERP_API mxArray *
+  mxCreateCellMatrix (mwSize m, mwSize n);
+
+  extern OCTINTERP_API mxArray *
+  mxCreateCharArray (mwSize ndims, const mwSize *dims);
+
+  extern OCTINTERP_API mxArray *
+  mxCreateCharMatrixFromStrings (mwSize m, const char **str);
+
+  extern OCTINTERP_API mxArray *
+  mxCreateDoubleMatrix (mwSize nr, mwSize nc, mxComplexity flag);
+
+  extern OCTINTERP_API mxArray *
+  mxCreateDoubleScalar (double val);
+
+  extern OCTINTERP_API mxArray *
+  mxCreateLogicalArray (mwSize ndims, const mwSize *dims);
+
+  extern OCTINTERP_API mxArray *
+  mxCreateLogicalMatrix (mwSize m, mwSize n);
+
+  extern OCTINTERP_API mxArray *
+  mxCreateLogicalScalar (mxLogical val);
+
+  extern OCTINTERP_API mxArray *
+  mxCreateNumericArray (mwSize ndims, const mwSize *dims, mxClassID class_id,
+                        mxComplexity flag);
+
+  extern OCTINTERP_API mxArray *
+  mxCreateNumericMatrix (mwSize m, mwSize n, mxClassID class_id,
+                         mxComplexity flag);
+
+  extern OCTINTERP_API mxArray *
+  mxCreateUninitNumericArray (mwSize ndims, const mwSize *dims,
+                              mxClassID class_id, mxComplexity flag);
+
+  extern OCTINTERP_API mxArray *
+  mxCreateUninitNumericMatrix (mwSize m, mwSize n, mxClassID class_id,
+                               mxComplexity flag);
+
+  extern OCTINTERP_API mxArray *
+  mxCreateSparse (mwSize m, mwSize n, mwSize nzmax, mxComplexity flag);
+
+  extern OCTINTERP_API mxArray *
+  mxCreateSparseLogicalMatrix (mwSize m, mwSize n, mwSize nzmax);
+
+  extern OCTINTERP_API mxArray *
+  mxCreateString (const char *str);
+
+  extern OCTINTERP_API mxArray *
+  mxCreateStructArray (mwSize ndims, const mwSize *dims, int num_keys,
+                       const char **keys);
+
+  extern OCTINTERP_API mxArray *
+  mxCreateStructMatrix (mwSize rows, mwSize cols, int num_keys,
+                        const char **keys);
+
+  extern OCTINTERP_API mxArray *
+  mxCreateCellArray_interleaved (mwSize ndims, const mwSize *dims);
+
+  extern OCTINTERP_API mxArray *
+  mxCreateCellMatrix_interleaved (mwSize m, mwSize n);
+
+  extern OCTINTERP_API mxArray *
+  mxCreateCharArray_interleaved (mwSize ndims, const mwSize *dims);
+
+  extern OCTINTERP_API mxArray *
+  mxCreateCharMatrixFromStrings_interleaved (mwSize m, const char **str);
+
+  extern OCTINTERP_API mxArray *
+  mxCreateDoubleMatrix_interleaved (mwSize nr, mwSize nc, mxComplexity flag);
+
+  extern OCTINTERP_API mxArray *
+  mxCreateDoubleScalar_interleaved (double val);
+
+  extern OCTINTERP_API mxArray *
+  mxCreateLogicalArray_interleaved (mwSize ndims, const mwSize *dims);
+
+  extern OCTINTERP_API mxArray *
+  mxCreateLogicalMatrix_interleaved (mwSize m, mwSize n);
+
+  extern OCTINTERP_API mxArray *
+  mxCreateLogicalScalar_interleaved (mxLogical val);
+
+  extern OCTINTERP_API mxArray *
+  mxCreateNumericArray_interleaved (mwSize ndims, const mwSize *dims,
+                                    mxClassID class_id, mxComplexity flag);
+
+  extern OCTINTERP_API mxArray *
+  mxCreateNumericMatrix_interleaved (mwSize m, mwSize n, mxClassID class_id,
+                                     mxComplexity flag);
+
+  extern OCTINTERP_API mxArray *
+  mxCreateUninitNumericArray_interleaved (mwSize ndims, const mwSize *dims,
+                                          mxClassID class_id,
+                                          mxComplexity flag);
+
+  extern OCTINTERP_API mxArray *
+  mxCreateUninitNumericMatrix_interleaved (mwSize m, mwSize n,
+                                           mxClassID class_id,
+                                           mxComplexity flag);
+
+  extern OCTINTERP_API mxArray *
+  mxCreateSparse_interleaved (mwSize m, mwSize n, mwSize nzmax,
+                              mxComplexity flag);
+
+  extern OCTINTERP_API mxArray *
+  mxCreateSparseLogicalMatrix_interleaved (mwSize m, mwSize n, mwSize nzmax);
+
+  extern OCTINTERP_API mxArray *
+  mxCreateString_interleaved (const char *str);
+
+  extern OCTINTERP_API mxArray *
+  mxCreateStructArray_interleaved (mwSize ndims, const mwSize *dims,
+                                   int num_keys, const char **keys);
+
+  extern OCTINTERP_API mxArray *
+  mxCreateStructMatrix_interleaved (mwSize rows, mwSize cols, int num_keys,
+                                    const char **keys);
+
+  extern OCTINTERP_API int mxMakeArrayReal (mxArray *ptr);
+  extern OCTINTERP_API int mxMakeArrayComplex (mxArray *ptr);
+
+  extern OCTINTERP_API mxDouble * mxGetDoubles (const mxArray *p);
+  extern OCTINTERP_API mxSingle * mxGetSingles (const mxArray *p);
+  extern OCTINTERP_API mxInt8 * mxGetInt8s (const mxArray *p);
+  extern OCTINTERP_API mxInt16 * mxGetInt16s (const mxArray *p);
+  extern OCTINTERP_API mxInt32 * mxGetInt32s (const mxArray *p);
+  extern OCTINTERP_API mxInt64 * mxGetInt64s (const mxArray *p);
+  extern OCTINTERP_API mxUint8 * mxGetUint8s (const mxArray *p);
+  extern OCTINTERP_API mxUint16 * mxGetUint16s (const mxArray *p);
+  extern OCTINTERP_API mxUint32 * mxGetUint32s (const mxArray *p);
+  extern OCTINTERP_API mxUint64 * mxGetUint64s (const mxArray *p);
+
+  extern OCTINTERP_API mxComplexDouble * mxGetComplexDoubles (const mxArray *p);
+  extern OCTINTERP_API mxComplexSingle * mxGetComplexSingles (const mxArray *p);
+#if 0
+  /* We don't have these yet. */
+  extern OCTINTERP_API mxComplexInt8 * mxGetComplexInt8s (const mxArray *p);
+  extern OCTINTERP_API mxComplexInt16 * mxGetComplexInt16s (const mxArray *p);
+  extern OCTINTERP_API mxComplexInt32 * mxGetComplexInt32s (const mxArray *p);
+  extern OCTINTERP_API mxComplexInt64 * mxGetComplexInt64s (const mxArray *p);
+  extern OCTINTERP_API mxComplexUint8 * mxGetComplexUint8s (const mxArray *p);
+  extern OCTINTERP_API mxComplexUint16 * mxGetComplexUint16s (const mxArray *p);
+  extern OCTINTERP_API mxComplexUint32 * mxGetComplexUint32s (const mxArray *p);
+  extern OCTINTERP_API mxComplexUint64 * mxGetComplexUint64s (const mxArray *p);
+#endif
+
+  extern OCTINTERP_API double * mxGetPi (const mxArray *ptr);
+  extern OCTINTERP_API void * mxGetImagData (const mxArray *ptr);
+
+  extern OCTINTERP_API int mxSetDoubles (mxArray *p, mxDouble *d);
+  extern OCTINTERP_API int mxSetSingles (mxArray *p, mxSingle *d);
+  extern OCTINTERP_API int mxSetInt8s (mxArray *p, mxInt8 *d);
+  extern OCTINTERP_API int mxSetInt16s (mxArray *p, mxInt16 *d);
+  extern OCTINTERP_API int mxSetInt32s (mxArray *p, mxInt32 *d);
+  extern OCTINTERP_API int mxSetInt64s (mxArray *p, mxInt64 *d);
+  extern OCTINTERP_API int mxSetUint8s (mxArray *p, mxUint8 *d);
+  extern OCTINTERP_API int mxSetUint16s (mxArray *p, mxUint16 *d);
+  extern OCTINTERP_API int mxSetUint32s (mxArray *p, mxUint32 *d);
+  extern OCTINTERP_API int mxSetUint64s (mxArray *p, mxUint64 *d);
+
+  extern OCTINTERP_API int mxSetComplexDoubles (mxArray *p, mxComplexDouble *d);
+  extern OCTINTERP_API int mxSetComplexSingles (mxArray *p, mxComplexSingle *d);
+#if 0
+  /* We don't have these yet. */
+  extern OCTINTERP_API int mxSetComplexInt8s (mxArray *p, mxComplexInt8 *d);
+  extern OCTINTERP_API int mxSetComplexInt16s (mxArray *p, mxComplexInt16 *d);
+  extern OCTINTERP_API int mxSetComplexInt32s (mxArray *p, mxComplexInt32 *d);
+  extern OCTINTERP_API int mxSetComplexInt64s (mxArray *p, mxComplexInt64 *d);
+  extern OCTINTERP_API int mxSetComplexUint8s (mxArray *p, mxComplexUint8 *d);
+  extern OCTINTERP_API int mxSetComplexUint16s (mxArray *p, mxComplexUint16 *d);
+  extern OCTINTERP_API int mxSetComplexUint32s (mxArray *p, mxComplexUint32 *d);
+  extern OCTINTERP_API int mxSetComplexUint64s (mxArray *p, mxComplexUint64 *d);
+#endif
+
+  extern OCTINTERP_API void mxSetPi (mxArray *ptr, double *pi);
+  extern OCTINTERP_API void mxSetImagData (mxArray *ptr, void *pi);
+}
+
 // #define DEBUG 1
 
 static void
@@ -112,6 +303,10 @@
 
 // ------------------------------------------------------------------
 
+mxArray_base::mxArray_base (bool interleaved)
+  : m_interleaved (interleaved)
+{ }
+
 static mwIndex
 calc_single_subscript_internal (mwSize ndims, const mwSize *dims,
                                 mwSize nsubs, const mwIndex *subs)
@@ -157,13 +352,26 @@
 
 static inline void * maybe_mark_foreign (void *ptr);
 
+#define VOID_MUTATION_METHOD(FCN_NAME, ARG_LIST)        \
+  void FCN_NAME ARG_LIST { request_mutation (); }
+
+#define CONST_VOID_MUTATION_METHOD(FCN_NAME, ARG_LIST)  \
+  void FCN_NAME ARG_LIST const { request_mutation (); }
+
+#define MUTATION_METHOD(RET_TYPE, FCN_NAME, ARG_LIST, RET_VAL)          \
+  RET_TYPE FCN_NAME ARG_LIST { request_mutation (); return RET_VAL; }
+
+#define CONST_MUTATION_METHOD(RET_TYPE, FCN_NAME, ARG_LIST, RET_VAL)    \
+  RET_TYPE FCN_NAME ARG_LIST const { request_mutation (); return RET_VAL; }
+
 class mxArray_octave_value : public mxArray_base
 {
 public:
 
-  mxArray_octave_value (const octave_value& ov)
-    : mxArray_base (), val (ov), mutate_flag (false),
-      id (mxUNKNOWN_CLASS), class_name (nullptr), ndims (-1), dims (nullptr) { }
+  mxArray_octave_value (bool interleaved, const octave_value& ov)
+    : mxArray_base (interleaved), val (ov), mutate_flag (false),
+      id (mxUNKNOWN_CLASS), class_name (nullptr), ndims (-1), dims (nullptr)
+  { }
 
   // No assignment!  FIXME: should this be implemented?  Note that we
   // do have a copy constructor.
@@ -174,7 +382,7 @@
 
   mxArray * as_mxArray (void) const
   {
-    mxArray *retval = val.as_mxArray ();
+    mxArray *retval = val.as_mxArray (m_interleaved);
 
     // RETVAL is assumed to be an mxArray_matlab object.  Should we
     // assert that condition here?
@@ -303,16 +511,10 @@
     return ndims;
   }
 
-  void set_m (mwSize /*m*/) { request_mutation (); }
-
-  void set_n (mwSize /*n*/) { request_mutation (); }
-
-  int set_dimensions (mwSize * /*dims_arg*/, mwSize /*ndims_arg*/)
-  {
-    request_mutation ();
-
-    return 0;
-  }
+  VOID_MUTATION_METHOD (set_m, (mwSize))
+  VOID_MUTATION_METHOD (set_n, (mwSize))
+
+  MUTATION_METHOD (int, set_dimensions, (mwSize *, mwSize), 0)
 
   mwSize get_number_of_elements (void) const { return val.numel (); }
 
@@ -378,7 +580,7 @@
   }
 
   // Not allowed.
-  void set_class_name (const char * /*name_arg*/) { request_mutation (); }
+  VOID_MUTATION_METHOD (set_class_name, (const char *))
 
   mxArray * get_property (mwIndex idx, const char *pname) const
   {
@@ -393,7 +595,7 @@
             octave_value pval = ov_cdef->get_property (idx, pname);
 
             if (pval.is_defined())
-              retval = new mxArray (pval);
+              retval = new mxArray (m_interleaved, pval);
           }
       }
 
@@ -410,17 +612,13 @@
           ov_cdef->set_property (idx, pname, pval->as_octave_value ());
       }
     else
-      err_invalid_type ();
+      err_invalid_type ("set_property");
   }
 
-  mxArray * get_cell (mwIndex /*idx*/) const
-  {
-    request_mutation ();
-    return nullptr;
-  }
+  CONST_MUTATION_METHOD (mxArray *, get_cell, (mwIndex), nullptr)
 
   // Not allowed.
-  void set_cell (mwIndex /*idx*/, mxArray * /*val*/) { request_mutation (); }
+  VOID_MUTATION_METHOD (set_cell, (mwIndex, mxArray *))
 
   double get_scalar (void) const
   {
@@ -454,6 +652,61 @@
     return retval;
   }
 
+  template <typename T>
+  T * get_data (mxClassID class_id, mxComplexity complexity) const
+  {
+    T *retval = static_cast<T *> (val.mex_get_data (class_id, complexity));
+
+    if (retval)
+      maybe_mark_foreign (retval);
+    else
+      request_mutation ();
+
+    return retval;
+  }
+
+  CONST_MUTATION_METHOD (mxDouble *, get_doubles, (void), nullptr);
+
+  CONST_MUTATION_METHOD (mxSingle *, get_singles, (void), nullptr);
+
+  CONST_MUTATION_METHOD (mxInt8 *, get_int8s, (void), nullptr);
+
+  CONST_MUTATION_METHOD (mxInt16 *, get_int16s, (void), nullptr);
+
+  CONST_MUTATION_METHOD (mxInt32 *, get_int32s, (void), nullptr);
+
+  CONST_MUTATION_METHOD (mxInt64 *, get_int64s, (void), nullptr);
+
+  CONST_MUTATION_METHOD (mxUint8 *, get_uint8s, (void), nullptr);
+
+  CONST_MUTATION_METHOD (mxUint16 *, get_uint16s, (void), nullptr);
+
+  CONST_MUTATION_METHOD (mxUint32 *, get_uint32s, (void), nullptr);
+
+  CONST_MUTATION_METHOD (mxUint64 *, get_uint64s, (void), nullptr);
+
+  CONST_MUTATION_METHOD (mxComplexDouble *, get_complex_doubles, (void), nullptr);
+  CONST_MUTATION_METHOD (mxComplexSingle *, get_complex_singles, (void), nullptr);
+
+#if 0
+  /* We don't have these yet. */
+  CONST_MUTATION_METHOD (mxComplexInt8 *, get_complex_int8s, (void), nullptr);
+
+  CONST_MUTATION_METHOD (mxComplexInt16 *, get_complex_int16s, (void), nullptr);
+
+  CONST_MUTATION_METHOD (mxComplexInt32 *, get_complex_int32s, (void), nullptr);
+
+  CONST_MUTATION_METHOD (mxComplexInt64 *, get_complex_int64s, (void), nullptr);
+
+  CONST_MUTATION_METHOD (mxComplexUint8 *, get_complex_uint8s, (void), nullptr);
+
+  CONST_MUTATION_METHOD (mxComplexUint16 *, get_complex_uint16s, (void), nullptr);
+
+  CONST_MUTATION_METHOD (mxComplexUint32 *, get_complex_uint32s, (void), nullptr);
+
+  CONST_MUTATION_METHOD (mxComplexUint64 *, get_complex_uint64s, (void), nullptr);
+#endif
+
   void * get_imag_data (void) const
   {
     void *retval = nullptr;
@@ -467,10 +720,35 @@
   }
 
   // Not allowed.
-  void set_data (void * /*pr*/) { request_mutation (); }
+  VOID_MUTATION_METHOD (set_data, (void *))
+
+  MUTATION_METHOD (int, set_doubles, (mxDouble *), 0)
+  MUTATION_METHOD (int, set_singles, (mxSingle *), 0)
+  MUTATION_METHOD (int, set_int8s, (mxInt8 *), 0)
+  MUTATION_METHOD (int, set_int16s, (mxInt16 *), 0)
+  MUTATION_METHOD (int, set_int32s, (mxInt32 *), 0)
+  MUTATION_METHOD (int, set_int64s, (mxInt64 *), 0)
+  MUTATION_METHOD (int, set_uint8s, (mxUint8 *), 0)
+  MUTATION_METHOD (int, set_uint16s, (mxUint16 *), 0)
+  MUTATION_METHOD (int, set_uint32s, (mxUint32 *), 0)
+  MUTATION_METHOD (int, set_uint64s, (mxUint64 *), 0)
+
+  MUTATION_METHOD (int, set_complex_doubles, (mxComplexDouble *), 0)
+  MUTATION_METHOD (int, set_complex_singles, (mxComplexSingle *), 0)
+#if 0
+  /* We don't have these yet. */
+  MUTATION_METHOD (int, set_complex_int8s, (mxComplexInt8 *), 0)
+  MUTATION_METHOD (int, set_complex_int16s, (mxComplexInt16 *), 0)
+  MUTATION_METHOD (int, set_complex_int32s, (mxComplexInt32 *), 0)
+  MUTATION_METHOD (int, set_complex_int64s, (mxComplexInt64 *), 0)
+  MUTATION_METHOD (int, set_complex_uint8s, (mxComplexUint8 *), 0)
+  MUTATION_METHOD (int, set_complex_uint16s, (mxComplexUint16 *), 0)
+  MUTATION_METHOD (int, set_complex_uint32s, (mxComplexUint32 *), 0)
+  MUTATION_METHOD (int, set_complex_uint64s, (mxComplexUint64 *), 0)
+#endif
 
   // Not allowed.
-  void set_imag_data (void * /*pi*/) { request_mutation (); }
+  VOID_MUTATION_METHOD (set_imag_data, (void *))
 
   mwIndex * get_ir (void) const
   {
@@ -485,50 +763,30 @@
   mwSize get_nzmax (void) const { return val.nzmax (); }
 
   // Not allowed.
-  void set_ir (mwIndex * /*ir*/) { request_mutation (); }
-
-  // Not allowed.
-  void set_jc (mwIndex * /*jc*/) { request_mutation (); }
+  VOID_MUTATION_METHOD (set_ir, (mwIndex *))
 
   // Not allowed.
-  void set_nzmax (mwSize /*nzmax*/) { request_mutation (); }
+  VOID_MUTATION_METHOD (set_jc, (mwIndex *))
 
   // Not allowed.
-  int add_field (const char * /*key*/)
-  {
-    request_mutation ();
-    return 0;
-  }
+  VOID_MUTATION_METHOD (set_nzmax, (mwSize))
+
+  // Not allowed.
+  MUTATION_METHOD (int, add_field, (const char *), 0)
 
   // Not allowed.
-  void remove_field (int /*key_num*/) { request_mutation (); }
-
-  mxArray * get_field_by_number (mwIndex /*index*/, int /*key_num*/) const
-  {
-    request_mutation ();
-    return nullptr;
-  }
+  VOID_MUTATION_METHOD (remove_field, (int))
+
+  CONST_MUTATION_METHOD (mxArray *, get_field_by_number, (mwIndex, int), nullptr)
 
   // Not allowed.
-  void set_field_by_number (mwIndex /*index*/, int /*key_num*/,
-                            mxArray * /*val*/)
-  {
-    request_mutation ();
-  }
+  VOID_MUTATION_METHOD (set_field_by_number, (mwIndex, int, mxArray *))
 
   int get_number_of_fields (void) const { return val.nfields (); }
 
-  const char * get_field_name_by_number (int /*key_num*/) const
-  {
-    request_mutation ();
-    return nullptr;
-  }
-
-  int get_field_number (const char * /*key*/) const
-  {
-    request_mutation ();
-    return 0;
-  }
+  CONST_MUTATION_METHOD (const char *, get_field_name_by_number, (int), nullptr)
+
+  CONST_MUTATION_METHOD (int, get_field_number, (const char *), 0)
 
   int get_string (char *buf, mwSize buflen) const
   {
@@ -596,21 +854,21 @@
 
     switch (id)
       {
-      case mxDOUBLE_CLASS: return sizeof (double);
-      case mxSINGLE_CLASS: return sizeof (float);
-      case mxCHAR_CLASS: return sizeof (mxChar);
-      case mxLOGICAL_CLASS: return sizeof (mxLogical);
       case mxCELL_CLASS: return sizeof (mxArray *);
       case mxSTRUCT_CLASS: return sizeof (mxArray *);
+      case mxLOGICAL_CLASS: return sizeof (mxLogical);
+      case mxCHAR_CLASS: return sizeof (mxChar);
+      case mxDOUBLE_CLASS: return get_numeric_element_size (sizeof (mxDouble));
+      case mxSINGLE_CLASS: return get_numeric_element_size (sizeof (mxSingle));
+      case mxINT8_CLASS: return get_numeric_element_size (sizeof (mxInt8));
+      case mxUINT8_CLASS: return get_numeric_element_size (sizeof (mxUint8));
+      case mxINT16_CLASS: return get_numeric_element_size (sizeof (mxInt16));
+      case mxUINT16_CLASS: return get_numeric_element_size (sizeof (mxUint16));
+      case mxINT32_CLASS: return get_numeric_element_size (sizeof (mxInt32));
+      case mxUINT32_CLASS: return get_numeric_element_size (sizeof (mxUint32));
+      case mxINT64_CLASS: return get_numeric_element_size (sizeof (mxInt64));
+      case mxUINT64_CLASS: return get_numeric_element_size (sizeof (mxUint64));
       case mxFUNCTION_CLASS: return 0;
-      case mxINT8_CLASS: return 1;
-      case mxUINT8_CLASS: return 1;
-      case mxINT16_CLASS: return 2;
-      case mxUINT16_CLASS: return 2;
-      case mxINT32_CLASS: return 4;
-      case mxUINT32_CLASS: return 4;
-      case mxINT64_CLASS: return 8;
-      case mxUINT64_CLASS: return 8;
       // FIXME: user-defined objects need their own class ID.
       //        What should they return, size of pointer?
       default: return 0;
@@ -637,9 +895,9 @@
     : mxArray_base (arg), val (arg.val), mutate_flag (arg.mutate_flag),
       id (arg.id), class_name (mxArray::strsave (arg.class_name)),
       ndims (arg.ndims),
-      dims (ndims > 0 ? static_cast<mwSize *>
-                         (mxArray::malloc (ndims * sizeof (mwSize)))
-                      : nullptr)
+      dims (ndims > 0
+            ? static_cast<mwSize *> (mxArray::malloc (ndims * sizeof (mwSize)))
+            : nullptr)
   {
     if (dims)
       {
@@ -671,13 +929,14 @@
 {
 protected:
 
-  mxArray_matlab (mxClassID id_arg = mxUNKNOWN_CLASS)
-    : mxArray_base (), class_name (nullptr), id (id_arg), ndims (0),
+  mxArray_matlab (bool interleaved, mxClassID id_arg = mxUNKNOWN_CLASS)
+    : mxArray_base (interleaved), class_name (nullptr), id (id_arg), ndims (0),
       dims (nullptr)
   { }
 
-  mxArray_matlab (mxClassID id_arg, mwSize ndims_arg, const mwSize *dims_arg)
-    : mxArray_base (), class_name (nullptr), id (id_arg),
+  mxArray_matlab (bool interleaved, mxClassID id_arg, mwSize ndims_arg,
+                  const mwSize *dims_arg)
+    : mxArray_base (interleaved), class_name (nullptr), id (id_arg),
       ndims (ndims_arg < 2 ? 2 : ndims_arg),
       dims (static_cast<mwSize *> (mxArray::malloc (ndims * sizeof (mwSize))))
   {
@@ -704,8 +963,8 @@
       }
   }
 
-  mxArray_matlab (mxClassID id_arg, const dim_vector& dv)
-    : mxArray_base (), class_name (nullptr), id (id_arg),
+  mxArray_matlab (bool interleaved, mxClassID id_arg, const dim_vector& dv)
+    : mxArray_base (interleaved), class_name (nullptr), id (id_arg),
       ndims (dv.ndims ()),
       dims (static_cast<mwSize *> (mxArray::malloc (ndims * sizeof (mwSize))))
   {
@@ -721,8 +980,8 @@
       }
   }
 
-  mxArray_matlab (mxClassID id_arg, mwSize m, mwSize n)
-    : mxArray_base (), class_name (nullptr), id (id_arg), ndims (2),
+  mxArray_matlab (bool interleaved, mxClassID id_arg, mwSize m, mwSize n)
+    : mxArray_base (interleaved), class_name (nullptr), id (id_arg), ndims (2),
       dims (static_cast<mwSize *> (mxArray::malloc (ndims * sizeof (mwSize))))
   {
     dims[0] = m;
@@ -900,98 +1159,304 @@
 
   mxArray * get_cell (mwIndex /*idx*/) const
   {
-    err_invalid_type ();
+    err_invalid_type ("get_cell");
   }
 
   void set_cell (mwIndex /*idx*/, mxArray * /*val*/)
   {
-    err_invalid_type ();
+    err_invalid_type ("set_cell");
   }
 
   double get_scalar (void) const
   {
-    err_invalid_type ();
+    err_invalid_type ("get_scalar");
   }
 
   void * get_data (void) const
   {
-    err_invalid_type ();
+    err_invalid_type ("get_data");
+  }
+
+  mxDouble * get_doubles (void) const
+  {
+    err_invalid_type ("get_doubles");
+  }
+
+  mxSingle * get_singles (void) const
+  {
+    err_invalid_type ("get_singles");
+  }
+
+  mxInt8 * get_int8s (void) const
+  {
+    err_invalid_type ("get_int8s");
+  }
+
+  mxInt16 * get_int16s (void) const
+  {
+    err_invalid_type ("get_int16s");
+  }
+
+  mxInt32 * get_int32s (void) const
+  {
+    err_invalid_type ("get_int32s");
+  }
+
+  mxInt64 * get_int64s (void) const
+  {
+    err_invalid_type ("get_int64s");
+  }
+
+  mxUint8 * get_uint8s (void) const
+  {
+    err_invalid_type ("get_uint8s");
+  }
+
+  mxUint16 * get_uint16s (void) const
+  {
+    err_invalid_type ("get_uint16s");
+  }
+
+  mxUint32 * get_uint32s (void) const
+  {
+    err_invalid_type ("get_uint32s");
+  }
+
+  mxUint64 * get_uint64s (void) const
+  {
+    err_invalid_type ("get_uint64s");
   }
 
+  mxComplexDouble * get_complex_doubles (void) const
+  {
+    err_invalid_type ("get_complex_doubles");
+  }
+
+  mxComplexSingle * get_complex_singles (void) const
+  {
+    err_invalid_type ("get_complex_singles");
+  }
+
+#if 0
+  /* We don't have these yet. */
+  mxComplexInt8 * get_complex_int8s (void) const
+  {
+    err_invalid_type ("get_complex_int8s");
+  }
+
+  mxComplexInt16 * get_complex_int16s (void) const
+  {
+    err_invalid_type ("get_complex_int16s");
+  }
+
+  mxComplexInt32 * get_complex_int32s (void) const
+  {
+    err_invalid_type ("get_complex_int32s");
+  }
+
+  mxComplexInt64 * get_complex_int64s (void) const
+  {
+    err_invalid_type ("get_complex_int64s");
+  }
+
+  mxComplexUint8 * get_complex_uint8s (void) const
+  {
+    err_invalid_type ("get_complex_uint8s");
+  }
+
+  mxComplexUint16 * get_complex_uint16s (void) const
+  {
+    err_invalid_type ("get_complex_uint16s");
+  }
+
+  mxComplexUint32 * get_complex_uint32s (void) const
+  {
+    err_invalid_type ("get_complex_uint32s");
+  }
+
+  mxComplexUint64 * get_complex_uint64s (void) const
+  {
+    err_invalid_type ("get_complex_uint64s");
+  }
+#endif
+
   void * get_imag_data (void) const
   {
-    err_invalid_type ();
+    err_invalid_type ("get_imag_data");
   }
 
   void set_data (void * /*pr*/)
   {
-    err_invalid_type ();
+    err_invalid_type ("set_data");
+  }
+
+  int set_doubles (mxDouble *)
+  {
+    err_invalid_type ("set_doubles");
+  }
+
+  int set_singles (mxSingle *)
+  {
+    err_invalid_type ("set_singles");
+  }
+
+  int set_int8s (mxInt8 *)
+  {
+    err_invalid_type ("set_int8s");
+  }
+
+  int set_int16s (mxInt16 *)
+  {
+    err_invalid_type ("set_int16s");
+  }
+
+  int set_int32s (mxInt32 *)
+  {
+    err_invalid_type ("set_int32s");
+  }
+
+  int set_int64s (mxInt64 *)
+  {
+    err_invalid_type ("set_int64s");
+  }
+
+  int set_uint8s (mxUint8 *)
+  {
+    err_invalid_type ("set_uint8s");
+  }
+
+  int set_uint16s (mxUint16 *)
+  {
+    err_invalid_type ("set_uint16s");
+  }
+
+  int set_uint32s (mxUint32 *)
+  {
+    err_invalid_type ("set_uint32s");
+  }
+
+  int set_uint64s (mxUint64 *)
+  {
+    err_invalid_type ("set_uint64s");
   }
 
+  int set_complex_doubles (mxComplexDouble *)
+  {
+    err_invalid_type ("set_complex_doubles");
+  }
+
+  int set_complex_singles (mxComplexSingle *)
+  {
+    err_invalid_type ("set_complex_singles");
+  }
+
+#if 0
+  /* We don't have these yet. */
+  int set_complex_int8s (mxComplexInt8 *)
+  {
+    err_invalid_type ("set_complex_int8s");
+  }
+
+  int set_complex_int16s (mxComplexInt16 *)
+  {
+    err_invalid_type ("set_complex_int16s");
+  }
+
+  int set_complex_int32s (mxComplexInt32 *)
+  {
+    err_invalid_type ("set_complex_int32s");
+  }
+
+  int set_complex_int64s (mxComplexInt64 *)
+  {
+    err_invalid_type ("set_complex_int64s");
+  }
+
+  int set_complex_uint8s (mxComplexUint8 *)
+  {
+    err_invalid_type ("set_complex_uint8s");
+  }
+
+  int set_complex_uint16s (mxComplexUint16 *)
+  {
+    err_invalid_type ("set_complex_uint16s");
+  }
+
+  int set_complex_uint32s (mxComplexUint32 *)
+  {
+    err_invalid_type ("set_complex_uint32s");
+  }
+
+  int set_complex_uint64s (mxComplexUint64 *)
+  {
+    err_invalid_type ("set_complex_uint64s");
+  }
+#endif
+
   void set_imag_data (void * /*pi*/)
   {
-    err_invalid_type ();
+    err_invalid_type ("set_imag_data");
   }
 
   mwIndex * get_ir (void) const
   {
-    err_invalid_type ();
+    err_invalid_type ("get_ir");
   }
 
   mwIndex * get_jc (void) const
   {
-    err_invalid_type ();
+    err_invalid_type ("get_jc");
   }
 
   mwSize get_nzmax (void) const
   {
-    err_invalid_type ();
+    err_invalid_type ("get_nzmax");
   }
 
   void set_ir (mwIndex * /*ir*/)
   {
-    err_invalid_type ();
+    err_invalid_type ("set_ir");
   }
 
   void set_jc (mwIndex * /*jc*/)
   {
-    err_invalid_type ();
+    err_invalid_type ("set_jc");
   }
 
   void set_nzmax (mwSize /*nzmax*/)
   {
-    err_invalid_type ();
+    err_invalid_type ("set_nzmax");
   }
 
   int add_field (const char * /*key*/)
   {
-    err_invalid_type ();
+    err_invalid_type ("add_field");
   }
 
   void remove_field (int /*key_num*/)
   {
-    err_invalid_type ();
+    err_invalid_type ("remove_field");
   }
 
   mxArray * get_field_by_number (mwIndex /*index*/, int /*key_num*/) const
   {
-    err_invalid_type ();
+    err_invalid_type ("get_field_by_number");
   }
 
   void set_field_by_number (mwIndex /*index*/, int /*key_num*/,
                             mxArray * /*val*/)
   {
-    err_invalid_type ();
+    err_invalid_type ("set_field_by_number");
   }
 
   int get_number_of_fields (void) const
   {
-    err_invalid_type ();
+    err_invalid_type ("get_number_of_fields");
   }
 
   const char * get_field_name_by_number (int /*key_num*/) const
   {
-    err_invalid_type ();
+    err_invalid_type ("get_field_name_by_number");
   }
 
   int get_field_number (const char * /*key*/) const
@@ -1001,12 +1466,12 @@
 
   int get_string (char * /*buf*/, mwSize /*buflen*/) const
   {
-    err_invalid_type ();
+    err_invalid_type ("get_string");
   }
 
   char * array_to_string (void) const
   {
-    err_invalid_type ();
+    err_invalid_type ("array_to_string");
   }
 
   mwIndex calc_single_subscript (mwSize nsubs, mwIndex *subs) const
@@ -1022,16 +1487,16 @@
       case mxSTRUCT_CLASS: return sizeof (mxArray *);
       case mxLOGICAL_CLASS: return sizeof (mxLogical);
       case mxCHAR_CLASS: return sizeof (mxChar);
-      case mxDOUBLE_CLASS: return sizeof (double);
-      case mxSINGLE_CLASS: return sizeof (float);
-      case mxINT8_CLASS: return 1;
-      case mxUINT8_CLASS: return 1;
-      case mxINT16_CLASS: return 2;
-      case mxUINT16_CLASS: return 2;
-      case mxINT32_CLASS: return 4;
-      case mxUINT32_CLASS: return 4;
-      case mxINT64_CLASS: return 8;
-      case mxUINT64_CLASS: return 8;
+      case mxDOUBLE_CLASS: return get_numeric_element_size (sizeof (mxDouble));
+      case mxSINGLE_CLASS: return get_numeric_element_size (sizeof (mxSingle));
+      case mxINT8_CLASS: return get_numeric_element_size (sizeof (mxInt8));
+      case mxUINT8_CLASS: return get_numeric_element_size (sizeof (mxUint8));
+      case mxINT16_CLASS: return get_numeric_element_size (sizeof (mxInt16));
+      case mxUINT16_CLASS: return get_numeric_element_size (sizeof (mxUint16));
+      case mxINT32_CLASS: return get_numeric_element_size (sizeof (mxInt32));
+      case mxUINT32_CLASS: return get_numeric_element_size (sizeof (mxUint32));
+      case mxINT64_CLASS: return get_numeric_element_size (sizeof (mxInt64));
+      case mxUINT64_CLASS: return get_numeric_element_size (sizeof (mxUint64));
       case mxFUNCTION_CLASS: return 0;
       // FIXME: user-defined objects need their own class ID.
       //        What should they return, size of pointer?
@@ -1065,59 +1530,79 @@
 
   mwSize ndims;
   mwSize *dims;
-
-  OCTAVE_NORETURN void err_invalid_type (void) const
-  {
-    error ("invalid type for operation");
-  }
 };
 
+
 // Matlab-style numeric, character, and logical data.
 
+#define TYPED_GET_METHOD(TYPE, FCN_NAME)        \
+  TYPE FCN_NAME (void) const                    \
+  {                                             \
+    if (! m_interleaved)                        \
+      panic_impossible ();                      \
+                                                \
+    return static_cast<TYPE> (pr);              \
+  }
+
+#define TYPED_SET_METHOD(TYPE, FCN_NAME)        \
+  int FCN_NAME (TYPE d)                         \
+  {                                             \
+    if (! m_interleaved)                        \
+      panic_impossible ();                      \
+                                                \
+    pr = d;                                     \
+    return 0;                                   \
+  }
+
 class mxArray_number : public mxArray_matlab
 {
 public:
 
-  mxArray_number (mxClassID id_arg, mwSize ndims_arg, const mwSize *dims_arg,
-                  mxComplexity flag = mxREAL, bool init = true)
-    : mxArray_matlab (id_arg, ndims_arg, dims_arg),
-      pr (init ? mxArray::calloc (get_number_of_elements (),
-                                  get_element_size ())
-               : mxArray::malloc (get_number_of_elements ()
-                                  * get_element_size ())),
-      pi (flag == mxCOMPLEX
-            ? (init ? mxArray::calloc (get_number_of_elements (),
-                                       get_element_size ())
-                    : mxArray::malloc (get_number_of_elements ()
-                                       * get_element_size ()))
-            : nullptr) { }
-
-  mxArray_number (mxClassID id_arg, const dim_vector& dv,
+  mxArray_number (bool interleaved, mxClassID id_arg, mwSize ndims_arg,
+                  const mwSize *dims_arg, mxComplexity flag = mxREAL,
+                  bool init = true)
+    : mxArray_matlab (interleaved, id_arg, ndims_arg, dims_arg),
+      m_complex (flag == mxCOMPLEX),
+      pr (init
+          ? mxArray::calloc (get_number_of_elements (), get_element_size ())
+          : mxArray::malloc (get_number_of_elements () * get_element_size ())),
+      pi (m_interleaved
+          ? nullptr
+          : (m_complex
+             ? (init
+                ? mxArray::calloc (get_number_of_elements (), get_element_size ())
+                : mxArray::malloc (get_number_of_elements () * get_element_size ()))
+             : nullptr))
+  { }
+
+  mxArray_number (bool interleaved, mxClassID id_arg, const dim_vector& dv,
                   mxComplexity flag = mxREAL)
-    : mxArray_matlab (id_arg, dv),
+    : mxArray_matlab (interleaved, id_arg, dv), m_complex (flag == mxCOMPLEX),
       pr (mxArray::calloc (get_number_of_elements (), get_element_size ())),
-      pi (flag == mxCOMPLEX ? mxArray::calloc (get_number_of_elements (),
-                                               get_element_size ())
-                            : nullptr)
+      pi (m_interleaved
+          ? nullptr
+          : (m_complex
+             ? mxArray::calloc (get_number_of_elements (), get_element_size ())
+             : nullptr))
   { }
 
-  mxArray_number (mxClassID id_arg, mwSize m, mwSize n,
+  mxArray_number (bool interleaved, mxClassID id_arg, mwSize m, mwSize n,
                   mxComplexity flag = mxREAL, bool init = true)
-    : mxArray_matlab (id_arg, m, n),
-      pr (init ? mxArray::calloc (get_number_of_elements (),
-                                  get_element_size ())
-               : mxArray::malloc (get_number_of_elements ()
-                                  * get_element_size ())),
-      pi (flag == mxCOMPLEX
-            ? (init ? mxArray::calloc (get_number_of_elements (),
-                                       get_element_size ())
-                    : mxArray::malloc (get_number_of_elements ()
-                                       * get_element_size ()))
-            : nullptr)
+    : mxArray_matlab (interleaved, id_arg, m, n), m_complex (flag == mxCOMPLEX),
+      pr (init
+          ? mxArray::calloc (get_number_of_elements (), get_element_size ())
+          : mxArray::malloc (get_number_of_elements () * get_element_size ())),
+      pi (m_interleaved
+          ? nullptr
+          : (m_complex
+             ? (init
+                ? mxArray::calloc (get_number_of_elements (), get_element_size ())
+                : mxArray::malloc (get_number_of_elements () * get_element_size ()))
+             : nullptr))
   { }
 
-  mxArray_number (mxClassID id_arg, double val)
-    : mxArray_matlab (id_arg, 1, 1),
+  mxArray_number (bool interleaved, mxClassID id_arg, double val)
+    : mxArray_matlab (interleaved, id_arg, 1, 1), m_complex (false),
       pr (mxArray::calloc (get_number_of_elements (), get_element_size ())),
       pi (nullptr)
   {
@@ -1125,8 +1610,8 @@
     dpr[0] = val;
   }
 
-  mxArray_number (mxClassID id_arg, mxLogical val)
-    : mxArray_matlab (id_arg, 1, 1),
+  mxArray_number (bool interleaved, mxClassID id_arg, mxLogical val)
+    : mxArray_matlab (interleaved, id_arg, 1, 1), m_complex (false),
       pr (mxArray::calloc (get_number_of_elements (), get_element_size ())),
       pi (nullptr)
   {
@@ -1134,10 +1619,11 @@
     lpr[0] = val;
   }
 
-  mxArray_number (const char *str)
-    : mxArray_matlab (mxCHAR_CLASS,
+  mxArray_number (bool interleaved, const char *str)
+    : mxArray_matlab (interleaved, mxCHAR_CLASS,
                       str ? (strlen (str) ? 1 : 0) : 0,
                       str ? strlen (str) : 0),
+      m_complex (false),
       pr (mxArray::calloc (get_number_of_elements (), get_element_size ())),
       pi (nullptr)
   {
@@ -1148,8 +1634,9 @@
   }
 
   // FIXME: ???
-  mxArray_number (mwSize m, const char **str)
-    : mxArray_matlab (mxCHAR_CLASS, m, max_str_len (m, str)),
+  mxArray_number (bool interleaved, mwSize m, const char **str)
+    : mxArray_matlab (interleaved, mxCHAR_CLASS, m, max_str_len (m, str)),
+      m_complex (false),
       pr (mxArray::calloc (get_number_of_elements (), get_element_size ())),
       pi (nullptr)
   {
@@ -1176,11 +1663,13 @@
 protected:
 
   mxArray_number (const mxArray_number& val)
-    : mxArray_matlab (val),
+    : mxArray_matlab (val), m_complex (val.m_complex),
       pr (mxArray::malloc (get_number_of_elements () * get_element_size ())),
-      pi (val.pi ? mxArray::malloc (get_number_of_elements ()
-                                    * get_element_size ())
-                 : nullptr)
+      pi (m_interleaved
+          ? nullptr
+          : (val.pi
+             ? mxArray::malloc (get_number_of_elements () * get_element_size ())
+             : nullptr))
   {
     size_t nbytes = get_number_of_elements () * get_element_size ();
 
@@ -1198,7 +1687,10 @@
 
   mxArray_number& operator = (const mxArray_number&);
 
-  mxArray_base * dup (void) const { return new mxArray_number (*this); }
+  mxArray_base * dup (void) const
+  {
+    return new mxArray_number (*this);
+  }
 
   ~mxArray_number (void)
   {
@@ -1206,10 +1698,15 @@
     mxFree (pi);
   }
 
-  int is_complex (void) const { return pi != nullptr; }
+  int is_complex (void) const
+  {
+    return m_interleaved ? m_complex : (pi != nullptr);
+  }
 
   double get_scalar (void) const
   {
+    // FIXME: how does this work for interleaved complex arrays?
+
     double retval = 0;
 
     switch (get_class_id ())
@@ -1271,11 +1768,73 @@
 
   void * get_data (void) const { return pr; }
 
-  void * get_imag_data (void) const { return pi; }
+  void * get_imag_data (void) const
+  {
+    if (m_interleaved)
+      panic_impossible ();
+
+    return pi;
+  }
 
   void set_data (void *pr_arg) { pr = pr_arg; }
 
-  void set_imag_data (void *pi_arg) { pi = pi_arg; }
+  void set_imag_data (void *pi_arg)
+  {
+    if (m_interleaved)
+      panic_impossible ();
+
+    pi = pi_arg;
+  }
+
+  TYPED_GET_METHOD (mxDouble *, get_doubles)
+  TYPED_GET_METHOD (mxSingle *, get_singles)
+  TYPED_GET_METHOD (mxInt8 *, get_int8s)
+  TYPED_GET_METHOD (mxInt16 *, get_int16s)
+  TYPED_GET_METHOD (mxInt32 *, get_int32s)
+  TYPED_GET_METHOD (mxInt64 *, get_int64s)
+  TYPED_GET_METHOD (mxUint8 *, get_uint8s)
+  TYPED_GET_METHOD (mxUint16 *, get_uint16s)
+  TYPED_GET_METHOD (mxUint32 *, get_uint32s)
+  TYPED_GET_METHOD (mxUint64 *, get_uint64s)
+
+  TYPED_GET_METHOD (mxComplexDouble *, get_complex_doubles)
+  TYPED_GET_METHOD (mxComplexSingle *, get_complex_singles)
+#if 0
+  /* We don't have these yet. */
+  TYPED_GET_METHOD (mxComplexInt8 *, get_complex_int8s)
+  TYPED_GET_METHOD (mxComplexInt16 *, get_complex_int16s)
+  TYPED_GET_METHOD (mxComplexInt32 *, get_complex_int32s)
+  TYPED_GET_METHOD (mxComplexInt64 *, get_complex_int64s)
+  TYPED_GET_METHOD (mxComplexUint8 *, get_complex_uint8s)
+  TYPED_GET_METHOD (mxComplexUint16 *, get_complex_uint16s)
+  TYPED_GET_METHOD (mxComplexUint32 *, get_complex_uint32s)
+  TYPED_GET_METHOD (mxComplexUint64 *, get_complex_uint64s)
+#endif
+
+  TYPED_SET_METHOD (mxDouble *, set_doubles)
+  TYPED_SET_METHOD (mxSingle *, set_singles)
+  TYPED_SET_METHOD (mxInt8 *, set_int8s)
+  TYPED_SET_METHOD (mxInt16 *, set_int16s)
+  TYPED_SET_METHOD (mxInt32 *, set_int32s)
+  TYPED_SET_METHOD (mxInt64 *, set_int64s)
+  TYPED_SET_METHOD (mxUint8 *, set_uint8s)
+  TYPED_SET_METHOD (mxUint16 *, set_uint16s)
+  TYPED_SET_METHOD (mxUint32 *, set_uint32s)
+  TYPED_SET_METHOD (mxUint64 *, set_uint64s)
+
+  TYPED_SET_METHOD (mxComplexDouble *, set_complex_doubles)
+  TYPED_SET_METHOD (mxComplexSingle *, set_complex_singles)
+#if 0
+  /* We don't have these yet. */
+  TYPED_SET_METHOD (mxComplexInt8 *, set_complex_int8s)
+  TYPED_SET_METHOD (mxComplexInt16 *, set_complex_int16s)
+  TYPED_SET_METHOD (mxComplexInt32 *, set_complex_int32s)
+  TYPED_SET_METHOD (mxComplexInt64 *, set_complex_int64s)
+  TYPED_SET_METHOD (mxComplexUint8 *, set_complex_uint8s)
+  TYPED_SET_METHOD (mxComplexUint16 *, set_complex_uint16s)
+  TYPED_SET_METHOD (mxComplexUint32 *, set_complex_uint32s)
+  TYPED_SET_METHOD (mxComplexUint64 *, set_complex_uint64s)
+#endif
 
   int get_string (char *buf, mwSize buflen) const
   {
@@ -1336,23 +1895,40 @@
         {
           mwSize nel = get_number_of_elements ();
 
-          double *ppr = static_cast<double *> (pr);
-
-          if (pi)
+          if (is_complex ())
             {
-              ComplexNDArray val (dv);
-
-              Complex *ptr = val.fortran_vec ();
-
-              double *ppi = static_cast<double *> (pi);
-
-              for (mwIndex i = 0; i < nel; i++)
-                ptr[i] = Complex (ppr[i], ppi[i]);
-
-              retval = val;
+              if (m_interleaved)
+                {
+                  Complex *ppr = static_cast<Complex *> (pr);
+
+                  ComplexNDArray val (dv);
+                  Complex *ptr = val.fortran_vec ();
+
+                  for (mwIndex i = 0; i < nel; i++)
+                    ptr[i] = ppr[i];
+
+                  retval = val;
+                }
+              else
+                {
+                  double *ppr = static_cast<double *> (pr);
+
+                  ComplexNDArray val (dv);
+
+                  Complex *ptr = val.fortran_vec ();
+
+                  double *ppi = static_cast<double *> (pi);
+
+                  for (mwIndex i = 0; i < nel; i++)
+                    ptr[i] = Complex (ppr[i], ppi[i]);
+
+                  retval = val;
+                }
             }
           else
             {
+              double *ppr = static_cast<double *> (pr);
+
               NDArray val (dv);
 
               double *ptr = val.fortran_vec ();
@@ -1369,23 +1945,40 @@
         {
           mwSize nel = get_number_of_elements ();
 
-          float *ppr = static_cast<float *> (pr);
-
-          if (pi)
+          if (is_complex ())
             {
-              FloatComplexNDArray val (dv);
-
-              FloatComplex *ptr = val.fortran_vec ();
-
-              float *ppi = static_cast<float *> (pi);
-
-              for (mwIndex i = 0; i < nel; i++)
-                ptr[i] = FloatComplex (ppr[i], ppi[i]);
-
-              retval = val;
+              if (m_interleaved)
+                {
+                  FloatComplex *ppr = static_cast<FloatComplex *> (pr);
+
+                  FloatComplexNDArray val (dv);
+                  FloatComplex *ptr = val.fortran_vec ();
+
+                  for (mwIndex i = 0; i < nel; i++)
+                    ptr[i] = ppr[i];
+
+                  retval = val;
+                }
+              else
+                {
+                  float *ppr = static_cast<float *> (pr);
+
+                  FloatComplexNDArray val (dv);
+
+                  FloatComplex *ptr = val.fortran_vec ();
+
+                  float *ppi = static_cast<float *> (pi);
+
+                  for (mwIndex i = 0; i < nel; i++)
+                    ptr[i] = FloatComplex (ppr[i], ppi[i]);
+
+                  retval = val;
+                }
             }
           else
             {
+              float *ppr = static_cast<float *> (pr);
+
               FloatNDArray val (dv);
 
               float *ptr = val.fortran_vec ();
@@ -1464,7 +2057,7 @@
   octave_value
   int_to_ov (const dim_vector& dv) const
   {
-    if (pi)
+    if (is_complex ())
       error ("complex integer types are not supported");
 
     mwSize nel = get_number_of_elements ();
@@ -1483,7 +2076,17 @@
 
 private:
 
+  // Flag to identify complex object if using interleaved data and PI is
+  // always nullptr.
+  bool m_complex;
+
+  // If using interleaved complex storage, this is the pointer to data
+  // (real, complex, or logical).  Otherwise, it is the pointer to the
+  // real part of the data.
   void *pr;
+
+  // If using non-interleaved complex storage, this is the pointer to
+  // the imaginary part of the data.  Othrwise is is always nullptr.
   void *pi;
 };
 
@@ -1493,24 +2096,31 @@
 {
 public:
 
-  mxArray_sparse (mxClassID id_arg, mwSize m, mwSize n, mwSize nzmax_arg,
-                  mxComplexity flag = mxREAL)
-    : mxArray_matlab (id_arg, m, n)
-  {
-    nzmax = (nzmax_arg > 0 ? nzmax_arg : 1);
-    pr = mxArray::calloc (nzmax, get_element_size ());
-    pi = (flag == mxCOMPLEX ? mxArray::calloc (nzmax, get_element_size ())
-                            : nullptr);
-    ir = (static_cast<mwIndex *> (mxArray::calloc (nzmax, sizeof (mwIndex))));
-    jc = (static_cast<mwIndex *> (mxArray::calloc (n + 1, sizeof (mwIndex))));
-  }
+  mxArray_sparse (bool interleaved, mxClassID id_arg, mwSize m, mwSize n,
+                  mwSize nzmax_arg, mxComplexity flag = mxREAL)
+    : mxArray_matlab (interleaved, id_arg, m, n), m_complex (flag == mxCOMPLEX),
+
+      nzmax (nzmax_arg > 0 ? nzmax_arg : 1),
+      pr (mxArray::calloc (nzmax, get_element_size ())),
+      pi (m_interleaved
+          ? nullptr
+          : (m_complex
+             ? mxArray::calloc (nzmax, get_element_size ())
+             : nullptr)),
+      ir (static_cast<mwIndex *> (mxArray::calloc (nzmax, sizeof (mwIndex)))),
+      jc (static_cast<mwIndex *> (mxArray::calloc (n + 1, sizeof (mwIndex))))
+  { }
 
 private:
 
   mxArray_sparse (const mxArray_sparse& val)
     : mxArray_matlab (val), nzmax (val.nzmax),
       pr (mxArray::malloc (nzmax * get_element_size ())),
-      pi (val.pi ? mxArray::malloc (nzmax * get_element_size ()) : nullptr),
+      pi (m_interleaved
+          ? nullptr
+          : (val.pi
+             ? mxArray::malloc (nzmax * get_element_size ())
+             : nullptr)),
       ir (static_cast<mwIndex *> (mxArray::malloc (nzmax * sizeof (mwIndex)))),
       jc (static_cast<mwIndex *> (mxArray::malloc (nzmax * sizeof (mwIndex))))
   {
@@ -1536,7 +2146,10 @@
 
   mxArray_sparse& operator = (const mxArray_sparse&);
 
-  mxArray_base * dup (void) const { return new mxArray_sparse (*this); }
+  mxArray_base * dup (void) const
+  {
+    return new mxArray_sparse (*this);
+  }
 
   ~mxArray_sparse (void)
   {
@@ -1546,17 +2159,38 @@
     mxFree (jc);
   }
 
-  int is_complex (void) const { return pi != nullptr; }
+  int is_complex (void) const
+  {
+    return m_interleaved ? m_complex : (pi != nullptr);
+  }
 
   int is_sparse (void) const { return 1; }
 
   void * get_data (void) const { return pr; }
 
-  void * get_imag_data (void) const { return pi; }
+  void * get_imag_data (void) const
+  {
+    if (m_interleaved)
+      panic_impossible ();
+
+    return pi;
+  }
 
   void set_data (void *pr_arg) { pr = pr_arg; }
 
-  void set_imag_data (void *pi_arg) { pi = pi_arg; }
+  void set_imag_data (void *pi_arg)
+  {
+    if (m_interleaved)
+      panic_impossible ();
+
+    pi = pi_arg;
+  }
+
+  TYPED_GET_METHOD (mxDouble *, get_doubles)
+  TYPED_GET_METHOD (mxComplexDouble *, get_complex_doubles)
+
+  TYPED_SET_METHOD (mxDouble *, set_doubles)
+  TYPED_SET_METHOD (mxComplexDouble *, set_complex_doubles)
 
   mwIndex * get_ir (void) const { return ir; }
 
@@ -1584,24 +2218,45 @@
       {
       case mxDOUBLE_CLASS:
         {
-          if (pi)
+          if (is_complex ())
             {
-              double *ppr = static_cast<double *> (pr);
-              double *ppi = static_cast<double *> (pi);
-
-              SparseComplexMatrix val (get_m (), get_n (),
-                                       static_cast<octave_idx_type> (nzmax));
-
-              for (mwIndex i = 0; i < nzmax; i++)
+              if (m_interleaved)
                 {
-                  val.xdata (i) = Complex (ppr[i], ppi[i]);
-                  val.xridx (i) = ir[i];
+                  Complex *ppr = static_cast<Complex *> (pr);
+
+                  SparseComplexMatrix val (get_m (), get_n (),
+                                           static_cast<octave_idx_type> (nzmax));
+
+                  for (mwIndex i = 0; i < nzmax; i++)
+                    {
+                      val.xdata (i) = ppr[i];
+                      val.xridx (i) = ir[i];
+                    }
+
+                  for (mwIndex i = 0; i < get_n () + 1; i++)
+                    val.xcidx (i) = jc[i];
+
+                  retval = val;
                 }
-
-              for (mwIndex i = 0; i < get_n () + 1; i++)
-                val.xcidx (i) = jc[i];
-
-              retval = val;
+              else
+                {
+                  double *ppr = static_cast<double *> (pr);
+                  double *ppi = static_cast<double *> (pi);
+
+                  SparseComplexMatrix val (get_m (), get_n (),
+                                           static_cast<octave_idx_type> (nzmax));
+
+                  for (mwIndex i = 0; i < nzmax; i++)
+                    {
+                      val.xdata (i) = Complex (ppr[i], ppi[i]);
+                      val.xridx (i) = ir[i];
+                    }
+
+                  for (mwIndex i = 0; i < get_n () + 1; i++)
+                    val.xcidx (i) = jc[i];
+
+                  retval = val;
+                }
             }
           else
             {
@@ -1657,10 +2312,23 @@
 
 private:
 
+  // Flag to identify complex object if using interleaved data and PI is
+  // always nullptr.
+  bool m_complex;
+
+  // Maximun number of nonzero elements.
   mwSize nzmax;
 
+  // If using interleaved complex storage, this is the pointer to data
+  // (real, complex, or logical).  Otherwise, it is the pointer to the
+  // real part of the data.
   void *pr;
+
+  // If using non-interleaved complex storage, this is the pointer to
+  // the imaginary part of the data.  Othrwise is is always nullptr.
   void *pi;
+
+  // Sparse storage indexing arrays.
   mwIndex *ir;
   mwIndex *jc;
 };
@@ -1671,9 +2339,9 @@
 {
 public:
 
-  mxArray_struct (mwSize ndims_arg, const mwSize *dims_arg, int num_keys_arg,
-                  const char **keys)
-    : mxArray_matlab (mxSTRUCT_CLASS, ndims_arg, dims_arg),
+  mxArray_struct (bool interleaved, mwSize ndims_arg, const mwSize *dims_arg,
+                  int num_keys_arg, const char **keys)
+    : mxArray_matlab (interleaved, mxSTRUCT_CLASS, ndims_arg, dims_arg),
       nfields (num_keys_arg),
       fields (static_cast<char **> (mxArray::calloc (nfields,
                                                      sizeof (char *)))),
@@ -1684,8 +2352,9 @@
     init (keys);
   }
 
-  mxArray_struct (const dim_vector& dv, int num_keys_arg, const char **keys)
-    : mxArray_matlab (mxSTRUCT_CLASS, dv), nfields (num_keys_arg),
+  mxArray_struct (bool interleaved, const dim_vector& dv, int num_keys_arg,
+                  const char **keys)
+    : mxArray_matlab (interleaved, mxSTRUCT_CLASS, dv), nfields (num_keys_arg),
       fields (static_cast<char **> (mxArray::calloc (nfields,
                                                      sizeof (char *)))),
       data (static_cast<mxArray **> (mxArray::calloc (nfields *
@@ -1695,8 +2364,10 @@
     init (keys);
   }
 
-  mxArray_struct (mwSize m, mwSize n, int num_keys_arg, const char **keys)
-    : mxArray_matlab (mxSTRUCT_CLASS, m, n), nfields (num_keys_arg),
+  mxArray_struct (bool interleaved, mwSize m, mwSize n, int num_keys_arg,
+                  const char **keys)
+    : mxArray_matlab (interleaved, mxSTRUCT_CLASS, m, n),
+      nfields (num_keys_arg),
       fields (static_cast<char **> (mxArray::calloc (nfields,
                                                      sizeof (char *)))),
       data (static_cast<mxArray **> (mxArray::calloc (nfields *
@@ -1937,18 +2608,18 @@
 {
 public:
 
-  mxArray_cell (mwSize ndims_arg, const mwSize *dims_arg)
-    : mxArray_matlab (mxCELL_CLASS, ndims_arg, dims_arg),
+  mxArray_cell (bool interleaved, mwSize ndims_arg, const mwSize *dims_arg)
+    : mxArray_matlab (interleaved, mxCELL_CLASS, ndims_arg, dims_arg),
       data (static_cast<mxArray **> (mxArray::calloc (get_number_of_elements (),
                                      sizeof (mxArray *)))) { }
 
-  mxArray_cell (const dim_vector& dv)
-    : mxArray_matlab (mxCELL_CLASS, dv),
+  mxArray_cell (bool interleaved, const dim_vector& dv)
+    : mxArray_matlab (interleaved, mxCELL_CLASS, dv),
       data (static_cast<mxArray **> (mxArray::calloc (get_number_of_elements (),
                                      sizeof (mxArray *)))) { }
 
-  mxArray_cell (mwSize m, mwSize n)
-    : mxArray_matlab (mxCELL_CLASS, m, n),
+  mxArray_cell (bool interleaved, mwSize m, mwSize n)
+    : mxArray_matlab (interleaved, mxCELL_CLASS, m, n),
       data (static_cast<mxArray **> (mxArray::calloc (get_number_of_elements (),
                                      sizeof (mxArray *)))) { }
 
@@ -2021,54 +2692,76 @@
 
 // ------------------------------------------------------------------
 
-mxArray::mxArray (const octave_value& ov)
-  : rep (new mxArray_octave_value (ov)), name (nullptr) { }
-
-mxArray::mxArray (mxClassID id, mwSize ndims, const mwSize *dims,
-                  mxComplexity flag, bool init)
-  : rep (new mxArray_number (id, ndims, dims, flag, init)), name (nullptr) { }
-
-mxArray::mxArray (mxClassID id, const dim_vector& dv, mxComplexity flag)
-  : rep (new mxArray_number (id, dv, flag)), name (nullptr) { }
-
-mxArray::mxArray (mxClassID id, mwSize m, mwSize n,
+mxArray::mxArray (bool interleaved, const octave_value& ov)
+  : rep (create_rep (interleaved, ov)), name (nullptr)
+{ }
+
+mxArray::mxArray (bool interleaved, mxClassID id, mwSize ndims,
+                  const mwSize *dims, mxComplexity flag, bool init)
+  : rep (create_rep (interleaved, id, ndims, dims, flag, init)),
+    name (nullptr)
+{ }
+
+mxArray::mxArray (bool interleaved, mxClassID id, const dim_vector& dv,
+                  mxComplexity flag)
+  : rep (create_rep (interleaved, id, dv, flag)), name (nullptr)
+{ }
+
+mxArray::mxArray (bool interleaved, mxClassID id, mwSize m, mwSize n,
                   mxComplexity flag, bool init)
-  : rep (new mxArray_number (id, m, n, flag, init)), name (nullptr) { }
-
-mxArray::mxArray (mxClassID id, double val)
-  : rep (new mxArray_number (id, val)), name (nullptr) { }
-
-mxArray::mxArray (mxClassID id, mxLogical val)
-  : rep (new mxArray_number (id, val)), name (nullptr) { }
-
-mxArray::mxArray (const char *str)
-  : rep (new mxArray_number (str)), name (nullptr) { }
-
-mxArray::mxArray (mwSize m, const char **str)
-  : rep (new mxArray_number (m, str)), name (nullptr) { }
-
-mxArray::mxArray (mxClassID id, mwSize m, mwSize n, mwSize nzmax,
-                  mxComplexity flag)
-  : rep (new mxArray_sparse (id, m, n, nzmax, flag)), name (nullptr) { }
-
-mxArray::mxArray (mwSize ndims, const mwSize *dims, int num_keys,
+  : rep (create_rep (interleaved, id, m, n, flag, init)), name (nullptr)
+{ }
+
+mxArray::mxArray (bool interleaved, mxClassID id, double val)
+  : rep (create_rep (interleaved, id, val)), name (nullptr)
+{ }
+
+mxArray::mxArray (bool interleaved, mxClassID id, mxLogical val)
+  : rep (create_rep (interleaved, id, val)), name (nullptr)
+{ }
+
+mxArray::mxArray (bool interleaved, const char *str)
+  : rep (create_rep (interleaved, str)), name (nullptr)
+{ }
+
+mxArray::mxArray (bool interleaved, mwSize m, const char **str)
+  : rep (create_rep (interleaved, m, str)), name (nullptr)
+{ }
+
+mxArray::mxArray (bool interleaved, mxClassID id, mwSize m, mwSize n,
+                  mwSize nzmax, mxComplexity flag)
+  : rep (create_rep (interleaved, id, m, n, nzmax, flag)), name (nullptr)
+{ }
+
+mxArray::mxArray (bool interleaved, mwSize ndims, const mwSize *dims,
+                  int num_keys,
                   const char **keys)
-  : rep (new mxArray_struct (ndims, dims, num_keys, keys)), name (nullptr) { }
-
-mxArray::mxArray (const dim_vector& dv, int num_keys, const char **keys)
-  : rep (new mxArray_struct (dv, num_keys, keys)), name (nullptr) { }
-
-mxArray::mxArray (mwSize m, mwSize n, int num_keys, const char **keys)
-  : rep (new mxArray_struct (m, n, num_keys, keys)), name (nullptr) { }
-
-mxArray::mxArray (mwSize ndims, const mwSize *dims)
-  : rep (new mxArray_cell (ndims, dims)), name (nullptr) { }
-
-mxArray::mxArray (const dim_vector& dv)
-  : rep (new mxArray_cell (dv)), name (nullptr) { }
-
-mxArray::mxArray (mwSize m, mwSize n)
-  : rep (new mxArray_cell (m, n)), name (nullptr) { }
+  : rep (new mxArray_struct (interleaved, ndims, dims, num_keys, keys)),
+    name (nullptr)
+{ }
+
+mxArray::mxArray (bool interleaved, const dim_vector& dv, int num_keys,
+                  const char **keys)
+  : rep (new mxArray_struct (interleaved, dv, num_keys, keys)), name (nullptr)
+{ }
+
+mxArray::mxArray (bool interleaved, mwSize m, mwSize n, int num_keys,
+                  const char **keys)
+  : rep (new mxArray_struct (interleaved, m, n, num_keys, keys)),
+    name (nullptr)
+{ }
+
+mxArray::mxArray (bool interleaved, mwSize ndims, const mwSize *dims)
+  : rep (new mxArray_cell (interleaved, ndims, dims)), name (nullptr)
+{ }
+
+mxArray::mxArray (bool interleaved, const dim_vector& dv)
+  : rep (new mxArray_cell (interleaved, dv)), name (nullptr)
+{ }
+
+mxArray::mxArray (bool interleaved, mwSize m, mwSize n)
+  : rep (new mxArray_cell (interleaved, m, n)), name (nullptr)
+{ }
 
 mxArray::~mxArray (void)
 {
@@ -2100,6 +2793,64 @@
   return rep->as_octave_value ();
 }
 
+mxArray_base *
+mxArray::create_rep (bool interleaved, const octave_value& ov)
+{
+  return new mxArray_octave_value (interleaved, ov);
+}
+
+mxArray_base *
+mxArray::create_rep (bool interleaved, mxClassID id, mwSize ndims,
+                     const mwSize *dims, mxComplexity flag, bool init)
+{
+  return new mxArray_number (interleaved, id, ndims, dims, flag, init);
+}
+
+mxArray_base *
+mxArray::create_rep (bool interleaved, mxClassID id, const dim_vector& dv,
+                     mxComplexity flag)
+{
+  return new mxArray_number (interleaved, id, dv, flag);
+}
+
+mxArray_base *
+mxArray::create_rep (bool interleaved, mxClassID id, mwSize m, mwSize n,
+                     mxComplexity flag, bool init)
+{
+  return new mxArray_number (interleaved, id, m, n, flag, init);
+}
+
+mxArray_base *
+mxArray::create_rep (bool interleaved, mxClassID id, double val)
+{
+  return new mxArray_number (interleaved, id, val);
+}
+
+mxArray_base *
+mxArray::create_rep (bool interleaved, mxClassID id, mxLogical val)
+{
+  return new mxArray_number (interleaved, id, val);
+}
+
+mxArray_base *
+mxArray::create_rep (bool interleaved, const char *str)
+{
+  return new mxArray_number (interleaved, str);
+}
+
+mxArray_base *
+mxArray::create_rep (bool interleaved, mwSize m, const char **str)
+{
+  return new mxArray_number (interleaved, m, str);
+}
+
+mxArray_base *
+mxArray::create_rep (bool interleaved, mxClassID id, mwSize m, mwSize n,
+                     mwSize nzmax, mxComplexity flag)
+{
+  return new mxArray_sparse (interleaved, id, m, n, nzmax, flag);
+}
+
 void
 mxArray::maybe_mutate (void) const
 {
@@ -2130,7 +2881,7 @@
 {
 public:
 
-  mex (octave_mex_function *f)
+  mex (octave_mex_function& f)
     : curr_mex_fcn (f), memlist (), arraylist (), fname (nullptr) { }
 
   // No copying!
@@ -2363,7 +3114,9 @@
   // freed on exit unless marked as persistent.
   mxArray * make_value (const octave_value& ov)
   {
-    return mark_array (new mxArray (ov));
+    bool interleaved = curr_mex_fcn.use_interleaved_complex ();
+
+    return mark_array (new mxArray (interleaved, ov));
   }
 
   // Free an array and its contents.
@@ -2387,7 +3140,7 @@
     return inlist;
   }
 
-  octave_mex_function * current_mex_function (void) const
+  octave_mex_function& current_mex_function (void) const
   {
     return curr_mex_fcn;
   }
@@ -2398,7 +3151,7 @@
 private:
 
   // Pointer to the mex function that corresponds to this mex context.
-  octave_mex_function *curr_mex_fcn;
+  octave_mex_function& curr_mex_fcn;
 
   // List of memory resources that need to be freed upon exit.
   std::set<void *> memlist;
@@ -2438,7 +3191,6 @@
     else
       warning ("%s: value not marked", function_name ());
 #endif
-
   }
 };
 
@@ -2478,8 +3230,9 @@
   return ptr;
 }
 
-static inline void *
-maybe_unmark (void *ptr)
+template <typename T>
+static inline T *
+maybe_unmark (T *ptr)
 {
   if (mex_context)
     mex_context->unmark (ptr);
@@ -2580,116 +3333,235 @@
 
 // Constructors.
 mxArray *
+mxCreateCellArray_interleaved (mwSize ndims, const mwSize *dims)
+{
+  return maybe_mark_array (new mxArray (true, ndims, dims));
+}
+
+mxArray *
 mxCreateCellArray (mwSize ndims, const mwSize *dims)
 {
-  return maybe_mark_array (new mxArray (ndims, dims));
+  return maybe_mark_array (new mxArray (false, ndims, dims));
+}
+
+mxArray *
+mxCreateCellMatrix_interleaved (mwSize m, mwSize n)
+{
+  return maybe_mark_array (new mxArray (true, m, n));
 }
 
 mxArray *
 mxCreateCellMatrix (mwSize m, mwSize n)
 {
-  return maybe_mark_array (new mxArray (m, n));
+  return maybe_mark_array (new mxArray (false, m, n));
+}
+
+mxArray *
+mxCreateCharArray_interleaved (mwSize ndims, const mwSize *dims)
+{
+  return maybe_mark_array (new mxArray (true, mxCHAR_CLASS, ndims, dims));
 }
 
 mxArray *
 mxCreateCharArray (mwSize ndims, const mwSize *dims)
 {
-  return maybe_mark_array (new mxArray (mxCHAR_CLASS, ndims, dims));
+  return maybe_mark_array (new mxArray (false, mxCHAR_CLASS, ndims, dims));
+}
+
+mxArray *
+mxCreateCharMatrixFromStrings_interleaved (mwSize m, const char **str)
+{
+  return maybe_mark_array (new mxArray (true, m, str));
 }
 
 mxArray *
 mxCreateCharMatrixFromStrings (mwSize m, const char **str)
 {
-  return maybe_mark_array (new mxArray (m, str));
+  return maybe_mark_array (new mxArray (false, m, str));
+}
+
+mxArray *
+mxCreateDoubleMatrix_interleaved (mwSize m, mwSize n, mxComplexity flag)
+{
+  return maybe_mark_array (new mxArray (true, mxDOUBLE_CLASS, m, n, flag));
 }
 
 mxArray *
 mxCreateDoubleMatrix (mwSize m, mwSize n, mxComplexity flag)
 {
-  return maybe_mark_array (new mxArray (mxDOUBLE_CLASS, m, n, flag));
+  return maybe_mark_array (new mxArray (false, mxDOUBLE_CLASS, m, n, flag));
+}
+
+mxArray *
+mxCreateDoubleScalar_interleaved (double val)
+{
+  return maybe_mark_array (new mxArray (true, mxDOUBLE_CLASS, val));
 }
 
 mxArray *
 mxCreateDoubleScalar (double val)
 {
-  return maybe_mark_array (new mxArray (mxDOUBLE_CLASS, val));
+  return maybe_mark_array (new mxArray (false, mxDOUBLE_CLASS, val));
+}
+
+mxArray *
+mxCreateLogicalArray_interleaved (mwSize ndims, const mwSize *dims)
+{
+  return maybe_mark_array (new mxArray (true, mxLOGICAL_CLASS, ndims, dims));
 }
 
 mxArray *
 mxCreateLogicalArray (mwSize ndims, const mwSize *dims)
 {
-  return maybe_mark_array (new mxArray (mxLOGICAL_CLASS, ndims, dims));
+  return maybe_mark_array (new mxArray (false, mxLOGICAL_CLASS, ndims, dims));
+}
+
+mxArray *
+mxCreateLogicalMatrix_interleaved (mwSize m, mwSize n)
+{
+  return maybe_mark_array (new mxArray (true, mxLOGICAL_CLASS, m, n));
 }
 
 mxArray *
 mxCreateLogicalMatrix (mwSize m, mwSize n)
 {
-  return maybe_mark_array (new mxArray (mxLOGICAL_CLASS, m, n));
+  return maybe_mark_array (new mxArray (false, mxLOGICAL_CLASS, m, n));
+}
+
+mxArray *
+mxCreateLogicalScalar_interleaved (mxLogical val)
+{
+  return maybe_mark_array (new mxArray (true, mxLOGICAL_CLASS, val));
 }
 
 mxArray *
 mxCreateLogicalScalar (mxLogical val)
 {
-  return maybe_mark_array (new mxArray (mxLOGICAL_CLASS, val));
+  return maybe_mark_array (new mxArray (false, mxLOGICAL_CLASS, val));
+}
+
+mxArray *
+mxCreateNumericArray_interleaved (mwSize ndims, const mwSize *dims,
+                                  mxClassID class_id, mxComplexity flag)
+{
+  return maybe_mark_array (new mxArray (true, class_id, ndims, dims, flag));
 }
 
 mxArray *
-mxCreateNumericArray (mwSize ndims, const mwSize *dims, mxClassID class_id,
-                      mxComplexity flag)
-{
-  return maybe_mark_array (new mxArray (class_id, ndims, dims, flag));
+mxCreateNumericArray (mwSize ndims, const mwSize *dims,
+                               mxClassID class_id, mxComplexity flag)
+{
+  return maybe_mark_array (new mxArray (false, class_id, ndims, dims, flag));
+}
+
+mxArray *
+mxCreateNumericMatrix_interleaved (mwSize m, mwSize n, mxClassID class_id,
+                                   mxComplexity flag)
+{
+  return maybe_mark_array (new mxArray (true, class_id, m, n, flag));
 }
 
 mxArray *
 mxCreateNumericMatrix (mwSize m, mwSize n, mxClassID class_id,
-                       mxComplexity flag)
-{
-  return maybe_mark_array (new mxArray (class_id, m, n, flag));
+                                mxComplexity flag)
+{
+  return maybe_mark_array (new mxArray (false, class_id, m, n, flag));
+}
+
+mxArray *
+mxCreateUninitNumericArray_interleaved (mwSize ndims, const mwSize *dims,
+                                        mxClassID class_id, mxComplexity flag)
+{
+  return maybe_mark_array (new mxArray (true, class_id, ndims, dims, flag,
+                                        false));
 }
 
 mxArray *
 mxCreateUninitNumericArray (mwSize ndims, const mwSize *dims,
-                            mxClassID class_id, mxComplexity flag)
-{
-  return maybe_mark_array (new mxArray (class_id, ndims, dims, flag, false));
+                                     mxClassID class_id, mxComplexity flag)
+{
+  return maybe_mark_array (new mxArray (false, class_id, ndims, dims, flag,
+                                        false));
+}
+
+mxArray *
+mxCreateUninitNumericMatrix_interleaved (mwSize m, mwSize n,
+                                         mxClassID class_id, mxComplexity flag)
+{
+  return maybe_mark_array (new mxArray (true, class_id, m, n, flag, false));
 }
 
 mxArray *
 mxCreateUninitNumericMatrix (mwSize m, mwSize n, mxClassID class_id,
-                             mxComplexity flag)
-{
-  return maybe_mark_array (new mxArray (class_id, m, n, flag, false));
+                                      mxComplexity flag)
+{
+  return maybe_mark_array (new mxArray (false, class_id, m, n, flag, false));
+}
+
+mxArray *
+mxCreateSparse_interleaved (mwSize m, mwSize n, mwSize nzmax, mxComplexity flag)
+{
+  return maybe_mark_array (new mxArray (true, mxDOUBLE_CLASS, m, n, nzmax,
+                                        flag));
 }
 
 mxArray *
 mxCreateSparse (mwSize m, mwSize n, mwSize nzmax, mxComplexity flag)
 {
-  return maybe_mark_array (new mxArray (mxDOUBLE_CLASS, m, n, nzmax, flag));
+  return maybe_mark_array (new mxArray (false, mxDOUBLE_CLASS, m, n, nzmax,
+                                        flag));
+}
+
+mxArray *
+mxCreateSparseLogicalMatrix_interleaved (mwSize m, mwSize n, mwSize nzmax)
+{
+  return maybe_mark_array (new mxArray (true, mxLOGICAL_CLASS, m, n, nzmax));
 }
 
 mxArray *
 mxCreateSparseLogicalMatrix (mwSize m, mwSize n, mwSize nzmax)
 {
-  return maybe_mark_array (new mxArray (mxLOGICAL_CLASS, m, n, nzmax));
+  return maybe_mark_array (new mxArray (false, mxLOGICAL_CLASS, m, n, nzmax));
+}
+
+mxArray *
+mxCreateString_interleaved (const char *str)
+{
+  return maybe_mark_array (new mxArray (true, str));
 }
 
 mxArray *
 mxCreateString (const char *str)
 {
-  return maybe_mark_array (new mxArray (str));
+  return maybe_mark_array (new mxArray (false, str));
+}
+
+mxArray *
+mxCreateStructArray_interleaved (mwSize ndims, const mwSize *dims,
+                                 int num_keys, const char **keys)
+{
+  return maybe_mark_array (new mxArray (true, ndims, dims, num_keys, keys));
 }
 
 mxArray *
 mxCreateStructArray (mwSize ndims, const mwSize *dims, int num_keys,
-                     const char **keys)
-{
-  return maybe_mark_array (new mxArray (ndims, dims, num_keys, keys));
+                              const char **keys)
+{
+  return maybe_mark_array (new mxArray (false, ndims, dims, num_keys, keys));
 }
 
 mxArray *
-mxCreateStructMatrix (mwSize m, mwSize n, int num_keys, const char **keys)
-{
-  return maybe_mark_array (new mxArray (m, n, num_keys, keys));
+mxCreateStructMatrix_interleaved (mwSize m, mwSize n, int num_keys,
+                                  const char **keys)
+{
+  return maybe_mark_array (new mxArray (true, m, n, num_keys, keys));
+}
+
+mxArray *
+mxCreateStructMatrix (mwSize m, mwSize n, int num_keys,
+                               const char **keys)
+{
+  return maybe_mark_array (new mxArray (false, m, n, num_keys, keys));
 }
 
 // Copy constructor.
@@ -2918,12 +3790,6 @@
   return static_cast<double *> (ptr->get_data ());
 }
 
-double *
-mxGetPi (const mxArray *ptr)
-{
-  return static_cast<double *> (ptr->get_imag_data ());
-}
-
 double
 mxGetScalar (const mxArray *ptr)
 {
@@ -2951,12 +3817,121 @@
   return ptr->get_data ();
 }
 
+double *
+mxGetPi (const mxArray *ptr)
+{
+  return static_cast<double *> (ptr->get_imag_data ());
+}
+
 void *
 mxGetImagData (const mxArray *ptr)
 {
   return ptr->get_imag_data ();
 }
 
+mxDouble * mxGetDoubles (const mxArray *ptr)
+{
+  return ptr->get_doubles ();
+}
+
+mxSingle * mxGetSingles (const mxArray *ptr)
+{
+  return ptr->get_singles ();
+}
+
+mxInt8 * mxGetInt8s (const mxArray *ptr)
+{
+  return ptr->get_int8s ();
+}
+
+mxInt16 * mxGetInt16s (const mxArray *ptr)
+{
+  return ptr->get_int16s ();
+}
+
+mxInt32 * mxGetInt32s (const mxArray *ptr)
+{
+  return ptr->get_int32s ();
+}
+
+mxInt64 * mxGetInt64s (const mxArray *ptr)
+{
+  return ptr->get_int64s ();
+}
+
+mxUint8 * mxGetUint8s (const mxArray *ptr)
+{
+  return ptr->get_uint8s ();
+}
+
+mxUint16 * mxGetUint16s (const mxArray *ptr)
+{
+  return ptr->get_uint16s ();
+}
+
+mxUint32 * mxGetUint32s (const mxArray *ptr)
+{
+  return ptr->get_uint32s ();
+}
+
+mxUint64 * mxGetUint64s (const mxArray *ptr)
+{
+  return ptr->get_uint64s ();
+}
+
+mxComplexDouble * mxGetComplexDoubles (const mxArray *ptr)
+{
+  return ptr->get_complex_doubles ();
+}
+
+mxComplexSingle * mxGetComplexSingles (const mxArray *ptr)
+{
+  return ptr->get_complex_singles ();
+}
+
+#if 0
+/* We don't have these yet. */
+mxComplexInt8 * mxGetComplexInt8s (const mxArray *ptr)
+{
+  return ptr->get_complex_int8s ();
+}
+
+mxComplexInt16 * mxGetComplexInt16s (const mxArray *ptr)
+{
+  return ptr->get_complex_int16s ();
+}
+
+mxComplexInt32 * mxGetComplexInt32s (const mxArray *ptr)
+{
+  return ptr->get_complex_int32s ();
+}
+
+mxComplexInt64 * mxGetComplexInt64s (const mxArray *ptr)
+{
+  return ptr->get_complex_int64s ();
+}
+
+mxComplexUint8 * mxGetComplexUint8s (const mxArray *ptr)
+{
+  return ptr->get_complex_uint8s ();
+}
+
+mxComplexUint16 * mxGetComplexUint16s (const mxArray *ptr)
+{
+  return ptr->get_complex_uint16s ();
+}
+
+mxComplexUint32 * mxGetComplexUint32s (const mxArray *ptr)
+{
+  return ptr->get_complex_uint32s ();
+}
+
+mxComplexUint64 * mxGetComplexUint64s (const mxArray *ptr)
+{
+  return ptr->get_complex_uint64s ();
+}
+#endif
+
 // Data setters.
 void
 mxSetPr (mxArray *ptr, double *pr)
@@ -2965,18 +3940,121 @@
 }
 
 void
+mxSetData (mxArray *ptr, void *pr)
+{
+  ptr->set_data (maybe_unmark (pr));
+}
+
+int mxSetDoubles (mxArray *ptr, mxDouble *data)
+{
+  return ptr->set_doubles (maybe_unmark (data));
+}
+
+int mxSetSingles (mxArray *ptr, mxSingle *data)
+{
+  return ptr->set_singles (maybe_unmark (data));
+}
+
+int mxSetInt8s (mxArray *ptr, mxInt8 *data)
+{
+  return ptr->set_int8s (maybe_unmark (data));
+}
+
+int mxSetInt16s (mxArray *ptr, mxInt16 *data)
+{
+  return ptr->set_int16s (maybe_unmark (data));
+}
+
+int mxSetInt32s (mxArray *ptr, mxInt32 *data)
+{
+  return ptr->set_int32s (maybe_unmark (data));
+}
+
+int mxSetInt64s (mxArray *ptr, mxInt64 *data)
+{
+  return ptr->set_int64s (maybe_unmark (data));
+}
+
+int mxSetUint8s (mxArray *ptr, mxUint8 *data)
+{
+  return ptr->set_uint8s (maybe_unmark (data));
+}
+
+int mxSetUint16s (mxArray *ptr, mxUint16 *data)
+{
+  return ptr->set_uint16s (maybe_unmark (data));
+}
+
+int mxSetUint32s (mxArray *ptr, mxUint32 *data)
+{
+  return ptr->set_uint32s (maybe_unmark (data));
+}
+
+int mxSetUint64s (mxArray *ptr, mxUint64 *data)
+{
+  return ptr->set_uint64s (maybe_unmark (data));
+}
+
+int mxSetComplexDoubles (mxArray *ptr, mxComplexDouble *data)
+{
+  return ptr->set_complex_doubles (maybe_unmark (data));
+}
+
+int mxSetComplexSingles (mxArray *ptr, mxComplexSingle *data)
+{
+  return ptr->set_complex_singles (maybe_unmark (data));
+}
+
+#if 0
+/* We don't have these yet. */
+int mxSetComplexInt8s (mxArray *ptr, mxComplexInt8 *data)
+{
+  return ptr->set_complex_int8s (maybe_unmark (data));
+}
+
+int mxSetComplexInt16s (mxArray *ptr, mxComplexInt16 *data)
+{
+  return ptr->set_complex_int16s (maybe_unmark (data));
+}
+
+int mxSetComplexInt32s (mxArray *ptr, mxComplexInt32 *data)
+{
+  return ptr->set_complex_int32s (maybe_unmark (data));
+}
+
+int mxSetComplexInt64s (mxArray *ptr, mxComplexInt64 *data)
+{
+  return ptr->set_complex_int64s (maybe_unmark (data));
+}
+
+int mxSetComplexUint8s (mxArray *ptr, mxComplexUint8 *data)
+{
+  return ptr->set_complex_uint8s (maybe_unmark (data));
+}
+
+int mxSetComplexUint16s (mxArray *ptr, mxComplexUint16 *data)
+{
+  return ptr->set_complex_uint16s (maybe_unmark (data));
+}
+
+int mxSetComplexUint32s (mxArray *ptr, mxComplexUint32 *data)
+{
+  return ptr->set_complex_uint32s (maybe_unmark (data));
+}
+
+int mxSetComplexUint64s (mxArray *ptr, mxComplexUint64 *data)
+{
+  return ptr->set_complex_uint64s (maybe_unmark (data));
+}
+#endif
+
+void
 mxSetPi (mxArray *ptr, double *pi)
 {
   ptr->set_imag_data (maybe_unmark (pi));
 }
 
 void
-mxSetData (mxArray *ptr, void *pr)
-{
-  ptr->set_data (maybe_unmark (pr));
-}
-
-void
 mxSetImagData (mxArray *ptr, void *pi)
 {
   ptr->set_imag_data (maybe_unmark (pi));
@@ -3177,7 +4255,7 @@
   // Save old mex pointer.
   frame.protect_var (mex_context);
 
-  mex context (&mex_fcn);
+  mex context (mex_fcn);
 
   for (int i = 0; i < nargin; i++)
     argin[i] = context.make_value (args(i));
@@ -3619,17 +4697,28 @@
 {
   if (mex_context)
     {
-      octave_mex_function *curr_mex_fcn = mex_context->current_mex_function ();
-
-      assert (curr_mex_fcn);
-
-      curr_mex_fcn->atexit (f);
+      octave_mex_function& curr_mex_fcn = mex_context->current_mex_function ();
+
+      curr_mex_fcn.atexit (f);
     }
 
   return 0;
 }
 
 const mxArray *
+mexGet_interleaved (double handle, const char *property)
+{
+  mxArray *m = nullptr;
+
+  octave_value ret = get_property_from_handle (handle, property, "mexGet");
+
+  if (ret.is_defined ())
+    m = ret.as_mxArray (true);
+
+  return m;
+}
+
+const mxArray *
 mexGet (double handle, const char *property)
 {
   mxArray *m = nullptr;
@@ -3637,7 +4726,7 @@
   octave_value ret = get_property_from_handle (handle, property, "mexGet");
 
   if (ret.is_defined ())
-    m = ret.as_mxArray ();
+    m = ret.as_mxArray (false);
 
   return m;
 }
--- a/libinterp/corefcn/mexproto.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/corefcn/mexproto.h	Tue Jul 07 19:40:20 2020 -0400
@@ -61,10 +61,19 @@
 #  include <stdbool.h>
 #endif
 
+#if ! defined (MX_HAS_INTERLEAVED_COMPLEX)
+#  define MX_HAS_INTERLEAVED_COMPLEX 0
+#endif
+
 #define MXARRAY_TYPEDEFS_ONLY
 #include "mxarray.h"
 #undef MXARRAY_TYPEDEFS_ONLY
 
+/* Prototype for the gateway function.  */
+
+extern void mexFunction (int nlhs, mxArray *plhs[],
+                         int nrhs, const mxArray *prhs[]);
+
 /* Interface to the interpreter.  */
 extern OCTINTERP_API const char * mexFunctionName (void);
 
@@ -98,8 +107,12 @@
 extern OCTINTERP_API int mexPutVariable (const char *space, const char *name,
                                          const mxArray *ptr);
 
+#if MX_HAS_INTERLEAVED_COMPLEX
+#  define mexGet mexGet_interleaved
+#endif
 extern OCTINTERP_API const mxArray * mexGet (double handle,
                                              const char *property);
+
 extern OCTINTERP_API int mexSet (double handle, const char *property,
                                  mxArray *val);
 
@@ -131,6 +144,27 @@
 extern OCTINTERP_API void mxFree (void *ptr);
 
 /* Constructors.  */
+#if MX_HAS_INTERLEAVED_COMPLEX
+#  define mxCreateCellArray mxCreateCellArray_interleaved
+#  define mxCreateCellMatrix mxCreateCellMatrix_interleaved
+#  define mxCreateCharArray mxCreateCharArray_interleaved
+#  define mxCreateCharMatrixFromStrings mxCreateCharMatrixFromStrings_interleaved
+#  define mxCreateDoubleMatrix mxCreateDoubleMatrix_interleaved
+#  define mxCreateDoubleScalar mxCreateDoubleScalar_interleaved
+#  define mxCreateLogicalArray mxCreateLogicalArray_interleaved
+#  define mxCreateLogicalMatrix mxCreateLogicalMatrix_interleaved
+#  define mxCreateLogicalScalar mxCreateLogicalScalar_interleaved
+#  define mxCreateNumericArray mxCreateNumericArray_interleaved
+#  define mxCreateNumericMatrix mxCreateNumericMatrix_interleaved
+#  define mxCreateUninitNumericArray mxCreateUninitNumericArray_interleaved
+#  define mxCreateUninitNumericMatrix mxCreateUninitNumericMatrix_interleaved
+#  define mxCreateSparse mxCreateSparse_interleaved
+#  define mxCreateSparseLogicalMatrix mxCreateSparseLogicalMatrix_interleaved
+#  define mxCreateString mxCreateString_interleaved
+#  define mxCreateStructArray mxCreateStructArray_interleaved
+#  define mxCreateStructMatrix mxCreateStructMatrix_interleaved
+#endif
+
 extern OCTINTERP_API mxArray * mxCreateCellArray (mwSize ndims,
                                                   const mwSize *dims);
 extern OCTINTERP_API mxArray * mxCreateCellMatrix (mwSize m, mwSize n);
@@ -227,20 +261,79 @@
 extern OCTINTERP_API int mxSetDimensions (mxArray *ptr, const mwSize *dims,
                                           mwSize ndims);
 
+#if MX_HAS_INTERLEAVED_COMPLEX
+extern OCTINTERP_API int mxMakeArrayReal (mxArray *ptr);
+extern OCTINTERP_API int mxMakeArrayComplex (mxArray *ptr);
+#endif
+
 /* Data extractors.  */
-extern OCTINTERP_API double * mxGetPi (const mxArray *ptr);
 extern OCTINTERP_API double * mxGetPr (const mxArray *ptr);
 extern OCTINTERP_API double mxGetScalar (const mxArray *ptr);
 extern OCTINTERP_API mxChar * mxGetChars (const mxArray *ptr);
 extern OCTINTERP_API mxLogical * mxGetLogicals (const mxArray *ptr);
 extern OCTINTERP_API void * mxGetData (const mxArray *ptr);
+#if MX_HAS_INTERLEAVED_COMPLEX
+extern OCTINTERP_API mxDouble * mxGetDoubles (const mxArray *p);
+extern OCTINTERP_API mxSingle * mxGetSingles (const mxArray *p);
+extern OCTINTERP_API mxInt8 * mxGetInt8s (const mxArray *p);
+extern OCTINTERP_API mxInt16 * mxGetInt16s (const mxArray *p);
+extern OCTINTERP_API mxInt32 * mxGetInt32s (const mxArray *p);
+extern OCTINTERP_API mxInt64 * mxGetInt64s (const mxArray *p);
+extern OCTINTERP_API mxUint8 * mxGetUint8s (const mxArray *p);
+extern OCTINTERP_API mxUint16 * mxGetUint16s (const mxArray *p);
+extern OCTINTERP_API mxUint32 * mxGetUint32s (const mxArray *p);
+extern OCTINTERP_API mxUint64 * mxGetUint64s (const mxArray *p);
+
+extern OCTINTERP_API mxComplexDouble * mxGetComplexDoubles (const mxArray *p);
+extern OCTINTERP_API mxComplexSingle * mxGetComplexSingles (const mxArray *p);
+#if 0
+/* We don't have these yet. */
+extern OCTINTERP_API mxComplexInt8 * mxGetComplexInt8s (const mxArray *p);
+extern OCTINTERP_API mxComplexInt16 * mxGetComplexInt16s (const mxArray *p);
+extern OCTINTERP_API mxComplexInt32 * mxGetComplexInt32s (const mxArray *p);
+extern OCTINTERP_API mxComplexInt64 * mxGetComplexInt64s (const mxArray *p);
+extern OCTINTERP_API mxComplexUint8 * mxGetComplexUint8s (const mxArray *p);
+extern OCTINTERP_API mxComplexUint16 * mxGetComplexUint16s (const mxArray *p);
+extern OCTINTERP_API mxComplexUint32 * mxGetComplexUint32s (const mxArray *p);
+extern OCTINTERP_API mxComplexUint64 * mxGetComplexUint64s (const mxArray *p);
+#endif
+#else
+extern OCTINTERP_API double * mxGetPi (const mxArray *ptr);
 extern OCTINTERP_API void * mxGetImagData (const mxArray *ptr);
+#endif
 
 /* Data setters.  */
 extern OCTINTERP_API void mxSetPr (mxArray *ptr, double *pr);
+extern OCTINTERP_API void mxSetData (mxArray *ptr, void *data);
+#if MX_HAS_INTERLEAVED_COMPLEX
+extern OCTINTERP_API int mxSetDoubles (mxArray *p, mxDouble *d);
+extern OCTINTERP_API int mxSetSingles (mxArray *p, mxSingle *d);
+extern OCTINTERP_API int mxSetInt8s (mxArray *p, mxInt8 *d);
+extern OCTINTERP_API int mxSetInt16s (mxArray *p, mxInt16 *d);
+extern OCTINTERP_API int mxSetInt32s (mxArray *p, mxInt32 *d);
+extern OCTINTERP_API int mxSetInt64s (mxArray *p, mxInt64 *d);
+extern OCTINTERP_API int mxSetUint8s (mxArray *p, mxUint8 *d);
+extern OCTINTERP_API int mxSetUint16s (mxArray *p, mxUint16 *d);
+extern OCTINTERP_API int mxSetUint32s (mxArray *p, mxUint32 *d);
+extern OCTINTERP_API int mxSetUint64s (mxArray *p, mxUint64 *d);
+
+extern OCTINTERP_API int mxSetComplexDoubles (mxArray *p, mxComplexDouble *d);
+extern OCTINTERP_API int mxSetComplexSingles (mxArray *p, mxComplexSingle *d);
+#if 0
+/* We don't have these yet. */
+extern OCTINTERP_API int mxSetComplexInt8s (mxArray *p, mxComplexInt8 *d);
+extern OCTINTERP_API int mxSetComplexInt16s (mxArray *p, mxComplexInt16 *d);
+extern OCTINTERP_API int mxSetComplexInt32s (mxArray *p, mxComplexInt32 *d);
+extern OCTINTERP_API int mxSetComplexInt64s (mxArray *p, mxComplexInt64 *d);
+extern OCTINTERP_API int mxSetComplexUint8s (mxArray *p, mxComplexUint8 *d);
+extern OCTINTERP_API int mxSetComplexUint16s (mxArray *p, mxComplexUint16 *d);
+extern OCTINTERP_API int mxSetComplexUint32s (mxArray *p, mxComplexUint32 *d);
+extern OCTINTERP_API int mxSetComplexUint64s (mxArray *p, mxComplexUint64 *d);
+#endif
+#else
 extern OCTINTERP_API void mxSetPi (mxArray *ptr, double *pi);
-extern OCTINTERP_API void mxSetData (mxArray *ptr, void *data);
 extern OCTINTERP_API void mxSetImagData (mxArray *ptr, void *pi);
+#endif
 
 /* Classes.  */
 extern OCTINTERP_API mxClassID mxGetClassID (const mxArray *ptr);
--- a/libinterp/corefcn/mk-mxarray-h.in.sh	Tue Jul 07 18:34:23 2020 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-#! /bin/sh
-#
-########################################################################
-#
-# Copyright (C) 2016-2020 The Octave Project Developers
-#
-# See the file COPYRIGHT.md in the top-level directory of this
-# distribution or <https://octave.org/copyright/>.
-#
-# This file is part of Octave.
-#
-# Octave is free software: you can 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
-# <https://www.gnu.org/licenses/>.
-#
-########################################################################
-
-: ${SED=@SED@}
-
-OCTAVE_IDX_TYPE="@OCTAVE_IDX_TYPE@"
-
-$SED \
-  -e "s|%NO_EDIT_WARNING%|DO NOT EDIT!  Generated automatically by mx-mxarray-h.|" \
-  -e "s|%OCTAVE_IDX_TYPE%|${OCTAVE_IDX_TYPE}|"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/corefcn/mk-mxtypes-h.in.sh	Tue Jul 07 19:40:20 2020 -0400
@@ -0,0 +1,34 @@
+#! /bin/sh
+#
+########################################################################
+#
+# Copyright (C) 2016-2020 The Octave Project Developers
+#
+# See the file COPYRIGHT.md in the top-level directory of this
+# distribution or <https://octave.org/copyright/>.
+#
+# This file is part of Octave.
+#
+# Octave is free software: you can 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
+# <https://www.gnu.org/licenses/>.
+#
+########################################################################
+
+: ${SED=@SED@}
+
+OCTAVE_IDX_TYPE="@OCTAVE_IDX_TYPE@"
+
+$SED \
+  -e "s|%NO_EDIT_WARNING%|DO NOT EDIT!  Generated automatically by mx-mxtypes-h.sh|" \
+  -e "s|%OCTAVE_IDX_TYPE%|${OCTAVE_IDX_TYPE}|"
--- a/libinterp/corefcn/module.mk	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/corefcn/module.mk	Tue Jul 07 19:40:20 2020 -0400
@@ -58,6 +58,7 @@
   %reldir%/ls-utils.h \
   %reldir%/mex.h \
   %reldir%/mexproto.h \
+  %reldir%/mxarray.h \
   %reldir%/oct-errno.h \
   %reldir%/oct-fstrm.h \
   %reldir%/oct-handle.h \
@@ -89,7 +90,6 @@
   %reldir%/sysdep.h \
   %reldir%/text-engine.h \
   %reldir%/text-renderer.h \
-  %reldir%/txt-eng.h \
   %reldir%/url-handle-manager.h \
   %reldir%/utils.h \
   %reldir%/variables.h \
@@ -298,8 +298,8 @@
 	fi && \
 	mv $@-t $@
 
-%reldir%/mxarray.h: %reldir%/mxarray.in.h %reldir%/mk-mxarray-h.sh | %reldir%/$(octave_dirstamp)
-	$(AM_V_GEN)$(call simple-filter-rule,%reldir%/mk-mxarray-h.sh)
+%reldir%/mxtypes.h: %reldir%/mxtypes.in.h %reldir%/mk-mxtypes-h.sh | %reldir%/$(octave_dirstamp)
+	$(AM_V_GEN)$(call simple-filter-rule,%reldir%/mk-mxtypes-h.sh)
 
 %reldir%/oct-tex-lexer.ll: %reldir%/oct-tex-lexer.in.ll %reldir%/oct-tex-symbols.in | %reldir%/$(octave_dirstamp)
 	$(AM_V_GEN)rm -f $@-t && \
@@ -332,11 +332,11 @@
   %reldir%/genprops.awk \
   %reldir%/graphics.in.h \
   %reldir%/mk-errno-list.sh \
-  %reldir%/mk-mxarray-h.in.sh \
-  %reldir%/mxarray.in.h \
+  %reldir%/mk-mxtypes-h.in.sh \
+  %reldir%/mxtypes.in.h \
   %reldir%/oct-errno.in.cc \
   %reldir%/oct-tex-lexer.in.ll \
   %reldir%/oct-tex-symbols.in
 
 GEN_CONFIG_SHELL += \
-  %reldir%/mk-mxarray-h.sh
+  %reldir%/mk-mxtypes-h.sh
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/corefcn/mxarray.h	Tue Jul 07 19:40:20 2020 -0400
@@ -0,0 +1,746 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2001-2020 The Octave Project Developers
+//
+// See the file COPYRIGHT.md in the top-level directory of this
+// distribution or <https://octave.org/copyright/>.
+//
+// This file is part of Octave.
+//
+// Octave is free software: you can 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
+// <https://www.gnu.org/licenses/>.
+//
+////////////////////////////////////////////////////////////////////////
+
+/*
+
+Part of this code was originally distributed as part of Octave Forge under
+the following terms:
+
+Author: Paul Kienzle
+I grant this code to the public domain.
+2001-03-22
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+*/
+
+#if ! defined (octave_mxarray_h)
+#define octave_mxarray_h 1
+
+#include "octave-config.h"
+
+#include "mxtypes.h"
+
+#if ! defined (MXARRAY_TYPEDEFS_ONLY)
+
+#include <cstring>
+#include "error.h"
+
+class octave_value;
+class dim_vector;
+
+#define DO_MUTABLE_METHOD(RET_T, METHOD_CALL)   \
+  RET_T retval = rep->METHOD_CALL;              \
+                                                \
+  if (rep->mutation_needed ())                  \
+    {                                           \
+      maybe_mutate ();                          \
+      retval = rep->METHOD_CALL;                \
+    }                                           \
+                                                \
+  return retval
+
+#define DO_VOID_MUTABLE_METHOD(METHOD_CALL)     \
+  rep->METHOD_CALL;                             \
+                                                \
+  if (rep->mutation_needed ())                  \
+    {                                           \
+      maybe_mutate ();                          \
+      rep->METHOD_CALL;                         \
+    }
+
+class mxArray;
+
+// A class to provide the default implementation of some of the
+// virtual functions declared in the mxArray class.
+
+class mxArray_base
+{
+protected:
+
+  mxArray_base (bool interleaved);
+
+public:
+
+  virtual mxArray_base * dup (void) const = 0;
+
+  virtual mxArray * as_mxArray (void) const { return nullptr; }
+
+  virtual ~mxArray_base (void) = default;
+
+  virtual bool is_octave_value (void) const { return false; }
+
+  virtual int iscell (void) const = 0;
+
+  virtual int is_char (void) const = 0;
+
+  virtual int is_class (const char *name_arg) const
+  {
+    int retval = 0;
+
+    const char *cname = get_class_name ();
+
+    if (cname && name_arg)
+      retval = ! strcmp (cname, name_arg);
+
+    return retval;
+  }
+
+  virtual int is_complex (void) const = 0;
+
+  virtual int is_double (void) const = 0;
+
+  virtual int is_function_handle (void) const = 0;
+
+  virtual int is_int16 (void) const = 0;
+
+  virtual int is_int32 (void) const = 0;
+
+  virtual int is_int64 (void) const = 0;
+
+  virtual int is_int8 (void) const = 0;
+
+  virtual int is_logical (void) const = 0;
+
+  virtual int is_numeric (void) const = 0;
+
+  virtual int is_single (void) const = 0;
+
+  virtual int is_sparse (void) const = 0;
+
+  virtual int is_struct (void) const = 0;
+
+  virtual int is_uint16 (void) const = 0;
+
+  virtual int is_uint32 (void) const = 0;
+
+  virtual int is_uint64 (void) const = 0;
+
+  virtual int is_uint8 (void) const = 0;
+
+  virtual int is_logical_scalar (void) const
+  {
+    return is_logical () && get_number_of_elements () == 1;
+  }
+
+  virtual int is_logical_scalar_true (void) const = 0;
+
+  virtual mwSize get_m (void) const = 0;
+
+  virtual mwSize get_n (void) const = 0;
+
+  virtual mwSize * get_dimensions (void) const = 0;
+
+  virtual mwSize get_number_of_dimensions (void) const = 0;
+
+  virtual void set_m (mwSize m) = 0;
+
+  virtual void set_n (mwSize n) = 0;
+
+  virtual int set_dimensions (mwSize *dims_arg, mwSize ndims_arg) = 0;
+
+  virtual mwSize get_number_of_elements (void) const = 0;
+
+  virtual int isempty (void) const = 0;
+
+  virtual bool is_scalar (void) const = 0;
+
+  virtual mxClassID get_class_id (void) const = 0;
+
+  virtual const char * get_class_name (void) const = 0;
+
+  virtual void set_class_name (const char *name_arg) = 0;
+
+  // The following functions aren't pure virtual because they are only
+  // valid for one type.  Making them pure virtual would mean that they
+  // have to be implemented for all derived types, and all of those
+  // would need to throw errors instead of just doing it once here.
+
+  virtual mxArray *
+  get_property (mwIndex /*idx*/, const char * /*pname*/) const
+  {
+    return nullptr;
+  }
+
+  virtual void set_property (mwIndex /*idx*/, const char * /*pname*/,
+                             const mxArray * /*pval*/)
+  {
+    err_invalid_type ("set_property");
+  }
+
+  virtual mxArray * get_cell (mwIndex /*idx*/) const
+  {
+    err_invalid_type ("get_cell");
+  }
+
+  virtual void set_cell (mwIndex idx, mxArray *val) = 0;
+
+  virtual double get_scalar (void) const = 0;
+
+  virtual void * get_data (void) const = 0;
+
+  virtual mxDouble * get_doubles (void) const = 0;
+  virtual mxSingle * get_singles (void) const = 0;
+  virtual mxInt8 * get_int8s (void) const = 0;
+  virtual mxInt16 * get_int16s (void) const = 0;
+  virtual mxInt32 * get_int32s (void) const = 0;
+  virtual mxInt64 * get_int64s (void) const = 0;
+  virtual mxUint8 * get_uint8s (void) const = 0;
+  virtual mxUint16 * get_uint16s (void) const = 0;
+  virtual mxUint32 * get_uint32s (void) const = 0;
+  virtual mxUint64 * get_uint64s (void) const = 0;
+
+  virtual mxComplexDouble * get_complex_doubles (void) const = 0;
+  virtual mxComplexSingle * get_complex_singles (void) const = 0;
+#if 0
+  /* We don't have these yet. */
+  virtual mxComplexInt8 * get_complex_int8s (void) const = 0;
+  virtual mxComplexInt16 * get_complex_int16s (void) const = 0;
+  virtual mxComplexInt32 * get_complex_int32s (void) const = 0;
+  virtual mxComplexInt64 * get_complex_int64s (void) const = 0;
+  virtual mxComplexUint8 * get_complex_uint8s (void) const = 0;
+  virtual mxComplexUint16 * get_complex_uint16s (void) const = 0;
+  virtual mxComplexUint32 * get_complex_uint32s (void) const = 0;
+  virtual mxComplexUint64 * get_complex_uint64s (void) const = 0;
+#endif
+
+  virtual void * get_imag_data (void) const = 0;
+
+  virtual void set_data (void *pr) = 0;
+
+  virtual int set_doubles (mxDouble *data) = 0;
+  virtual int set_singles (mxSingle *data) = 0;
+  virtual int set_int8s (mxInt8 *data) = 0;
+  virtual int set_int16s (mxInt16 *data) = 0;
+  virtual int set_int32s (mxInt32 *data) = 0;
+  virtual int set_int64s (mxInt64 *data) = 0;
+  virtual int set_uint8s (mxUint8 *data) = 0;
+  virtual int set_uint16s (mxUint16 *data) = 0;
+  virtual int set_uint32s (mxUint32 *data) = 0;
+  virtual int set_uint64s (mxUint64 *data) = 0;
+
+  virtual int set_complex_doubles (mxComplexDouble *data) = 0;
+  virtual int set_complex_singles (mxComplexSingle *data) = 0;
+#if 0
+  /* We don't have these yet. */
+  virtual int set_complex_int8s (mxComplexInt8 *data) = 0;
+  virtual int set_complex_int16s (mxComplexInt16 *data) = 0;
+  virtual int set_complex_int32s (mxComplexInt32 *data) = 0;
+  virtual int set_complex_int64s (mxComplexInt64 *data) = 0;
+  virtual int set_complex_uint8s (mxComplexUint8 *data) = 0;
+  virtual int set_complex_uint16s (mxComplexUint16 *data) = 0;
+  virtual int set_complex_uint32s (mxComplexUint32 *data) = 0;
+  virtual int set_complex_uint64s (mxComplexUint64 *data) = 0;
+#endif
+
+  virtual void set_imag_data (void *pi) = 0;
+
+  virtual mwIndex * get_ir (void) const = 0;
+
+  virtual mwIndex * get_jc (void) const = 0;
+
+  virtual mwSize get_nzmax (void) const = 0;
+
+  virtual void set_ir (mwIndex *ir) = 0;
+
+  virtual void set_jc (mwIndex *jc) = 0;
+
+  virtual void set_nzmax (mwSize nzmax) = 0;
+
+  virtual int add_field (const char *key) = 0;
+
+  virtual void remove_field (int key_num) = 0;
+
+  virtual mxArray * get_field_by_number (mwIndex index, int key_num) const = 0;
+
+  virtual void
+  set_field_by_number (mwIndex index, int key_num, mxArray *val) = 0;
+
+  virtual int get_number_of_fields (void) const = 0;
+
+  virtual const char * get_field_name_by_number (int key_num) const = 0;
+
+  virtual int get_field_number (const char *key) const = 0;
+
+  virtual int get_string (char *buf, mwSize buflen) const = 0;
+
+  virtual char * array_to_string (void) const = 0;
+
+  virtual mwIndex calc_single_subscript (mwSize nsubs, mwIndex *subs) const = 0;
+
+  virtual size_t get_element_size (void) const = 0;
+
+  virtual bool mutation_needed (void) const { return false; }
+
+  virtual mxArray * mutate (void) const { return nullptr; }
+
+  virtual octave_value as_octave_value (void) const = 0;
+
+protected:
+
+  // If TRUE, we are using interleaved storage for complex numeric arrays.
+  bool m_interleaved;
+
+  mxArray_base (const mxArray_base&) = default;
+
+  size_t get_numeric_element_size (size_t size) const
+  {
+    return (m_interleaved
+            ? is_complex () ? 2 * size : size
+            : size);
+  }
+
+  OCTAVE_NORETURN void err_invalid_type (const char *op) const
+  {
+    error ("%s: invalid type for mxArray::%s", get_class_name (), op);
+  }
+};
+
+// The main interface class.  The representation can be based on an
+// octave_value object or a separate object that tries to reproduce
+// the semantics of mxArray objects in Matlab more directly.
+
+class mxArray
+{
+public:
+
+  mxArray (bool interleaved, const octave_value& ov);
+
+  mxArray (bool interleaved, mxClassID id, mwSize ndims, const mwSize *dims,
+           mxComplexity flag = mxREAL, bool init = true);
+
+  mxArray (bool interleaved, mxClassID id, const dim_vector& dv,
+           mxComplexity flag = mxREAL);
+
+  mxArray (bool interleaved, mxClassID id, mwSize m, mwSize n,
+           mxComplexity flag = mxREAL, bool init = true);
+
+  mxArray (bool interleaved, mxClassID id, double val);
+
+  mxArray (bool interleaved, mxClassID id, mxLogical val);
+
+  mxArray (bool interleaved, const char *str);
+
+  mxArray (bool interleaved, mwSize m, const char **str);
+
+  mxArray (bool interleaved, mxClassID id, mwSize m, mwSize n, mwSize nzmax,
+           mxComplexity flag = mxREAL);
+
+  mxArray (bool interleaved, mwSize ndims, const mwSize *dims, int num_keys,
+           const char **keys);
+
+  mxArray (bool interleaved, const dim_vector& dv, int num_keys,
+           const char **keys);
+
+  mxArray (bool interleaved, mwSize m, mwSize n, int num_keys,
+           const char **keys);
+
+  mxArray (bool interleaved, mwSize ndims, const mwSize *dims);
+
+  mxArray (bool interleaved, const dim_vector& dv);
+
+  mxArray (bool interleaved, mwSize m, mwSize n);
+
+  mxArray * dup (void) const
+  {
+    mxArray *retval = rep->as_mxArray ();
+
+    if (retval)
+      retval->set_name (name);
+    else
+      {
+        mxArray_base *new_rep = rep->dup ();
+
+        retval = new mxArray (new_rep, name);
+      }
+
+    return retval;
+  }
+
+  // No copying!
+
+  mxArray (const mxArray&) = delete;
+
+  mxArray& operator = (const mxArray&) = delete;
+
+  ~mxArray (void);
+
+  bool is_octave_value (void) const { return rep->is_octave_value (); }
+
+  int iscell (void) const { return rep->iscell (); }
+
+  int is_char (void) const { return rep->is_char (); }
+
+  int is_class (const char *name_arg) const { return rep->is_class (name_arg); }
+
+  int is_complex (void) const { return rep->is_complex (); }
+
+  int is_double (void) const { return rep->is_double (); }
+
+  int is_function_handle (void) const { return rep->is_function_handle (); }
+
+  int is_int16 (void) const { return rep->is_int16 (); }
+
+  int is_int32 (void) const { return rep->is_int32 (); }
+
+  int is_int64 (void) const { return rep->is_int64 (); }
+
+  int is_int8 (void) const { return rep->is_int8 (); }
+
+  int is_logical (void) const { return rep->is_logical (); }
+
+  int is_numeric (void) const { return rep->is_numeric (); }
+
+  int is_single (void) const { return rep->is_single (); }
+
+  int is_sparse (void) const { return rep->is_sparse (); }
+
+  int is_struct (void) const { return rep->is_struct (); }
+
+  int is_uint16 (void) const { return rep->is_uint16 (); }
+
+  int is_uint32 (void) const { return rep->is_uint32 (); }
+
+  int is_uint64 (void) const { return rep->is_uint64 (); }
+
+  int is_uint8 (void) const { return rep->is_uint8 (); }
+
+  int is_logical_scalar (void) const { return rep->is_logical_scalar (); }
+
+  int is_logical_scalar_true (void) const
+  { return rep->is_logical_scalar_true (); }
+
+  mwSize get_m (void) const { return rep->get_m (); }
+
+  mwSize get_n (void) const { return rep->get_n (); }
+
+  mwSize * get_dimensions (void) const { return rep->get_dimensions (); }
+
+  mwSize get_number_of_dimensions (void) const
+  { return rep->get_number_of_dimensions (); }
+
+  void set_m (mwSize m) { DO_VOID_MUTABLE_METHOD (set_m (m)); }
+
+  void set_n (mwSize n) { DO_VOID_MUTABLE_METHOD (set_n (n)); }
+
+  int set_dimensions (mwSize *dims_arg, mwSize ndims_arg)
+  { DO_MUTABLE_METHOD (int, set_dimensions (dims_arg, ndims_arg)); }
+
+  mwSize get_number_of_elements (void) const
+  { return rep->get_number_of_elements (); }
+
+  int isempty (void) const { return get_number_of_elements () == 0; }
+
+  bool is_scalar (void) const { return rep->is_scalar (); }
+
+  const char * get_name (void) const { return name; }
+
+  void set_name (const char *name_arg);
+
+  mxClassID get_class_id (void) const { return rep->get_class_id (); }
+
+  const char * get_class_name (void) const { return rep->get_class_name (); }
+
+  mxArray * get_property (mwIndex idx, const char *pname) const
+  { return rep->get_property (idx, pname); }
+
+  void set_property (mwIndex idx, const char *pname, const mxArray *pval)
+  { rep->set_property (idx, pname, pval); }
+
+  void set_class_name (const char *name_arg)
+  { DO_VOID_MUTABLE_METHOD (set_class_name (name_arg)); }
+
+  mxArray * get_cell (mwIndex idx) const
+  { DO_MUTABLE_METHOD (mxArray *, get_cell (idx)); }
+
+  void set_cell (mwIndex idx, mxArray *val)
+  { DO_VOID_MUTABLE_METHOD (set_cell (idx, val)); }
+
+  double get_scalar (void) const { return rep->get_scalar (); }
+
+  void * get_data (void) const { DO_MUTABLE_METHOD (void *, get_data ()); }
+
+  mxDouble * get_doubles (void) const
+  { DO_MUTABLE_METHOD (mxDouble *, get_doubles ()); }
+
+  mxSingle * get_singles (void) const
+  { DO_MUTABLE_METHOD (mxSingle *, get_singles ()); }
+
+  mxInt8 * get_int8s (void) const
+  { DO_MUTABLE_METHOD (mxInt8 *, get_int8s ()); }
+
+  mxInt16 * get_int16s (void) const
+  { DO_MUTABLE_METHOD (mxInt16 *, get_int16s ()); }
+
+  mxInt32 * get_int32s (void) const
+  { DO_MUTABLE_METHOD (mxInt32 *, get_int32s ()); }
+
+  mxInt64 * get_int64s (void) const
+  { DO_MUTABLE_METHOD (mxInt64 *, get_int64s ()); }
+
+  mxUint8 * get_uint8s (void) const
+  { DO_MUTABLE_METHOD (mxUint8 *, get_uint8s ()); }
+
+  mxUint16 * get_uint16s (void) const
+  { DO_MUTABLE_METHOD (mxUint16 *, get_uint16s ()); }
+
+  mxUint32 * get_uint32s (void) const
+  { DO_MUTABLE_METHOD (mxUint32 *, get_uint32s ()); }
+
+  mxUint64 * get_uint64s (void) const
+  { DO_MUTABLE_METHOD (mxUint64 *, get_uint64s ()); }
+
+  mxComplexDouble * get_complex_doubles (void) const
+  { DO_MUTABLE_METHOD (mxComplexDouble *, get_complex_doubles ()); }
+
+  mxComplexSingle * get_complex_singles (void) const
+  { DO_MUTABLE_METHOD (mxComplexSingle *, get_complex_singles ()); }
+
+#if 0
+  /* We don't have these yet. */
+  mxComplexInt8 * get_complex_int8s (void) const
+  { DO_MUTABLE_METHOD (mxComplexInt8 *, get_complex_int8s ()); }
+
+  mxComplexInt16 * get_complex_int16s (void) const
+  { DO_MUTABLE_METHOD (mxComplexInt16 *, get_complex_int16s ()); }
+
+  mxComplexInt32 * get_complex_int32s (void) const
+  { DO_MUTABLE_METHOD (mxComplexInt32 *, get_complex_int32s ()); }
+
+  mxComplexInt64 * get_complex_int64s (void) const
+  { DO_MUTABLE_METHOD (mxComplexInt64 *, get_complex_int64s ()); }
+
+  mxComplexUint8 * get_complex_uint8s (void) const
+  { DO_MUTABLE_METHOD (mxComplexUint8 *, get_complex_uint8s ()); }
+
+  mxComplexUint16 * get_complex_uint16s (void) const
+  { DO_MUTABLE_METHOD (mxComplexUint16 *, get_complex_uint16s ()); }
+
+  mxComplexUint32 * get_complex_uint32s (void) const
+  { DO_MUTABLE_METHOD (mxComplexUint32 *, get_complex_uint32s ()); }
+
+  mxComplexUint64 * get_complex_uint64s (void) const
+  { DO_MUTABLE_METHOD (mxComplexUint64 *, get_complex_uint64s ()); }
+#endif
+
+  void * get_imag_data (void) const
+  { DO_MUTABLE_METHOD (void *, get_imag_data ()); }
+
+  void set_data (void *pr) { DO_VOID_MUTABLE_METHOD (set_data (pr)); }
+
+  int set_doubles (mxDouble *data)
+  { DO_MUTABLE_METHOD (int, set_doubles (data)); }
+
+  int set_singles (mxSingle *data)
+  { DO_MUTABLE_METHOD (int, set_singles (data)); }
+
+  int set_int8s (mxInt8 *data)
+  { DO_MUTABLE_METHOD (int, set_int8s (data)); }
+
+  int set_int16s (mxInt16 *data)
+  { DO_MUTABLE_METHOD (int, set_int16s (data)); }
+
+  int set_int32s (mxInt32 *data)
+  { DO_MUTABLE_METHOD (int, set_int32s (data)); }
+
+  int set_int64s (mxInt64 *data)
+  { DO_MUTABLE_METHOD (int, set_int64s (data)); }
+
+  int set_uint8s (mxUint8 *data)
+  { DO_MUTABLE_METHOD (int, set_uint8s (data)); }
+
+  int set_uint16s (mxUint16 *data)
+  { DO_MUTABLE_METHOD (int, set_uint16s (data)); }
+
+  int set_uint32s (mxUint32 *data)
+  { DO_MUTABLE_METHOD (int, set_uint32s (data)); }
+
+  int set_uint64s (mxUint64 *data)
+  { DO_MUTABLE_METHOD (int, set_uint64s (data)); }
+
+  int set_complex_doubles (mxComplexDouble *data)
+  { DO_MUTABLE_METHOD (int, set_complex_doubles (data)); }
+
+  int set_complex_singles (mxComplexSingle *data)
+  { DO_MUTABLE_METHOD (int, set_complex_singles (data)); }
+
+#if 0
+  /* We don't have these yet. */
+  int set_complex_int8s (mxComplexInt8 *data)
+  { DO_MUTABLE_METHOD (int, set_complex_int8s (data)); }
+
+  int set_complex_int16s (mxComplexInt16 *data)
+  { DO_MUTABLE_METHOD (int, set_complex_int16s (data)); }
+
+  int set_complex_int32s (mxComplexInt32 *data)
+  { DO_MUTABLE_METHOD (int, set_complex_int32s (data)); }
+
+  int set_complex_int64s (mxComplexInt64 *data)
+  { DO_MUTABLE_METHOD (int, set_complex_int64s (data)); }
+
+  int set_complex_uint8s (mxComplexUint8 *data)
+  { DO_MUTABLE_METHOD (int, set_complex_uint8s (data)); }
+
+  int set_complex_uint16s (mxComplexUint16 *data)
+  { DO_MUTABLE_METHOD (int, set_complex_uint16s (data)); }
+
+  int set_complex_uint32s (mxComplexUint32 *data)
+  { DO_MUTABLE_METHOD (int, set_complex_uint32s (data)); }
+
+  int set_complex_uint64s (mxComplexUint64 *data)
+  { DO_MUTABLE_METHOD (int, set_complex_uint64s (data)); }
+#endif
+
+  void set_imag_data (void *pi) { DO_VOID_MUTABLE_METHOD (set_imag_data (pi)); }
+
+  mwIndex * get_ir (void) const { DO_MUTABLE_METHOD (mwIndex *, get_ir ()); }
+
+  mwIndex * get_jc (void) const { DO_MUTABLE_METHOD (mwIndex *, get_jc ()); }
+
+  mwSize get_nzmax (void) const { return rep->get_nzmax (); }
+
+  void set_ir (mwIndex *ir) { DO_VOID_MUTABLE_METHOD (set_ir (ir)); }
+
+  void set_jc (mwIndex *jc) { DO_VOID_MUTABLE_METHOD (set_jc (jc)); }
+
+  void set_nzmax (mwSize nzmax) { DO_VOID_MUTABLE_METHOD (set_nzmax (nzmax)); }
+
+  int add_field (const char *key) { DO_MUTABLE_METHOD (int, add_field (key)); }
+
+  void remove_field (int key_num)
+  { DO_VOID_MUTABLE_METHOD (remove_field (key_num)); }
+
+  mxArray * get_field_by_number (mwIndex index, int key_num) const
+  { DO_MUTABLE_METHOD (mxArray *, get_field_by_number (index, key_num)); }
+
+  void set_field_by_number (mwIndex index, int key_num, mxArray *val)
+  { DO_VOID_MUTABLE_METHOD (set_field_by_number (index, key_num, val)); }
+
+  int get_number_of_fields (void) const { return rep->get_number_of_fields (); }
+
+  const char * get_field_name_by_number (int key_num) const
+  { DO_MUTABLE_METHOD (const char*, get_field_name_by_number (key_num)); }
+
+  int get_field_number (const char *key) const
+  { DO_MUTABLE_METHOD (int, get_field_number (key)); }
+
+  int get_string (char *buf, mwSize buflen) const
+  { return rep->get_string (buf, buflen); }
+
+  char * array_to_string (void) const { return rep->array_to_string (); }
+
+  mwIndex calc_single_subscript (mwSize nsubs, mwIndex *subs) const
+  { return rep->calc_single_subscript (nsubs, subs); }
+
+  size_t get_element_size (void) const { return rep->get_element_size (); }
+
+  bool mutation_needed (void) const { return rep->mutation_needed (); }
+
+  mxArray * mutate (void) const { return rep->mutate (); }
+
+  static void * malloc (size_t n);
+
+  static void * calloc (size_t n, size_t t);
+
+  static char * strsave (const char *str)
+  {
+    char *retval = nullptr;
+
+    if (str)
+      {
+        mwSize sz = sizeof (mxChar) * (strlen (str) + 1);
+
+        retval = static_cast<char *> (mxArray::malloc (sz));
+
+        if (retval)
+          strcpy (retval, str);
+      }
+
+    return retval;
+  }
+
+  static octave_value
+  as_octave_value (const mxArray *ptr, bool null_is_empty = true);
+
+  octave_value as_octave_value (void) const;
+
+private:
+
+  mutable mxArray_base *rep;
+
+  char *name;
+
+  mxArray (mxArray_base *r, const char *n)
+    : rep (r), name (mxArray::strsave (n)) { }
+
+  static mxArray_base *
+  create_rep (bool interleaved, const octave_value& ov);
+
+  static mxArray_base *
+  create_rep (bool interleaved, mxClassID id, mwSize ndims,
+              const mwSize *dims, mxComplexity flag, bool init);
+
+  static mxArray_base *
+  create_rep (bool interleaved, mxClassID id, const dim_vector& dv,
+              mxComplexity flag);
+
+  static mxArray_base *
+  create_rep (bool interleaved, mxClassID id, mwSize m, mwSize n,
+              mxComplexity flag, bool init);
+
+  static mxArray_base *
+  create_rep (bool interleaved, mxClassID id, double val);
+
+  static mxArray_base *
+  create_rep (bool interleaved, mxClassID id, mxLogical val);
+
+  static mxArray_base *
+  create_rep (bool interleaved, const char *str);
+
+  static mxArray_base *
+  create_rep (bool interleaved, mwSize m, const char **str);
+
+  static mxArray_base *
+  create_rep (bool interleaved, mxClassID id, mwSize m, mwSize n,
+              mwSize nzmax, mxComplexity flag);
+
+  void maybe_mutate (void) const;
+};
+
+#undef DO_MUTABLE_METHOD
+#undef DO_VOID_MUTABLE_METHOD
+
+#endif
+#endif
--- a/libinterp/corefcn/mxarray.in.h	Tue Jul 07 18:34:23 2020 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,570 +0,0 @@
-// %NO_EDIT_WARNING%
-
-////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2001-2020 The Octave Project Developers
-//
-// See the file COPYRIGHT.md in the top-level directory of this
-// distribution or <https://octave.org/copyright/>.
-//
-// This file is part of Octave.
-//
-// Octave is free software: you can 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
-// <https://www.gnu.org/licenses/>.
-//
-////////////////////////////////////////////////////////////////////////
-
-/*
-
-Part of this code was originally distributed as part of Octave Forge under
-the following terms:
-
-Author: Paul Kienzle
-I grant this code to the public domain.
-2001-03-22
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGE.
-
-*/
-
-#if ! defined (octave_mxarray_h)
-#define octave_mxarray_h 1
-
-#include "octave-config.h"
-
-typedef enum
-{
-  mxUNKNOWN_CLASS = 0,
-  mxCELL_CLASS,
-  mxSTRUCT_CLASS,
-  mxLOGICAL_CLASS,
-  mxCHAR_CLASS,
-  mxVOID_CLASS,
-  mxDOUBLE_CLASS,
-  mxSINGLE_CLASS,
-  mxINT8_CLASS,
-  mxUINT8_CLASS,
-  mxINT16_CLASS,
-  mxUINT16_CLASS,
-  mxINT32_CLASS,
-  mxUINT32_CLASS,
-  mxINT64_CLASS,
-  mxUINT64_CLASS,
-  mxFUNCTION_CLASS
-}
-mxClassID;
-
-typedef enum
-{
-  mxREAL = 0,
-  mxCOMPLEX = 1
-}
-mxComplexity;
-
-/* Matlab uses a wide char (uint16) internally, but Octave uses plain char. */
-/* typedef Uint16 mxChar; */
-typedef char mxChar;
-
-typedef unsigned char mxLogical;
-
-/*
- * FIXME: Mathworks says mwSize, mwIndex should be int generally.
- * But on 64-bit systems, or when mex -largeArrayDims is used, it is size_t.
- * mwSignedIndex is supposed to be ptrdiff_t.  All of this is confusing.
- * Its better to conform to the same indexing as the rest of Octave.
- */
-typedef %OCTAVE_IDX_TYPE% mwSize;
-typedef %OCTAVE_IDX_TYPE% mwIndex;
-typedef %OCTAVE_IDX_TYPE% mwSignedIndex;
-
-#if ! defined (MXARRAY_TYPEDEFS_ONLY)
-
-#include <cstring>
-#include "error.h"
-
-class octave_value;
-class dim_vector;
-
-#define DO_MUTABLE_METHOD(RET_T, METHOD_CALL)   \
-  RET_T retval = rep->METHOD_CALL;              \
-                                                \
-  if (rep->mutation_needed ())                  \
-    {                                           \
-      maybe_mutate ();                          \
-      retval = rep->METHOD_CALL;                \
-    }                                           \
-                                                \
-  return retval
-
-#define DO_VOID_MUTABLE_METHOD(METHOD_CALL)     \
-  rep->METHOD_CALL;                             \
-                                                \
-  if (rep->mutation_needed ())                  \
-    {                                           \
-      maybe_mutate ();                          \
-      rep->METHOD_CALL;                         \
-    }
-
-class mxArray;
-
-// A class to provide the default implementation of some of the
-// virtual functions declared in the mxArray class.
-
-class mxArray_base
-{
-protected:
-
-  mxArray_base (void) { }
-
-public:
-
-  virtual mxArray_base * dup (void) const = 0;
-
-  virtual mxArray * as_mxArray (void) const { return nullptr; }
-
-  virtual ~mxArray_base (void) = default;
-
-  virtual bool is_octave_value (void) const { return false; }
-
-  virtual int iscell (void) const = 0;
-
-  virtual int is_char (void) const = 0;
-
-  virtual int is_class (const char *name_arg) const
-  {
-    int retval = 0;
-
-    const char *cname = get_class_name ();
-
-    if (cname && name_arg)
-      retval = ! strcmp (cname, name_arg);
-
-    return retval;
-  }
-
-  virtual int is_complex (void) const = 0;
-
-  virtual int is_double (void) const = 0;
-
-  virtual int is_function_handle (void) const = 0;
-
-  virtual int is_int16 (void) const = 0;
-
-  virtual int is_int32 (void) const = 0;
-
-  virtual int is_int64 (void) const = 0;
-
-  virtual int is_int8 (void) const = 0;
-
-  virtual int is_logical (void) const = 0;
-
-  virtual int is_numeric (void) const = 0;
-
-  virtual int is_single (void) const = 0;
-
-  virtual int is_sparse (void) const = 0;
-
-  virtual int is_struct (void) const = 0;
-
-  virtual int is_uint16 (void) const = 0;
-
-  virtual int is_uint32 (void) const = 0;
-
-  virtual int is_uint64 (void) const = 0;
-
-  virtual int is_uint8 (void) const = 0;
-
-  virtual int is_logical_scalar (void) const
-  {
-    return is_logical () && get_number_of_elements () == 1;
-  }
-
-  virtual int is_logical_scalar_true (void) const = 0;
-
-  virtual mwSize get_m (void) const = 0;
-
-  virtual mwSize get_n (void) const = 0;
-
-  virtual mwSize * get_dimensions (void) const = 0;
-
-  virtual mwSize get_number_of_dimensions (void) const = 0;
-
-  virtual void set_m (mwSize m) = 0;
-
-  virtual void set_n (mwSize n) = 0;
-
-  virtual int set_dimensions (mwSize *dims_arg, mwSize ndims_arg) = 0;
-
-  virtual mwSize get_number_of_elements (void) const = 0;
-
-  virtual int isempty (void) const = 0;
-
-  virtual bool is_scalar (void) const = 0;
-
-  virtual mxClassID get_class_id (void) const = 0;
-
-  virtual const char * get_class_name (void) const = 0;
-
-  virtual void set_class_name (const char *name_arg) = 0;
-
-  // The following functions aren't pure virtual because they are only
-  // valid for one type.  Making them pure virtual would mean that they
-  // have to be implemented for all derived types, and all of those
-  // would need to throw errors instead of just doing it once here.
-
-  virtual mxArray *
-  get_property (mwIndex /*idx*/, const char * /*pname*/) const
-  {
-    return nullptr;
-  }
-
-  virtual void set_property (mwIndex /*idx*/, const char * /*pname*/,
-                             const mxArray * /*pval*/)
-  {
-    err_invalid_type ();
-  }
-
-  virtual mxArray * get_cell (mwIndex /*idx*/) const
-  {
-    err_invalid_type ();
-  }
-
-  virtual void set_cell (mwIndex idx, mxArray *val) = 0;
-
-  virtual double get_scalar (void) const = 0;
-
-  virtual void * get_data (void) const = 0;
-
-  virtual void * get_imag_data (void) const = 0;
-
-  virtual void set_data (void *pr) = 0;
-
-  virtual void set_imag_data (void *pi) = 0;
-
-  virtual mwIndex * get_ir (void) const = 0;
-
-  virtual mwIndex * get_jc (void) const = 0;
-
-  virtual mwSize get_nzmax (void) const = 0;
-
-  virtual void set_ir (mwIndex *ir) = 0;
-
-  virtual void set_jc (mwIndex *jc) = 0;
-
-  virtual void set_nzmax (mwSize nzmax) = 0;
-
-  virtual int add_field (const char *key) = 0;
-
-  virtual void remove_field (int key_num) = 0;
-
-  virtual mxArray * get_field_by_number (mwIndex index, int key_num) const = 0;
-
-  virtual void
-  set_field_by_number (mwIndex index, int key_num, mxArray *val) = 0;
-
-  virtual int get_number_of_fields (void) const = 0;
-
-  virtual const char * get_field_name_by_number (int key_num) const = 0;
-
-  virtual int get_field_number (const char *key) const = 0;
-
-  virtual int get_string (char *buf, mwSize buflen) const = 0;
-
-  virtual char * array_to_string (void) const = 0;
-
-  virtual mwIndex calc_single_subscript (mwSize nsubs, mwIndex *subs) const = 0;
-
-  virtual size_t get_element_size (void) const = 0;
-
-  virtual bool mutation_needed (void) const { return false; }
-
-  virtual mxArray * mutate (void) const { return nullptr; }
-
-  virtual octave_value as_octave_value (void) const = 0;
-
-protected:
-
-  mxArray_base (const mxArray_base&) { }
-
-  OCTAVE_NORETURN void err_invalid_type (void) const
-  {
-    error ("invalid type for operation");
-  }
-};
-
-// The main interface class.  The representation can be based on an
-// octave_value object or a separate object that tries to reproduce
-// the semantics of mxArray objects in Matlab more directly.
-
-class mxArray
-{
-public:
-
-  mxArray (const octave_value& ov);
-
-  mxArray (mxClassID id, mwSize ndims, const mwSize *dims,
-           mxComplexity flag = mxREAL, bool init = true);
-
-  mxArray (mxClassID id, const dim_vector& dv, mxComplexity flag = mxREAL);
-
-  mxArray (mxClassID id, mwSize m, mwSize n,
-           mxComplexity flag = mxREAL, bool init = true);
-
-  mxArray (mxClassID id, double val);
-
-  mxArray (mxClassID id, mxLogical val);
-
-  mxArray (const char *str);
-
-  mxArray (mwSize m, const char **str);
-
-  mxArray (mxClassID id, mwSize m, mwSize n, mwSize nzmax,
-           mxComplexity flag = mxREAL);
-
-  mxArray (mwSize ndims, const mwSize *dims, int num_keys, const char **keys);
-
-  mxArray (const dim_vector& dv, int num_keys, const char **keys);
-
-  mxArray (mwSize m, mwSize n, int num_keys, const char **keys);
-
-  mxArray (mwSize ndims, const mwSize *dims);
-
-  mxArray (const dim_vector& dv);
-
-  mxArray (mwSize m, mwSize n);
-
-  mxArray * dup (void) const
-  {
-    mxArray *retval = rep->as_mxArray ();
-
-    if (retval)
-      retval->set_name (name);
-    else
-      {
-        mxArray_base *new_rep = rep->dup ();
-
-        retval = new mxArray (new_rep, name);
-      }
-
-    return retval;
-  }
-
-  // No copying!
-
-  mxArray (const mxArray&) = delete;
-
-  mxArray& operator = (const mxArray&) = delete;
-
-  ~mxArray (void);
-
-  bool is_octave_value (void) const { return rep->is_octave_value (); }
-
-  int iscell (void) const { return rep->iscell (); }
-
-  int is_char (void) const { return rep->is_char (); }
-
-  int is_class (const char *name_arg) const { return rep->is_class (name_arg); }
-
-  int is_complex (void) const { return rep->is_complex (); }
-
-  int is_double (void) const { return rep->is_double (); }
-
-  int is_function_handle (void) const { return rep->is_function_handle (); }
-
-  int is_int16 (void) const { return rep->is_int16 (); }
-
-  int is_int32 (void) const { return rep->is_int32 (); }
-
-  int is_int64 (void) const { return rep->is_int64 (); }
-
-  int is_int8 (void) const { return rep->is_int8 (); }
-
-  int is_logical (void) const { return rep->is_logical (); }
-
-  int is_numeric (void) const { return rep->is_numeric (); }
-
-  int is_single (void) const { return rep->is_single (); }
-
-  int is_sparse (void) const { return rep->is_sparse (); }
-
-  int is_struct (void) const { return rep->is_struct (); }
-
-  int is_uint16 (void) const { return rep->is_uint16 (); }
-
-  int is_uint32 (void) const { return rep->is_uint32 (); }
-
-  int is_uint64 (void) const { return rep->is_uint64 (); }
-
-  int is_uint8 (void) const { return rep->is_uint8 (); }
-
-  int is_logical_scalar (void) const { return rep->is_logical_scalar (); }
-
-  int is_logical_scalar_true (void) const
-  { return rep->is_logical_scalar_true (); }
-
-  mwSize get_m (void) const { return rep->get_m (); }
-
-  mwSize get_n (void) const { return rep->get_n (); }
-
-  mwSize * get_dimensions (void) const { return rep->get_dimensions (); }
-
-  mwSize get_number_of_dimensions (void) const
-  { return rep->get_number_of_dimensions (); }
-
-  void set_m (mwSize m) { DO_VOID_MUTABLE_METHOD (set_m (m)); }
-
-  void set_n (mwSize n) { DO_VOID_MUTABLE_METHOD (set_n (n)); }
-
-  int set_dimensions (mwSize *dims_arg, mwSize ndims_arg)
-  { DO_MUTABLE_METHOD (int, set_dimensions (dims_arg, ndims_arg)); }
-
-  mwSize get_number_of_elements (void) const
-  { return rep->get_number_of_elements (); }
-
-  int isempty (void) const { return get_number_of_elements () == 0; }
-
-  bool is_scalar (void) const { return rep->is_scalar (); }
-
-  const char * get_name (void) const { return name; }
-
-  void set_name (const char *name_arg);
-
-  mxClassID get_class_id (void) const { return rep->get_class_id (); }
-
-  const char * get_class_name (void) const { return rep->get_class_name (); }
-
-  mxArray * get_property (mwIndex idx, const char *pname) const
-  { return rep->get_property (idx, pname); }
-
-  void set_property (mwIndex idx, const char *pname, const mxArray *pval)
-  { rep->set_property (idx, pname, pval); }
-
-  void set_class_name (const char *name_arg)
-  { DO_VOID_MUTABLE_METHOD (set_class_name (name_arg)); }
-
-  mxArray * get_cell (mwIndex idx) const
-  { DO_MUTABLE_METHOD (mxArray *, get_cell (idx)); }
-
-  void set_cell (mwIndex idx, mxArray *val)
-  { DO_VOID_MUTABLE_METHOD (set_cell (idx, val)); }
-
-  double get_scalar (void) const { return rep->get_scalar (); }
-
-  void * get_data (void) const { DO_MUTABLE_METHOD (void *, get_data ()); }
-
-  void * get_imag_data (void) const
-  { DO_MUTABLE_METHOD (void *, get_imag_data ()); }
-
-  void set_data (void *pr) { DO_VOID_MUTABLE_METHOD (set_data (pr)); }
-
-  void set_imag_data (void *pi) { DO_VOID_MUTABLE_METHOD (set_imag_data (pi)); }
-
-  mwIndex * get_ir (void) const { DO_MUTABLE_METHOD (mwIndex *, get_ir ()); }
-
-  mwIndex * get_jc (void) const { DO_MUTABLE_METHOD (mwIndex *, get_jc ()); }
-
-  mwSize get_nzmax (void) const { return rep->get_nzmax (); }
-
-  void set_ir (mwIndex *ir) { DO_VOID_MUTABLE_METHOD (set_ir (ir)); }
-
-  void set_jc (mwIndex *jc) { DO_VOID_MUTABLE_METHOD (set_jc (jc)); }
-
-  void set_nzmax (mwSize nzmax) { DO_VOID_MUTABLE_METHOD (set_nzmax (nzmax)); }
-
-  int add_field (const char *key) { DO_MUTABLE_METHOD (int, add_field (key)); }
-
-  void remove_field (int key_num)
-  { DO_VOID_MUTABLE_METHOD (remove_field (key_num)); }
-
-  mxArray * get_field_by_number (mwIndex index, int key_num) const
-  { DO_MUTABLE_METHOD (mxArray *, get_field_by_number (index, key_num)); }
-
-  void set_field_by_number (mwIndex index, int key_num, mxArray *val)
-  { DO_VOID_MUTABLE_METHOD (set_field_by_number (index, key_num, val)); }
-
-  int get_number_of_fields (void) const { return rep->get_number_of_fields (); }
-
-  const char * get_field_name_by_number (int key_num) const
-  { DO_MUTABLE_METHOD (const char*, get_field_name_by_number (key_num)); }
-
-  int get_field_number (const char *key) const
-  { DO_MUTABLE_METHOD (int, get_field_number (key)); }
-
-  int get_string (char *buf, mwSize buflen) const
-  { return rep->get_string (buf, buflen); }
-
-  char * array_to_string (void) const { return rep->array_to_string (); }
-
-  mwIndex calc_single_subscript (mwSize nsubs, mwIndex *subs) const
-  { return rep->calc_single_subscript (nsubs, subs); }
-
-  size_t get_element_size (void) const { return rep->get_element_size (); }
-
-  bool mutation_needed (void) const { return rep->mutation_needed (); }
-
-  mxArray * mutate (void) const { return rep->mutate (); }
-
-  static void * malloc (size_t n);
-
-  static void * calloc (size_t n, size_t t);
-
-  static char * strsave (const char *str)
-  {
-    char *retval = nullptr;
-
-    if (str)
-      {
-        mwSize sz = sizeof (mxChar) * (strlen (str) + 1);
-
-        retval = static_cast<char *> (mxArray::malloc (sz));
-
-        if (retval)
-          strcpy (retval, str);
-      }
-
-    return retval;
-  }
-
-  static octave_value
-  as_octave_value (const mxArray *ptr, bool null_is_empty = true);
-
-  octave_value as_octave_value (void) const;
-
-private:
-
-  mutable mxArray_base *rep;
-
-  char *name;
-
-  mxArray (mxArray_base *r, const char *n)
-    : rep (r), name (mxArray::strsave (n)) { }
-
-  void maybe_mutate (void) const;
-};
-
-#undef DO_MUTABLE_METHOD
-#undef DO_VOID_MUTABLE_METHOD
-
-#endif
-#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/corefcn/mxtypes.in.h	Tue Jul 07 19:40:20 2020 -0400
@@ -0,0 +1,128 @@
+// %NO_EDIT_WARNING%
+
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2001-2020 The Octave Project Developers
+//
+// See the file COPYRIGHT.md in the top-level directory of this
+// distribution or <https://octave.org/copyright/>.
+//
+// This file is part of Octave.
+//
+// Octave is free software: you can 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
+// <https://www.gnu.org/licenses/>.
+//
+////////////////////////////////////////////////////////////////////////
+
+/*
+
+Part of this code was originally distributed as part of Octave Forge under
+the following terms:
+
+Author: Paul Kienzle
+I grant this code to the public domain.
+2001-03-22
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+*/
+
+#if ! defined (octave_mxtypes_h)
+#define octave_mxtypes_h 1
+
+#include "octave-config.h"
+
+typedef enum
+{
+  mxUNKNOWN_CLASS = 0,
+  mxCELL_CLASS,
+  mxSTRUCT_CLASS,
+  mxLOGICAL_CLASS,
+  mxCHAR_CLASS,
+  mxVOID_CLASS,
+  mxDOUBLE_CLASS,
+  mxSINGLE_CLASS,
+  mxINT8_CLASS,
+  mxUINT8_CLASS,
+  mxINT16_CLASS,
+  mxUINT16_CLASS,
+  mxINT32_CLASS,
+  mxUINT32_CLASS,
+  mxINT64_CLASS,
+  mxUINT64_CLASS,
+  mxFUNCTION_CLASS
+}
+mxClassID;
+
+typedef enum
+{
+  mxREAL = 0,
+  mxCOMPLEX = 1
+}
+mxComplexity;
+
+/* Matlab uses a wide char (uint16) internally, but Octave uses plain char. */
+/* typedef Uint16 mxChar; */
+typedef char mxChar;
+
+typedef unsigned char mxLogical;
+
+typedef double mxDouble;
+typedef float mxSingle;
+
+typedef int8_t mxInt8;
+typedef int16_t mxInt16;
+typedef int32_t mxInt32;
+typedef int64_t mxInt64;
+
+typedef uint8_t mxUint8;
+typedef uint16_t mxUint16;
+typedef uint32_t mxUint32;
+typedef uint64_t mxUint64;
+
+typedef struct { mxDouble real; mxDouble imag; } mxComplexDouble;
+typedef struct { mxSingle real; mxSingle imag; } mxComplexSingle;
+
+/* We don't have these yet but we can define the types. */
+typedef struct { mxInt8 real; mxInt8 imag; } mxComplexInt8;
+typedef struct { mxInt16 real; mxInt16 imag; } mxComplexInt16;
+typedef struct { mxInt32 real; mxInt32 imag; } mxComplexInt32;
+typedef struct { mxInt64 real; mxInt64 imag; } mxComplexInt64;
+
+typedef struct { mxUint8 real; mxUint8 imag; } mxComplexUint8;
+typedef struct { mxUint16 real; mxUint16 imag; } mxComplexUint16;
+typedef struct { mxUint32 real; mxUint32 imag; } mxComplexUint32;
+typedef struct { mxUint64 real; mxUint64 imag; } mxComplexUint64;
+
+/*
+ * FIXME: Mathworks says mwSize, mwIndex should be int generally.
+ * But on 64-bit systems, or when mex -largeArrayDims is used, it is size_t.
+ * mwSignedIndex is supposed to be ptrdiff_t.  All of this is confusing.
+ * Its better to conform to the same indexing as the rest of Octave.
+ */
+typedef %OCTAVE_IDX_TYPE% mwSize;
+typedef %OCTAVE_IDX_TYPE% mwIndex;
+typedef %OCTAVE_IDX_TYPE% mwSignedIndex;
+
+#endif
--- a/libinterp/corefcn/oct-hist.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/corefcn/oct-hist.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -47,6 +47,7 @@
 #include "cmd-hist.h"
 #include "file-ops.h"
 #include "lo-mappers.h"
+#include "lo-sysdep.h"
 #include "oct-env.h"
 #include "oct-time.h"
 #include "str-vec.h"
@@ -238,7 +239,7 @@
 
     std::string name = sys::tempnam ("", "oct-");
 
-    std::fstream file (name.c_str (), std::ios::out);
+    std::ofstream file = sys::ofstream (name.c_str (), std::ios::out);
 
     if (! file)
       error ("%s: couldn't open temporary file '%s'", warn_for,
@@ -478,7 +479,7 @@
     // Write the commands to the history file since source_file
     // disables command line history while it executes.
 
-    std::fstream file (name.c_str (), std::ios::in);
+    std::fstream file = sys::fstream (name.c_str (), std::ios::in);
 
     char *line;
     //int first = 1;
--- a/libinterp/corefcn/oct-stream.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/corefcn/oct-stream.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -1914,7 +1914,7 @@
 
     bool match_literal (delimited_stream& isp, const textscan_format_elt& elem);
 
-    int skip_whitespace (delimited_stream& is, bool EOLstop = false);
+    int skip_whitespace (delimited_stream& is, bool EOLstop = true);
 
     int skip_delim (delimited_stream& is);
 
@@ -2472,7 +2472,7 @@
     while (! ds.eof ())
       {
         bool already_skipped_delim = false;
-        ts.skip_whitespace (ds);
+        ts.skip_whitespace (ds, false);
         ds.progress_benchmark ();
         ts.scan_complex (ds, *fmt_elts[0], val);
         if (ds.fail ())
@@ -3500,11 +3500,12 @@
         elem = fmt_list.next ();
         char *pos = is.tellg ();
 
-        // FIXME: these conversions "ignore delimiters".  Should they include
-        // delimiters at the start of the conversion, or can those be skipped?
-        if (elem->type != textscan_format_elt::literal_conversion
-            // && elem->type != '[' && elem->type != '^' && elem->type != 'c'
-           )
+        // Skip delimiter before reading the next fmt conversion,
+        // unless the fmt is a string literal which begins with a delimiter,
+        // in which case the literal must match everything.  Bug #58008
+        if (elem->type != textscan_format_elt::literal_conversion)
+          skip_delim (is);
+        else if (! is_delim (elem->text[0]))
           skip_delim (is);
 
         if (is.eof ())
@@ -3892,8 +3893,8 @@
   int
   textscan::skip_delim (delimited_stream& is)
   {
-    int c1 = skip_whitespace (is, true);  // 'true': stop once EOL is read
-    if (delim_list.numel () == 0)         // single character delimiter
+    int c1 = skip_whitespace (is);  // Stop once EOL is read
+    if (delim_list.numel () == 0)   // single character delimiter
       {
         if (is_delim (c1) || c1 == eol1 || c1 == eol2)
           {
@@ -3943,7 +3944,7 @@
                 int prev = -1;
                 // skip multiple delims.
                 // Increment lines for each end-of-line seen; for \r\n, decrement
-                while (is && ((c1 = skip_whitespace (is, true))
+                while (is && ((c1 = skip_whitespace (is))
                               != std::istream::traits_type::eof ())
                        && (((c1 == eol1 || c1 == eol2) && ++lines)
                            || -1 != lookahead (is, delim_list, delim_len)))
--- a/libinterp/corefcn/syscalls.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/corefcn/syscalls.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -377,9 +377,10 @@
 
 */
 
-DEFMETHODX ("fcntl", Ffcntl, interp, args, ,
+DEFMETHODX ("fcntl", Ffcntl, interp, args, nargout,
             doc: /* -*- texinfo -*-
-@deftypefn {} {[@var{err}, @var{msg}] =} fcntl (@var{fid}, @var{request}, @var{arg})
+@deftypefn  {} {} fcntl (@var{fid}, @var{request}, @var{arg})
+@deftypefnx {} {[@var{status}, @var{msg}] =} fcntl (@var{fid}, @var{request}, @var{arg})
 Change the properties of the open file @var{fid}.
 
 The following values may be passed as @var{request}:
@@ -430,8 +431,8 @@
 @w{@code{O_NONBLOCK}}.
 @end vtable
 
-If successful, @var{err} is 0 and @var{msg} is an empty string.  Otherwise,
-@var{err} is nonzero and @var{msg} contains a system-dependent error
+If successful, @var{status} is 0 and @var{msg} is an empty string.  Otherwise,
+@var{status} is -1 and @var{msg} contains a system-dependent error
 message.
 @seealso{fopen, dup2}
 @end deftypefn */)
@@ -454,11 +455,25 @@
   if (fid < 0)
     error ("fcntl: invalid file id");
 
+  octave_value_list retval;
   std::string msg;
 
   int status = octave::sys::fcntl (fid, req, arg, msg);
 
-  return ovl (status, msg);
+  if (nargout == 0)
+    {
+      if (status < 0)
+        error ("fcntl: operation failed: %s", msg.c_str ());
+    }
+  else
+    {
+      if (status < 0)
+        retval = ovl (-1.0, msg);
+      else
+        retval = ovl (0.0, "");
+    }
+
+  return retval;
 }
 
 DEFMETHODX ("fork", Ffork, interp, args, ,
@@ -591,26 +606,29 @@
   return ovl (octave::sys::getuid ());
 }
 
-DEFUNX ("kill", Fkill, args, ,
+DEFUNX ("kill", Fkill, args, nargout,
         doc: /* -*- texinfo -*-
-@deftypefn {} {[@var{err}, @var{msg}] =} kill (@var{pid}, @var{sig})
+@deftypefn  {} {} kill (@var{pid}, @var{sig})
+@deftypefnx {} {[@var{status}, @var{msg}] =} kill (@var{pid}, @var{sig})
 Send signal @var{sig} to process @var{pid}.
 
 If @var{pid} is positive, then signal @var{sig} is sent to @var{pid}.
 
-If @var{pid} is 0, then signal @var{sig} is sent to every process
-in the process group of the current process.
+If @var{pid} is 0, then signal @var{sig} is sent to every process in the
+process group of the current process.
 
-If @var{pid} is -1, then signal @var{sig} is sent to every process
-except process 1.
+If @var{pid} is -1, then signal @var{sig} is sent to every process except
+process 1.
 
-If @var{pid} is less than -1, then signal @var{sig} is sent to every
-process in the process group @var{-pid}.
+If @var{pid} is less than -1, then signal @var{sig} is sent to every process in
+the process group @var{-pid}.
 
 If @var{sig} is 0, then no signal is sent, but error checking is still
 performed.
 
-Return 0 if successful, otherwise return -1.
+If successful, @var{status} is 0 and @var{msg} is an empty string.
+Otherwise, @var{status} is -1 and @var{msg} contains a system-dependent
+error message.
 @end deftypefn */)
 {
   if (args.length () != 2)
@@ -620,11 +638,25 @@
 
   int sig = args(1).int_value (true);
 
+  octave_value_list retval;
   std::string msg;
 
   int status = octave::sys::kill (pid, sig, msg);
 
-  return ovl (status, msg);
+  if (nargout == 0)
+    {
+      if (status < 0)
+        error ("kill: operation failed: %s", msg.c_str ());
+    }
+  else
+    {
+      if (status < 0)
+        retval = ovl (-1.0, msg);
+      else
+        retval = ovl (0.0, "");
+    }
+
+  return retval;
 }
 
 DEFUNX ("lstat", Flstat, args, ,
@@ -676,17 +708,17 @@
   return retval;
 }
 
-DEFUNX ("mkfifo", Fmkfifo, args, ,
+DEFUNX ("mkfifo", Fmkfifo, args, nargout,
         doc: /* -*- texinfo -*-
-@deftypefn  {} {@var{err} =} mkfifo (@var{name}, @var{mode})
-@deftypefnx {} {[@var{err}, @var{msg}] =} mkfifo (@var{name}, @var{mode})
+@deftypefn  {} {} mkfifo (@var{name}, @var{mode})
+@deftypefnx {} {[@var{status}, @var{msg}] =} mkfifo (@var{name}, @var{mode})
 Create a FIFO special file named @var{name} with file mode @var{mode}.
 
 @var{mode} is interpreted as an octal number and is subject to umask
 processing.  The final calculated mode is @code{@var{mode} - @var{umask}}.
 
-If successful, @var{err} is 0 and @var{msg} is an empty string.
-Otherwise, @var{err} is nonzero and @var{msg} contains a system-dependent
+If successful, @var{status} is 0 and @var{msg} is an empty string.
+Otherwise, @var{status} is -1 and @var{msg} contains a system-dependent
 error message.
 @seealso{pipe, umask}
 @end deftypefn */)
@@ -703,11 +735,25 @@
 
   int mode = convert (octal_mode, 8, 10);
 
+  octave_value_list retval;
   std::string msg;
 
   int status = octave::sys::mkfifo (name, mode, msg);
 
-  return ovl (status, msg);
+  if (nargout == 0)
+    {
+      if (status < 0)
+        error ("mkfifo: operation failed: %s", msg.c_str ());
+    }
+  else
+    {
+      if (status < 0)
+        retval = ovl (-1.0, msg);
+      else
+        retval = ovl (0.0, "");
+    }
+
+  return retval;
 }
 
 /*
@@ -1073,13 +1119,14 @@
 %! endif
 */
 
-DEFMETHODX ("unlink", Funlink, interp, args, ,
+DEFMETHODX ("unlink", Funlink, interp, args, nargout,
             doc: /* -*- texinfo -*-
-@deftypefn {} {[@var{err}, @var{msg}] =} unlink (@var{file})
+@deftypefn  {} {} unlink (@var{file})
+@deftypefnx {} {[@var{status}, @var{msg}] =} unlink (@var{file})
 Delete the file named @var{file}.
 
-If successful, @var{err} is 0 and @var{msg} is an empty string.
-Otherwise, @var{err} is nonzero and @var{msg} contains a system-dependent
+If successful, @var{status} is 0 and @var{msg} is an empty string.
+Otherwise, @var{status} is -1 and @var{msg} contains a system-dependent
 error message.
 @seealso{delete, rmdir}
 @end deftypefn */)
@@ -1089,6 +1136,7 @@
 
   std::string name = args(0).xstring_value ("unlink: FILE must be a string");
 
+  octave_value_list retval;
   std::string msg;
 
   octave::event_manager& evmgr = interp.get_event_manager ();
@@ -1099,7 +1147,20 @@
 
   evmgr.file_renamed (status == 0);
 
-  return ovl (status, msg);
+  if (nargout == 0)
+    {
+      if (status < 0)
+        error ("unlink: operation failed: %s", msg.c_str ());
+    }
+  else
+    {
+      if (status < 0)
+        retval = ovl (-1.0, msg);
+      else
+        retval = ovl (0.0, "");
+    }
+
+  return retval;
 }
 
 /*
@@ -1111,13 +1172,13 @@
 %! endif
 %! fdisp (fid, pi);
 %! fclose (fid);
-%! [err, msg] = unlink (file);
-%! assert (err, 0);
+%! [status, msg] = unlink (file);
+%! assert (status, 0);
 %! assert (msg, "");
 
 ## Test input validation
-%!error unlink ()
-%!error unlink ("a", "b")
+%!error <Invalid call> unlink ()
+%!error <Invalid call> unlink ("a", "b")
 %!error <FILE must be a string> unlink (123)
 */
 
--- a/libinterp/corefcn/sysdep.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/corefcn/sysdep.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -97,6 +97,7 @@
 #define WIN32_LEAN_AND_MEAN
 #include <windows.h>
 #include <tlhelp32.h>
+#include <psapi.h>
 #include <shellapi.h>
 
 #endif
@@ -282,6 +283,101 @@
 #endif
 }
 
+DEFUN (__wmemory__, args, ,
+       doc: /* -*- texinfo -*-
+@deftypefn {} {[@var{proc}, @var{sys}] =} __wmemory__ ()
+Return memory information on Windows.
+
+On non-Windows platforms, this function fails with an error.
+@end deftypefn */)
+{
+#if defined (OCTAVE_USE_WINDOWS_API)
+  if (args.length () != 0)
+    print_usage ();
+
+  // Get memory usage of the current process
+  octave_scalar_map proc_struct;
+
+  HANDLE h_proc = GetCurrentProcess ();
+  if (h_proc == nullptr)
+    error ("__wmemory__: Couldn't open handle to own process.");
+
+  PROCESS_MEMORY_COUNTERS proc_mem_count;
+  if (GetProcessMemoryInfo (h_proc, &proc_mem_count, sizeof (proc_mem_count)))
+    {
+      proc_struct.setfield ("PageFaultCount",
+                            proc_mem_count.PageFaultCount);
+      proc_struct.setfield ("PeakWorkingSetSize",
+                            proc_mem_count.PeakWorkingSetSize);
+      proc_struct.setfield ("WorkingSetSize",
+                            proc_mem_count.WorkingSetSize);
+      proc_struct.setfield ("QuotaPeakPagedPoolUsage",
+                            proc_mem_count.QuotaPeakPagedPoolUsage);
+      proc_struct.setfield ("QuotaPagedPoolUsage",
+                            proc_mem_count.QuotaPagedPoolUsage);
+      proc_struct.setfield ("QuotaPeakNonPagedPoolUsage",
+                            proc_mem_count.QuotaPeakNonPagedPoolUsage);
+      proc_struct.setfield ("QuotaNonPagedPoolUsage",
+                            proc_mem_count.QuotaNonPagedPoolUsage);
+      proc_struct.setfield ("PagefileUsage",
+                            proc_mem_count.PagefileUsage);
+      proc_struct.setfield ("PeakPagefileUsage",
+                            proc_mem_count.PeakPagefileUsage);
+    }
+  else
+    {
+      proc_struct.setfield ("PageFaultCount", 0);
+      proc_struct.setfield ("PeakWorkingSetSize", 0);
+      proc_struct.setfield ("WorkingSetSize", 0);
+      proc_struct.setfield ("QuotaPeakPagedPoolUsage", 0);
+      proc_struct.setfield ("QuotaPagedPoolUsage", 0);
+      proc_struct.setfield ("QuotaPeakNonPagedPoolUsage", 0);
+      proc_struct.setfield ("QuotaNonPagedPoolUsage", 0);
+      proc_struct.setfield ("PagefileUsage", 0);
+      proc_struct.setfield ("PeakPagefileUsage", 0);
+    }
+
+  CloseHandle (h_proc);
+
+  // Get system memory usage
+  octave_scalar_map sys_struct;
+
+  MEMORYSTATUSEX mem_stat;
+
+  mem_stat.dwLength = sizeof (mem_stat);
+
+  if (GlobalMemoryStatusEx (&mem_stat))
+    {
+      sys_struct.setfield ("MemoryLoad", mem_stat.dwMemoryLoad);
+      sys_struct.setfield ("TotalPhys", mem_stat.ullTotalPhys);
+      sys_struct.setfield ("AvailPhys", mem_stat.ullAvailPhys);
+      sys_struct.setfield ("TotalPageFile", mem_stat.ullTotalPageFile);
+      sys_struct.setfield ("AvailPageFile", mem_stat.ullAvailPageFile);
+      sys_struct.setfield ("TotalVirtual", mem_stat.ullTotalVirtual);
+      sys_struct.setfield ("AvailVirtual", mem_stat.ullAvailVirtual);
+      sys_struct.setfield ("AvailExtendedVirtual",
+                           mem_stat.ullAvailExtendedVirtual);
+    }
+  else
+    {
+      sys_struct.setfield ("MemoryLoad", 0);
+      sys_struct.setfield ("TotalPhys", 0);
+      sys_struct.setfield ("AvailPhys", 0);
+      sys_struct.setfield ("TotalPageFile", 0);
+      sys_struct.setfield ("AvailPageFile", 0);
+      sys_struct.setfield ("TotalVirtual", 0);
+      sys_struct.setfield ("AvailVirtual", 0);
+      sys_struct.setfield ("AvailExtendedVirtual", 0);
+    }
+
+  return ovl (proc_struct, sys_struct);
+
+#else
+  octave_unused_parameter (args);
+  error ("__wmemory__: Function is only supported on Windows platforms.");
+#endif
+}
+
 namespace octave
 {
 #if defined (__MINGW32__)
--- a/libinterp/corefcn/sysdep.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/corefcn/sysdep.h	Tue Jul 07 19:40:20 2020 -0400
@@ -59,71 +59,4 @@
   extern OCTINTERP_API bool drive_or_unc_share (const std::string&);
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (5, "use 'octave::sysdep_init' instead")
-inline void
-sysdep_init (void)
-{
-  octave::sysdep_init ();
-}
-
-OCTAVE_DEPRECATED (5, "use 'octave::set_application_id' instead")
-inline void
-set_application_id (void)
-{
-  octave::set_application_id ();
-}
-
-OCTAVE_DEPRECATED (5, "use 'octave::sysdep_cleanup' instead")
-inline void
-sysdep_cleanup (void)
-{
-  octave::sysdep_cleanup ();
-}
-
-OCTAVE_DEPRECATED (5, "use 'octave::raw_mode' instead")
-inline void
-raw_mode (bool on, bool wait = true)
-{
-  octave::raw_mode (on, wait);
-}
-
-OCTAVE_DEPRECATED (5, "use 'octave::popen' instead")
-inline FILE *
-octave_popen (const char *command, const char *mode)
-{
-  return octave::popen (command, mode);
-}
-
-OCTAVE_DEPRECATED (5, "use 'octave::pclose' instead")
-inline int
-octave_pclose (FILE *f)
-{
-  return octave::pclose (f);
-}
-
-OCTAVE_DEPRECATED (5, "use 'octave::kbhit' instead")
-inline int
-octave_kbhit (bool wait = true)
-{
-  return octave::kbhit (wait);
-}
-
-OCTAVE_DEPRECATED (5, "use 'octave::get_P_tmpdir' instead")
-inline std::string
-get_P_tmpdir (void)
-{
-  return octave::get_P_tmpdir ();
-}
-
-OCTAVE_DEPRECATED (5, "use 'octave::same_file_internal' instead")
-inline bool
-same_file_internal (const std::string& a, const std::string& b)
-{
-  return octave::same_file_internal (a, b);
-}
-
 #endif
-
-#endif
--- a/libinterp/corefcn/text-engine.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/corefcn/text-engine.h	Tue Jul 07 19:40:20 2020 -0400
@@ -459,53 +459,4 @@
   }
 }
 
-#if defined (OCAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (5, "use 'octave::text_element' instead")
-typedef octave::text_element text_element;
-
-OCTAVE_DEPRECATED (5, "use 'octave::text_element_string' instead")
-typedef octave::text_element_string text_element_string;
-
-OCTAVE_DEPRECATED (5, "use 'octave::text_element_symbol' instead")
-typedef octave::text_element_symbol text_element_symbol;
-
-OCTAVE_DEPRECATED (5, "use 'octave::text_element_list' instead")
-typedef octave::text_element_list text_element_list;
-
-OCTAVE_DEPRECATED (5, "use 'octave::text_element_subscript' instead")
-typedef octave::text_element_subscript text_element_subscript;
-
-OCTAVE_DEPRECATED (5, "use 'octave::text_element_superscript' instead")
-typedef octave::text_element_superscript text_element_superscript;
-
-OCTAVE_DEPRECATED (5, "use 'octave::text_element_combined' instead")
-typedef octave::text_element_combined text_element_combined;
-
-OCTAVE_DEPRECATED (5, "use 'octave::text_element_fontstyle' instead")
-typedef octave::text_element_fontstyle text_element_fontstyle;
-
-OCTAVE_DEPRECATED (5, "use 'octave::text_element_fontname' instead")
-typedef octave::text_element_fontname text_element_fontname;
-
-OCTAVE_DEPRECATED (5, "use 'octave::text_element_fontsize' instead")
-typedef octave::text_element_fontsize text_element_fontsize;
-
-OCTAVE_DEPRECATED (5, "use 'octave::text_element_color' instead")
-typedef octave::text_element_color text_element_color;
-
-OCTAVE_DEPRECATED (5, "use 'octave::text_processor' instead")
-typedef octave::text_processor text_processor;
-
-OCTAVE_DEPRECATED (5, "use 'octave::text_parser' instead")
-typedef octave::text_parser text_parser;
-
-OCTAVE_DEPRECATED (5, "use 'octave::text_parser_none' instead")
-typedef octave::text_parser_none text_parser_none;
-
-OCTAVE_DEPRECATED (5, "use 'octave::text_parser_tex' instead")
-typedef octave::text_parser_tex text_parser_tex;
-
 #endif
-
-#endif
--- a/libinterp/corefcn/tril.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/corefcn/tril.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -209,8 +209,10 @@
   dim_vector dims = arg.dims ();
   if (dims.ndims () != 2)
     error ("%s: need a 2-D matrix", name.c_str ());
-  else if (k < -dims(0) || k > dims(1))
-    error ("%s: requested diagonal out of range", name.c_str ());
+  else if (k < -dims(0))
+    k = -dims(0);
+  else if (k > dims(1))
+    k = dims(1);
 
   octave_value retval;
 
@@ -428,24 +430,51 @@
 }
 
 /*
-%!test
+%!shared a, l2, l1, l0, lm1, lm2, lm3, lm4
 %! a = [1, 2, 3; 4, 5, 6; 7, 8, 9; 10, 11, 12];
 %!
-%! l0 = [1, 0, 0; 4, 5, 0; 7, 8, 9; 10, 11, 12];
+%! l2 = [1, 2, 3; 4, 5, 6; 7, 8, 9; 10, 11, 12];
 %! l1 = [1, 2, 0; 4, 5, 6; 7, 8, 9; 10, 11, 12];
-%! l2 = [1, 2, 3; 4, 5, 6; 7, 8, 9; 10, 11, 12];
+%! l0 = [1, 0, 0; 4, 5, 0; 7, 8, 9; 10, 11, 12];
 %! lm1 = [0, 0, 0; 4, 0, 0; 7, 8, 0; 10, 11, 12];
 %! lm2 = [0, 0, 0; 0, 0, 0; 7, 0, 0; 10, 11, 0];
 %! lm3 = [0, 0, 0; 0, 0, 0; 0, 0, 0; 10, 0, 0];
 %! lm4 = [0, 0, 0; 0, 0, 0; 0, 0, 0; 0, 0, 0];
 %!
-%! assert (tril (a, -4), lm4);
-%! assert (tril (a, -3), lm3);
-%! assert (tril (a, -2), lm2);
-%! assert (tril (a, -1), lm1);
-%! assert (tril (a), l0);
-%! assert (tril (a, 1), l1);
-%! assert (tril (a, 2), l2);
+%!assert (tril (a, 3), l2);
+%!assert (tril (a, 2), l2);
+%!assert (tril (a, 1), l1);
+%!assert (tril (a, 0), l0);
+%!assert (tril (a), l0);
+%!assert (tril (a, -1), lm1);
+%!assert (tril (a, -2), lm2);
+%!assert (tril (a, -3), lm3);
+%!assert (tril (a, -4), lm4);
+%!assert (tril (a, -5), lm4);
+
+%!shared a, u3, u2, u1, u0, um1, um2, um3
+%!
+%! a = [1, 2, 3; 4, 5, 6; 7, 8, 9; 10, 11, 12];
+%!
+%! u3 = [0, 0, 0; 0, 0, 0; 0, 0, 0; 0, 0, 0];
+%! u2 = [0, 0, 3; 0, 0, 0; 0, 0, 0; 0, 0, 0];
+%! u1 = [0, 2, 3; 0, 0, 6; 0, 0, 0; 0, 0, 0];
+%! u0 = [1, 2, 3; 0, 5, 6; 0, 0, 9; 0, 0, 0];
+%! um1 = [1, 2, 3; 4, 5, 6; 0, 8, 9; 0, 0, 12];
+%! um2 = [1, 2, 3; 4, 5, 6; 7, 8, 9; 0, 11, 12];
+%! um3 = [1, 2, 3; 4, 5, 6; 7, 8, 9; 10, 11, 12];
+%!
+%!assert (triu (a, 4), u3);
+%!assert (triu (a, 3), u3);
+%!assert (triu (a, 2), u2);
+%!assert (triu (a, 1), u1);
+%!assert (triu (a, 0), u0);
+%!assert (triu (a), u0);
+%!assert (triu (a, -1), um1);
+%!assert (triu (a, -2), um2);
+%!assert (triu (a, -3), um3);
+%!assert (triu (a, -4), um3);
 
 %!error tril ()
+%!error triu ()
 */
--- a/libinterp/corefcn/txt-eng.h	Tue Jul 07 18:34:23 2020 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2018-2020 The Octave Project Developers
-//
-// See the file COPYRIGHT.md in the top-level directory of this
-// distribution or <https://octave.org/copyright/>.
-//
-// This file is part of Octave.
-//
-// Octave is free software: you can 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
-// <https://www.gnu.org/licenses/>.
-//
-////////////////////////////////////////////////////////////////////////
-
-#if ! defined (octave_txt_eng_h)
-#define octave_txt_eng_h 1
-
-#include "octave-config.h"
-
-// Deprecated in Octave 5.  Remove in Octave 7
-#warning "txt-eng.h has been deprecated; use text-engine instead"
-
-#include "text-engine.h"
-
-#endif
--- a/libinterp/corefcn/urlwrite.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/corefcn/urlwrite.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -142,7 +142,8 @@
 
   octave::sys::file_stat fs (filename);
 
-  std::ofstream ofile (filename.c_str (), std::ios::out | std::ios::binary);
+  std::ofstream ofile =
+    octave::sys::ofstream (filename.c_str (), std::ios::out | std::ios::binary);
 
   if (! ofile.is_open ())
     error ("urlwrite: unable to open file");
--- a/libinterp/corefcn/utils.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/corefcn/utils.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -1648,183 +1648,3 @@
 
 %!error isstudent (1)
 */
-
-// Always define these functions.  The macro is intended to allow the
-// declarations to be hidden, not so that Octave will not provide the
-// functions if they are requested.
-
-// #if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-#include "ov.h"
-#include "ovl.h"
-#include "str-vec.h"
-
-bool
-valid_identifier (const char *s)
-{
-  return octave::valid_identifier (s);
-}
-
-bool
-valid_identifier (const std::string& s)
-{
-  return octave::valid_identifier (s);
-}
-
-bool
-same_file (const std::string& f, const std::string& g)
-{
-  return octave::same_file (f, g);
-}
-
-int
-almost_match (const std::string& std, const std::string& s,
-              int min_match_len, int case_sens)
-{
-  return octave::almost_match (std, s, min_match_len, case_sens);
-}
-
-int
-keyword_almost_match (const char * const *std, int *min_len,
-                      const std::string& s, int min_toks_to_match,
-                      int max_toks)
-{
-  return octave::keyword_almost_match (std, min_len, s, min_toks_to_match,
-                                       max_toks);
-}
-
-std::string
-search_path_for_file (const std::string& path, const string_vector& names)
-{
-  return octave::search_path_for_file (path, names);
-}
-
-string_vector
-search_path_for_all_files (const std::string& path, const string_vector& names)
-{
-  return octave::search_path_for_all_files (path, names);
-}
-
-std::string
-file_in_path (const std::string& name, const std::string& suffix)
-{
-  return octave::file_in_path (name, suffix);
-}
-
-std::string
-find_data_file_in_load_path  (const std::string& fcn, const std::string& file,
-                              bool require_regular_file)
-{
-  return octave::find_data_file_in_load_path  (fcn, file, require_regular_file);
-}
-
-std::string
-contents_file_in_path (const std::string& s)
-{
-  return octave::contents_file_in_path (s);
-}
-
-std::string
-fcn_file_in_path (const std::string& s)
-{
-  return octave::fcn_file_in_path (s);
-}
-
-std::string
-do_string_escapes (const std::string& s)
-{
-  return octave::do_string_escapes (s);
-}
-
-const char *
-undo_string_escape (char c)
-{
-  return octave::undo_string_escape (c);
-}
-
-std::string
-undo_string_escapes (const std::string& s)
-{
-  return octave::undo_string_escapes (s);
-}
-
-void
-check_dimensions (dim_vector& dim, const char *warnfor)
-{
-  return octave::check_dimensions (dim, warnfor);
-}
-
-void
-get_dimensions (const octave_value& a, const char *warn_for,
-                dim_vector& dim)
-{
-  return octave::get_dimensions (a, warn_for, dim);
-}
-
-void
-get_dimensions (const octave_value& a, const octave_value& b,
-                const char *warn_for, octave_idx_type& nr,
-                octave_idx_type& nc)
-{
-  return octave::get_dimensions (a, b, warn_for, nr, nc);
-}
-
-void
-get_dimensions (const octave_value& a, const char *warn_for,
-                octave_idx_type& nr, octave_idx_type& nc)
-{
-  return octave::get_dimensions (a, warn_for, nr, nc);
-}
-
-octave_idx_type
-dims_to_numel (const dim_vector& dims, const octave_value_list& idx)
-{
-  return octave::dims_to_numel (dims, idx);
-}
-
-Matrix
-identity_matrix (octave_idx_type nr, octave_idx_type nc)
-{
-  return octave::identity_matrix (nr, nc);
-}
-
-FloatMatrix
-float_identity_matrix (octave_idx_type nr, octave_idx_type nc)
-{
-  return octave::float_identity_matrix (nr, nc);
-}
-
-size_t
-octave_vformat (std::ostream& os, const char *fmt, va_list args)
-{
-  return octave::vformat (os, fmt, args);
-}
-
-std::string
-octave_vasprintf (const char *fmt, va_list args)
-{
-  return octave::vasprintf (fmt, args);
-}
-
-void
-octave_sleep (double seconds)
-{
-  octave::sleep (seconds);
-}
-
-octave_value_list
-do_simple_cellfun (octave_value_list (*fun) (const octave_value_list&, int),
-                   const char *fun_name, const octave_value_list& args,
-                   int nargout)
-{
-  return octave::do_simple_cellfun (fun, fun_name, args, nargout);
-}
-
-octave_value
-do_simple_cellfun (octave_value_list (*fun) (const octave_value_list&, int),
-                   const char *fun_name, const octave_value_list& args)
-{
-  return octave::do_simple_cellfun (fun, fun_name, args);
-}
-
-// #endif
--- a/libinterp/corefcn/utils.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/corefcn/utils.h	Tue Jul 07 19:40:20 2020 -0400
@@ -141,139 +141,4 @@
                      const char *fun_name, const octave_value_list& args);
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (5, "use 'octave::valid_identifier' instead")
-extern OCTINTERP_API bool
-valid_identifier (const char *s);
-
-OCTAVE_DEPRECATED (5, "use 'octave::valid_identifier' instead")
-extern OCTINTERP_API bool
-valid_identifier (const std::string& s);
-
-OCTAVE_DEPRECATED (5, "use 'octave::same_file' instead")
-extern OCTINTERP_API bool
-same_file (const std::string& f, const std::string& g);
-
-OCTAVE_DEPRECATED (5, "use 'octave::almost_match' instead")
-extern OCTINTERP_API int
-almost_match (const std::string& std, const std::string& s,
-              int min_match_len = 1, int case_sens = 1);
-
-OCTAVE_DEPRECATED (5, "use 'octave::keyword_almost_match' instead")
-extern OCTINTERP_API int
-keyword_almost_match (const char * const *std, int *min_len,
-                      const std::string& s, int min_toks_to_match,
-                      int max_toks);
-
-OCTAVE_DEPRECATED (5, "use 'octave::search_path_for_file' instead")
-extern OCTINTERP_API std::string
-search_path_for_file (const std::string& path, const string_vector& names);
-
-OCTAVE_DEPRECATED (5, "use 'octave::search_path_for_all_files' instead")
-extern OCTINTERP_API string_vector
-search_path_for_all_files (const std::string& path, const string_vector& names);
-
-OCTAVE_DEPRECATED (5, "use 'octave::file_in_path' instead")
-extern OCTINTERP_API std::string
-file_in_path (const std::string& name, const std::string& suffix);
-
-OCTAVE_DEPRECATED (5, "use 'octave::find_data_file_in_load_path ' instead")
-extern OCTINTERP_API std::string
-find_data_file_in_load_path  (const std::string& fcn, const std::string& file,
-                              bool require_regular_file = false);
-
-OCTAVE_DEPRECATED (5, "use 'octave::contents_file_in_path' instead")
-extern OCTINTERP_API std::string
-contents_file_in_path (const std::string& s);
-
-OCTAVE_DEPRECATED (5, "use 'octave::fcn_file_in_path' instead")
-extern OCTINTERP_API std::string
-fcn_file_in_path (const std::string& s);
-
-OCTAVE_DEPRECATED (5, "use 'octave::do_string_escapes' instead")
-extern OCTINTERP_API std::string
-do_string_escapes (const std::string& s);
-
-OCTAVE_DEPRECATED (5, "use 'octave::undo_string_escape' instead")
-extern OCTINTERP_API const char *
-undo_string_escape (char c);
-
-OCTAVE_DEPRECATED (5, "use 'octave::undo_string_escapes' instead")
-extern OCTINTERP_API std::string
-undo_string_escapes (const std::string& s);
-
-OCTAVE_DEPRECATED (5, "use 'octave::check_dimensions' instead")
-extern OCTINTERP_API void
-check_dimensions (dim_vector& dim, const char *warnfor);
-
-OCTAVE_DEPRECATED (5, "use 'octave::get_dimensions' instead")
-extern OCTINTERP_API void
-get_dimensions (const octave_value& a, const char *warn_for,
-                dim_vector& dim);
-
-OCTAVE_DEPRECATED (5, "use 'octave::get_dimensions' instead")
-extern OCTINTERP_API void
-get_dimensions (const octave_value& a, const octave_value& b,
-                const char *warn_for, octave_idx_type& nr,
-                octave_idx_type& nc);
-
-OCTAVE_DEPRECATED (5, "use 'octave::get_dimensions' instead")
-extern OCTINTERP_API void
-get_dimensions (const octave_value& a, const char *warn_for,
-                octave_idx_type& nr, octave_idx_type& nc);
-
-OCTAVE_DEPRECATED (5, "use 'octave::dims_to_numel' instead")
-extern OCTINTERP_API octave_idx_type
-dims_to_numel (const dim_vector& dims, const octave_value_list& idx);
-
-OCTAVE_DEPRECATED (5, "use 'octave::identity_matrix' instead")
-extern OCTINTERP_API Matrix
-identity_matrix (octave_idx_type nr, octave_idx_type nc);
-
-OCTAVE_DEPRECATED (5, "use 'octave::float_identity_matrix' instead")
-extern OCTINTERP_API FloatMatrix
-float_identity_matrix (octave_idx_type nr, octave_idx_type nc);
-
-template <typename ... Args>
-OCTAVE_DEPRECATED (5, "use 'octave::format' instead")
-size_t
-octave_format (std::ostream& os, const char *fmt, Args&& ... args)
-{
-  return octave::format (os, fmt, std::forward<Args> (args) ...);
-}
-
-OCTAVE_DEPRECATED (5, "use 'octave::vformat' instead")
-extern OCTINTERP_API size_t
-octave_vformat (std::ostream& os, const char *fmt, va_list args);
-
-OCTAVE_DEPRECATED (5, "use 'octave::vasprintf' instead")
-extern OCTINTERP_API std::string
-octave_vasprintf (const char *fmt, va_list args);
-
-template <typename ... Args>
-OCTAVE_DEPRECATED (5, "use 'octave::asprintf' instead")
-std::string
-octave_asprintf (const char *fmt, Args&& ... args)
-{
-  return octave::asprintf (fmt, std::forward<Args> (args) ...);
-}
-
-OCTAVE_DEPRECATED (5, "use 'octave::sleep' instead")
-extern OCTINTERP_API void
-octave_sleep (double seconds);
-
-OCTAVE_DEPRECATED (5, "use 'octave::do_simple_cellfun' instead")
-extern OCTINTERP_API octave_value_list
-do_simple_cellfun (octave_value_list (*fun) (const octave_value_list&, int),
-                   const char *fun_name, const octave_value_list& args,
-                   int nargout);
-
-OCTAVE_DEPRECATED (5, "use 'octave::do_simple_cellfun' instead")
-extern OCTINTERP_API octave_value
-do_simple_cellfun (octave_value_list (*fun) (const octave_value_list&, int),
-                   const char *fun_name, const octave_value_list& args);
-
 #endif
-
-#endif
--- a/libinterp/corefcn/variables.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/corefcn/variables.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -1473,42 +1473,3 @@
 {
   return SET_INTERNAL_VARIABLE (missing_component_hook);
 }
-
-// The following function is deprecated.
-
-string_vector
-get_struct_elts (const std::string& text)
-{
-  int n = 1;
-
-  size_t pos = 0;
-
-  size_t len = text.length ();
-
-  while ((pos = text.find ('.', pos)) != std::string::npos)
-    {
-      if (++pos == len)
-        break;
-
-      n++;
-    }
-
-  string_vector retval (n);
-
-  pos = 0;
-
-  for (int i = 0; i < n; i++)
-    {
-      len = text.find ('.', pos);
-
-      if (len != std::string::npos)
-        len -= pos;
-
-      retval[i] = text.substr (pos, len);
-
-      if (len != std::string::npos)
-        pos += len + 1;
-    }
-
-  return retval;
-}
--- a/libinterp/corefcn/variables.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/corefcn/variables.h	Tue Jul 07 19:40:20 2020 -0400
@@ -116,8 +116,4 @@
 extern OCTINTERP_API std::string
 maybe_missing_function_hook (const std::string& name);
 
-OCTAVE_DEPRECATED (5, "this function will be removed in a future version of Octave")
-extern OCTINTERP_API string_vector
-get_struct_elts (const std::string& text);
-
 #endif
--- a/libinterp/dldfcn/__init_fltk__.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/dldfcn/__init_fltk__.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -2490,22 +2490,21 @@
 // autoloaded functions in the PKG_ADD file and will not be visible to
 // the interpreter.
 
+#if defined (HAVE_FLTK)
 static octave_value_list
 F__fltk_check__ (octave::interpreter& interp, const octave_value_list&, int)
 {
-#if defined (HAVE_FLTK)
   Fl::check ();
 
   if (Vdrawnow_requested)
     Fdrawnow (interp);
 
   return octave_value_list ();
-#else
   octave_unused_parameter (interp);
 
   err_disabled_feature ("__fltk_check__", "OpenGL and FLTK");
+}
 #endif
-}
 
 // Initialize the fltk graphics toolkit.
 
--- a/libinterp/dldfcn/audiodevinfo.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/dldfcn/audiodevinfo.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -2383,7 +2383,7 @@
     {
       // FIXME: Should be able to support 32-bit streams (bug #57939)
       int nbits = args(2).int_value ();
-      if (nbits != 8 || nbits != 16 || nbits != 24)
+      if (nbits != 8 && nbits != 16 && nbits != 24)
         error ("audioplayer: NBITS must be 8, 16, or 24");
 
       switch (args.length ())
--- a/libinterp/dldfcn/gzip.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/dldfcn/gzip.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -703,7 +703,7 @@
 %!      test_function (test_dir, z)
 %!    unwind_protect_cleanup
 %!      confirm_recursive_rmdir (false, "local");
-%!      rmdir (test_dir, "s");
+%!      sts = rmdir (test_dir, "s");
 %!    end_unwind_protect
 %!  endfor
 %!endfunction
@@ -843,7 +843,7 @@
 %!  unwind_protect_cleanup
 %!    confirm_recursive_rmdir (false, "local");
 %!    for idx = 1:numel(out_dirs)
-%!      rmdir (out_dirs{idx}, "s");
+%!      sts = rmdir (out_dirs{idx}, "s");
 %!    endfor
 %!  end_unwind_protect
 %!endfunction
--- a/libinterp/module.mk	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/module.mk	Tue Jul 07 19:40:20 2020 -0400
@@ -33,7 +33,7 @@
   %reldir%/corefcn/default-defs.h \
   %reldir%/corefcn/graphics-props.cc \
   %reldir%/corefcn/graphics.h \
-  %reldir%/corefcn/mxarray.h \
+  %reldir%/corefcn/mxtypes.h \
   %reldir%/corefcn/oct-tex-parser.h \
   %reldir%/corefcn/oct-tex-symbols.cc \
   %reldir%/parse-tree/oct-gperf.h \
@@ -66,7 +66,7 @@
   %reldir%/corefcn/default-defs.h \
   %reldir%/corefcn/graphics-props.cc \
   %reldir%/corefcn/graphics.h \
-  %reldir%/corefcn/mxarray.h \
+  %reldir%/corefcn/mxtypes.h \
   %reldir%/corefcn/oct-errno.cc \
   %reldir%/liboctinterp-build-info.cc \
   %reldir%/operators/ops.cc
@@ -99,7 +99,7 @@
   %reldir%/builtin-defun-decls.h \
   %reldir%/corefcn/graphics-props.cc \
   %reldir%/corefcn/graphics.h \
-  %reldir%/corefcn/mxarray.h
+  %reldir%/corefcn/mxtypes.h
 
 DIST_SRC += \
   %reldir%/octave.cc \
@@ -129,7 +129,7 @@
   %reldir%/builtins.cc \
   %reldir%/corefcn/default-defs.h \
   %reldir%/corefcn/graphics.h \
-  %reldir%/corefcn/mxarray.h \
+  %reldir%/corefcn/mxtypes.h \
   %reldir%/corefcn/oct-errno.cc \
   %reldir%/liboctinterp-build-info.cc \
   %reldir%/operators/ops.cc
--- a/libinterp/octave-value/ov-base-diag.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-base-diag.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -543,9 +543,9 @@
 
 template <typename DMT, typename MT>
 mxArray *
-octave_base_diag<DMT, MT>::as_mxArray (void) const
+octave_base_diag<DMT, MT>::as_mxArray (bool interleaved) const
 {
-  return to_dense ().as_mxArray ();
+  return to_dense ().as_mxArray (interleaved);
 }
 
 template <typename DMT, typename MT>
--- a/libinterp/octave-value/ov-base-diag.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-base-diag.h	Tue Jul 07 19:40:20 2020 -0400
@@ -224,7 +224,7 @@
              oct_data_conv::data_type output_type, int skip,
              octave::mach_info::float_format flt_fmt) const;
 
-  mxArray * as_mxArray (void) const;
+  mxArray * as_mxArray (bool interleaved) const;
 
   bool print_as_scalar (void) const;
 
--- a/libinterp/octave-value/ov-base.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-base.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -965,7 +965,7 @@
 }
 
 mxArray *
-octave_base_value::as_mxArray (void) const
+octave_base_value::as_mxArray (bool) const
 {
   return nullptr;
 }
--- a/libinterp/octave-value/ov-base.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-base.h	Tue Jul 07 19:40:20 2020 -0400
@@ -694,7 +694,7 @@
 
   virtual octave_idx_type * mex_get_jc (void) const { return nullptr; }
 
-  virtual mxArray * as_mxArray (void) const;
+  virtual mxArray * as_mxArray (bool interleaved) const;
 
   virtual octave_value diag (octave_idx_type k = 0) const;
 
--- a/libinterp/octave-value/ov-bool-mat.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-bool-mat.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -566,18 +566,18 @@
 }
 
 mxArray *
-octave_bool_matrix::as_mxArray (void) const
+octave_bool_matrix::as_mxArray (bool interleaved) const
 {
-  mxArray *retval = new mxArray (mxLOGICAL_CLASS, dims (), mxREAL);
+  mxArray *retval = new mxArray (interleaved, mxLOGICAL_CLASS, dims (), mxREAL);
 
-  bool *pr = static_cast<bool *> (retval->get_data ());
+  mxLogical *pd = static_cast<mxLogical *> (retval->get_data ());
 
   mwSize nel = numel ();
 
-  const bool *p = matrix.data ();
+  const bool *pdata = matrix.data ();
 
   for (mwIndex i = 0; i < nel; i++)
-    pr[i] = p[i];
+    pd[i] = pdata[i];
 
   return retval;
 }
--- a/libinterp/octave-value/ov-bool-mat.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-bool-mat.h	Tue Jul 07 19:40:20 2020 -0400
@@ -233,7 +233,7 @@
   // You should not use it anywhere else.
   void * mex_get_data (void) const { return matrix.mex_get_data (); }
 
-  mxArray * as_mxArray (void) const;
+  mxArray * as_mxArray (bool interleaved) const;
 
   // Mapper functions are converted to double for treatment
   octave_value map (unary_mapper_t umap) const
--- a/libinterp/octave-value/ov-bool-sparse.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-bool-sparse.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -802,23 +802,34 @@
 }
 
 mxArray *
-octave_sparse_bool_matrix::as_mxArray (void) const
+octave_sparse_bool_matrix::as_mxArray (bool interleaved) const
 {
   mwSize nz = nzmax ();
-  mxArray *retval = new mxArray (mxLOGICAL_CLASS, rows (), columns (),
-                                 nz, mxREAL);
-  bool *pr = static_cast<bool *> (retval->get_data ());
+  mwSize nr = rows ();
+  mwSize nc = columns ();
+
+  mxArray *retval = new mxArray (interleaved, mxLOGICAL_CLASS, nr, nc, nz,
+                                 mxREAL);
+
+  mxLogical *pd = static_cast<mxLogical *> (retval->get_data ());
   mwIndex *ir = retval->get_ir ();
-  mwIndex *jc = retval->get_jc ();
+
+  const bool *pdata = matrix.data ();
+  const octave_idx_type *pridx = matrix.ridx ();
 
   for (mwIndex i = 0; i < nz; i++)
     {
-      pr[i] = matrix.data (i);
-      ir[i] = matrix.ridx (i);
+      pd[i] = pdata[i];
+
+      ir[i] = pridx[i];
     }
 
-  for (mwIndex i = 0; i < columns () + 1; i++)
-    jc[i] = matrix.cidx (i);
+  mwIndex *jc = retval->get_jc ();
+
+  const octave_idx_type *pcidx = matrix.cidx ();
+
+  for (mwIndex i = 0; i < nc + 1; i++)
+    jc[i] = pcidx[i];
 
   return retval;
 }
--- a/libinterp/octave-value/ov-bool-sparse.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-bool-sparse.h	Tue Jul 07 19:40:20 2020 -0400
@@ -143,7 +143,7 @@
 
   bool load_hdf5 (octave_hdf5_id loc_id, const char *name);
 
-  mxArray * as_mxArray (void) const;
+  mxArray * as_mxArray (bool interleaved) const;
 
   // Mapper functions are converted to double for treatment
   octave_value map (unary_mapper_t umap) const
--- a/libinterp/octave-value/ov-bool.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-bool.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -312,13 +312,13 @@
 }
 
 mxArray *
-octave_bool::as_mxArray (void) const
+octave_bool::as_mxArray (bool interleaved) const
 {
-  mxArray *retval = new mxArray (mxLOGICAL_CLASS, 1, 1, mxREAL);
+  mxArray *retval = new mxArray (interleaved, mxLOGICAL_CLASS, 1, 1, mxREAL);
 
-  bool *pr = static_cast<bool *> (retval->get_data ());
+  mxLogical *pd = static_cast<mxLogical *> (retval->get_data ());
 
-  pr[0] = scalar;
+  pd[0] = scalar;
 
   return retval;
 }
--- a/libinterp/octave-value/ov-bool.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-bool.h	Tue Jul 07 19:40:20 2020 -0400
@@ -246,7 +246,7 @@
                      skip, flt_fmt);
   }
 
-  mxArray * as_mxArray (void) const;
+  mxArray * as_mxArray (bool interleaved) const;
 
   // Mapper functions are converted to double for treatment
   octave_value map (unary_mapper_t umap) const
--- a/libinterp/octave-value/ov-cell.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-cell.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -1406,9 +1406,9 @@
 */
 
 mxArray *
-octave_cell::as_mxArray (void) const
+octave_cell::as_mxArray (bool interleaved) const
 {
-  mxArray *retval = new mxArray (dims ());
+  mxArray *retval = new mxArray (interleaved, dims ());
 
   mxArray **elts = static_cast<mxArray **> (retval->get_data ());
 
@@ -1417,7 +1417,7 @@
   const octave_value *p = matrix.data ();
 
   for (mwIndex i = 0; i < nel; i++)
-    elts[i] = new mxArray (p[i]);
+    elts[i] = new mxArray (interleaved, p[i]);
 
   return retval;
 }
--- a/libinterp/octave-value/ov-cell.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-cell.h	Tue Jul 07 19:40:20 2020 -0400
@@ -172,7 +172,7 @@
 
   octave_value map (unary_mapper_t umap) const;
 
-  mxArray * as_mxArray (void) const;
+  mxArray * as_mxArray (bool interleaved) const;
 
   // Unsafe.  This function exists to support the MEX interface.
   // You should not use it anywhere else.
--- a/libinterp/octave-value/ov-ch-mat.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-ch-mat.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -222,18 +222,18 @@
 }
 
 mxArray *
-octave_char_matrix::as_mxArray (void) const
+octave_char_matrix::as_mxArray (bool interleaved) const
 {
-  mxArray *retval = new mxArray (mxCHAR_CLASS, dims (), mxREAL);
+  mxArray *retval = new mxArray (interleaved, mxCHAR_CLASS, dims (), mxREAL);
 
-  mxChar *pr = static_cast<mxChar *> (retval->get_data ());
+  mxChar *pd = static_cast<mxChar *> (retval->get_data ());
 
   mwSize nel = numel ();
 
-  const char *p = matrix.data ();
+  const char *pdata = matrix.data ();
 
   for (mwIndex i = 0; i < nel; i++)
-    pr[i] = p[i];
+    pd[i] = pdata[i];
 
   return retval;
 }
--- a/libinterp/octave-value/ov-ch-mat.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-ch-mat.h	Tue Jul 07 19:40:20 2020 -0400
@@ -167,7 +167,7 @@
   // You should not use it anywhere else.
   void * mex_get_data (void) const { return matrix.mex_get_data (); }
 
-  mxArray * as_mxArray (void) const;
+  mxArray * as_mxArray (bool interleaved) const;
 
   octave_value map (unary_mapper_t umap) const;
 };
--- a/libinterp/octave-value/ov-class.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-class.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -1638,7 +1638,7 @@
 }
 
 mxArray *
-octave_class::as_mxArray (void) const
+octave_class::as_mxArray (bool) const
 {
   err_wrong_type_arg ("octave_class::as_mxArray ()", type_name ());
 }
--- a/libinterp/octave-value/ov-class.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-class.h	Tue Jul 07 19:40:20 2020 -0400
@@ -205,7 +205,7 @@
 
   bool load_hdf5 (octave_hdf5_id loc_id, const char *name);
 
-  mxArray * as_mxArray (void) const;
+  mxArray * as_mxArray (bool interleaved) const;
 
 private:
   octave_map map;
--- a/libinterp/octave-value/ov-complex.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-complex.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -472,15 +472,26 @@
 }
 
 mxArray *
-octave_complex::as_mxArray (void) const
+octave_complex::as_mxArray (bool interleaved) const
 {
-  mxArray *retval = new mxArray (mxDOUBLE_CLASS, 1, 1, mxCOMPLEX);
+  mxArray *retval = new mxArray (interleaved, mxDOUBLE_CLASS, 1, 1, mxCOMPLEX);
+
+  if (interleaved)
+    {
+      mxComplexDouble *pd
+        = reinterpret_cast<mxComplexDouble *> (retval->get_complex_doubles ());
 
-  double *pr = static_cast<double *> (retval->get_data ());
-  double *pi = static_cast<double *> (retval->get_imag_data ());
+      pd[0].real = scalar.real ();
+      pd[0].imag = scalar.imag ();
+    }
+  else
+    {
+      mxDouble *pr = static_cast<mxDouble *> (retval->get_data ());
+      mxDouble *pi = static_cast<mxDouble *> (retval->get_imag_data ());
 
-  pr[0] = scalar.real ();
-  pi[0] = scalar.imag ();
+      pr[0] = scalar.real ();
+      pi[0] = scalar.imag ();
+    }
 
   return retval;
 }
--- a/libinterp/octave-value/ov-complex.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-complex.h	Tue Jul 07 19:40:20 2020 -0400
@@ -195,7 +195,7 @@
                      skip, flt_fmt);
   }
 
-  mxArray * as_mxArray (void) const;
+  mxArray * as_mxArray (bool interleaved) const;
 
   octave_value map (unary_mapper_t umap) const;
 
--- a/libinterp/octave-value/ov-cx-mat.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-cx-mat.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -724,21 +724,36 @@
 }
 
 mxArray *
-octave_complex_matrix::as_mxArray (void) const
+octave_complex_matrix::as_mxArray (bool interleaved) const
 {
-  mxArray *retval = new mxArray (mxDOUBLE_CLASS, dims (), mxCOMPLEX);
-
-  double *pr = static_cast<double *> (retval->get_data ());
-  double *pi = static_cast<double *> (retval->get_imag_data ());
+  mxArray *retval = new mxArray (interleaved, mxDOUBLE_CLASS, dims (),
+                                 mxCOMPLEX);
 
   mwSize nel = numel ();
 
-  const Complex *p = matrix.data ();
+  const Complex *pdata = matrix.data ();
+
+  if (interleaved)
+    {
+      mxComplexDouble *pd
+        = static_cast<mxComplexDouble *> (retval->get_data ());
 
-  for (mwIndex i = 0; i < nel; i++)
+      for (mwIndex i = 0; i < nel; i++)
+        {
+          pd[i].real = pdata[i].real ();
+          pd[i].imag = pdata[i].imag ();
+        }
+    }
+  else
     {
-      pr[i] = std::real (p[i]);
-      pi[i] = std::imag (p[i]);
+      mxDouble *pr = static_cast<mxDouble *> (retval->get_data ());
+      mxDouble *pi = static_cast<mxDouble *> (retval->get_imag_data ());
+
+      for (mwIndex i = 0; i < nel; i++)
+        {
+          pr[i] = pdata[i].real ();
+          pi[i] = pdata[i].imag ();
+        }
     }
 
   return retval;
--- a/libinterp/octave-value/ov-cx-mat.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-cx-mat.h	Tue Jul 07 19:40:20 2020 -0400
@@ -175,7 +175,7 @@
 
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
 
-  mxArray * as_mxArray (void) const;
+  mxArray * as_mxArray (bool interleaved) const;
 
   octave_value map (unary_mapper_t umap) const;
 
--- a/libinterp/octave-value/ov-cx-sparse.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-cx-sparse.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -874,26 +874,53 @@
 }
 
 mxArray *
-octave_sparse_complex_matrix::as_mxArray (void) const
+octave_sparse_complex_matrix::as_mxArray (bool interleaved) const
 {
   mwSize nz = nzmax ();
-  mxArray *retval = new mxArray (mxDOUBLE_CLASS, rows (), columns (),
-                                 nz, mxCOMPLEX);
-  double *pr = static_cast<double *> (retval->get_data ());
-  double *pi = static_cast<double *> (retval->get_imag_data ());
+  mwSize nr = rows ();
+  mwSize nc = columns ();
+
+  mxArray *retval = new mxArray (interleaved, mxDOUBLE_CLASS, nr, nc, nz,
+                                 mxCOMPLEX);
+
   mwIndex *ir = retval->get_ir ();
+
+  const Complex *pdata = matrix.data ();
+  const octave_idx_type *pridx = matrix.ridx ();
+
+  if (interleaved)
+    {
+      mxComplexDouble *pd
+        = static_cast<mxComplexDouble *> (retval->get_data ());
+
+      for (mwIndex i = 0; i < nz; i++)
+        {
+          pd[i].real = pdata[i].real ();
+          pd[i].imag = pdata[i].imag ();
+
+          ir[i] = pridx[i];
+        }
+    }
+  else
+    {
+      mxDouble *pr = static_cast<mxDouble *> (retval->get_data ());
+      mxDouble *pi = static_cast<mxDouble *> (retval->get_imag_data ());
+
+      for (mwIndex i = 0; i < nz; i++)
+        {
+          pr[i] = pdata[i].real ();
+          pi[i] = pdata[i].imag ();
+
+          ir[i] = pridx[i];
+        }
+    }
+
   mwIndex *jc = retval->get_jc ();
 
-  for (mwIndex i = 0; i < nz; i++)
-    {
-      Complex val = matrix.data (i);
-      pr[i] = val.real ();
-      pi[i] = val.imag ();
-      ir[i] = matrix.ridx (i);
-    }
+  const octave_idx_type *pcidx = matrix.cidx ();
 
-  for (mwIndex i = 0; i < columns () + 1; i++)
-    jc[i] = matrix.cidx (i);
+  for (mwIndex i = 0; i < nc + 1; i++)
+    jc[i] = pcidx[i];
 
   return retval;
 }
--- a/libinterp/octave-value/ov-cx-sparse.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-cx-sparse.h	Tue Jul 07 19:40:20 2020 -0400
@@ -149,7 +149,7 @@
 
   bool load_hdf5 (octave_hdf5_id loc_id, const char *name);
 
-  mxArray * as_mxArray (void) const;
+  mxArray * as_mxArray (bool interleaved) const;
 
   octave_value map (unary_mapper_t umap) const;
 
--- a/libinterp/octave-value/ov-float.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-float.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -335,13 +335,13 @@
 }
 
 mxArray *
-octave_float_scalar::as_mxArray (void) const
+octave_float_scalar::as_mxArray (bool interleaved) const
 {
-  mxArray *retval = new mxArray (mxSINGLE_CLASS, 1, 1, mxREAL);
+  mxArray *retval = new mxArray (interleaved, mxSINGLE_CLASS, 1, 1, mxREAL);
 
-  float *pr = static_cast<float *> (retval->get_data ());
+  mxSingle *pd = static_cast<mxSingle *> (retval->get_data ());
 
-  pr[0] = scalar;
+  pd[0] = scalar;
 
   return retval;
 }
--- a/libinterp/octave-value/ov-float.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-float.h	Tue Jul 07 19:40:20 2020 -0400
@@ -266,7 +266,7 @@
                      skip, flt_fmt);
   }
 
-  mxArray * as_mxArray (void) const;
+  mxArray * as_mxArray (bool interleaved) const;
 
   octave_value map (unary_mapper_t umap) const;
 
--- a/libinterp/octave-value/ov-flt-complex.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-flt-complex.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -414,15 +414,26 @@
 }
 
 mxArray *
-octave_float_complex::as_mxArray (void) const
+octave_float_complex::as_mxArray (bool interleaved) const
 {
-  mxArray *retval = new mxArray (mxSINGLE_CLASS, 1, 1, mxCOMPLEX);
+  mxArray *retval = new mxArray (interleaved, mxSINGLE_CLASS, 1, 1, mxCOMPLEX);
+
+  if (interleaved)
+    {
+      mxComplexSingle *pd
+        = static_cast<mxComplexSingle *> (retval->get_data ());
 
-  float *pr = static_cast<float *> (retval->get_data ());
-  float *pi = static_cast<float *> (retval->get_imag_data ());
+      pd[0].real = scalar.real ();
+      pd[0].imag = scalar.imag ();
+    }
+  else
+    {
+      mxSingle *pr = static_cast<mxSingle *> (retval->get_data ());
+      mxSingle *pi = static_cast<mxSingle *> (retval->get_imag_data ());
 
-  pr[0] = scalar.real ();
-  pi[0] = scalar.imag ();
+      pr[0] = scalar.real ();
+      pi[0] = scalar.imag ();
+    }
 
   return retval;
 }
--- a/libinterp/octave-value/ov-flt-complex.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-flt-complex.h	Tue Jul 07 19:40:20 2020 -0400
@@ -191,7 +191,7 @@
                      skip, flt_fmt);
   }
 
-  mxArray * as_mxArray (void) const;
+  mxArray * as_mxArray (bool interleaved) const;
 
   octave_value map (unary_mapper_t umap) const;
 
--- a/libinterp/octave-value/ov-flt-cx-mat.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-flt-cx-mat.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -676,21 +676,36 @@
 }
 
 mxArray *
-octave_float_complex_matrix::as_mxArray (void) const
+octave_float_complex_matrix::as_mxArray (bool interleaved) const
 {
-  mxArray *retval = new mxArray (mxSINGLE_CLASS, dims (), mxCOMPLEX);
-
-  float *pr = static_cast<float *> (retval->get_data ());
-  float *pi = static_cast<float *> (retval->get_imag_data ());
+  mxArray *retval = new mxArray (interleaved, mxSINGLE_CLASS, dims (),
+                                 mxCOMPLEX);
 
   mwSize nel = numel ();
 
-  const FloatComplex *p = matrix.data ();
+  const FloatComplex *pdata = matrix.data ();
+
+  if (interleaved)
+    {
+      mxComplexSingle *pd
+        = static_cast<mxComplexSingle *> (retval->get_data ());
 
-  for (mwIndex i = 0; i < nel; i++)
+      for (mwIndex i = 0; i < nel; i++)
+        {
+          pd[i].real = pdata[i].real ();
+          pd[i].imag = pdata[i].imag ();
+        }
+    }
+  else
     {
-      pr[i] = std::real (p[i]);
-      pi[i] = std::imag (p[i]);
+      mxSingle *pr = static_cast<mxSingle *> (retval->get_data ());
+      mxSingle *pi = static_cast<mxSingle *> (retval->get_imag_data ());
+
+      for (mwIndex i = 0; i < nel; i++)
+        {
+          pr[i] = pdata[i].real ();
+          pi[i] = pdata[i].imag ();
+        }
     }
 
   return retval;
--- a/libinterp/octave-value/ov-flt-cx-mat.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-flt-cx-mat.h	Tue Jul 07 19:40:20 2020 -0400
@@ -171,7 +171,7 @@
 
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
 
-  mxArray * as_mxArray (void) const;
+  mxArray * as_mxArray (bool interleaved) const;
 
   octave_value map (unary_mapper_t umap) const;
 
--- a/libinterp/octave-value/ov-flt-re-mat.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-flt-re-mat.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -717,18 +717,18 @@
 }
 
 mxArray *
-octave_float_matrix::as_mxArray (void) const
+octave_float_matrix::as_mxArray (bool interleaved) const
 {
-  mxArray *retval = new mxArray (mxSINGLE_CLASS, dims (), mxREAL);
+  mxArray *retval = new mxArray (interleaved, mxSINGLE_CLASS, dims (), mxREAL);
 
-  float *pr = static_cast<float *> (retval->get_data ());
+  mxSingle *pd = static_cast<mxSingle *> (retval->get_data ());
 
   mwSize nel = numel ();
 
-  const float *p = matrix.data ();
+  const float *pdata = matrix.data ();
 
   for (mwIndex i = 0; i < nel; i++)
-    pr[i] = p[i];
+    pd[i] = pdata[i];
 
   return retval;
 }
--- a/libinterp/octave-value/ov-flt-re-mat.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-flt-re-mat.h	Tue Jul 07 19:40:20 2020 -0400
@@ -217,7 +217,7 @@
   // You should not use it anywhere else.
   void * mex_get_data (void) const { return matrix.mex_get_data (); }
 
-  mxArray * as_mxArray (void) const;
+  mxArray * as_mxArray (bool interleaved) const;
 
   octave_value map (unary_mapper_t umap) const;
 
--- a/libinterp/octave-value/ov-intx.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-intx.h	Tue Jul 07 19:40:20 2020 -0400
@@ -315,19 +315,20 @@
   // You should not use it anywhere else.
   void * mex_get_data (void) const { return matrix.mex_get_data (); }
 
-  mxArray * as_mxArray (void) const
+  mxArray * as_mxArray (bool interleaved) const
   {
-    mxArray *retval = new mxArray (OCTAVE_INT_MX_CLASS, dims (), mxREAL);
+    mxArray *retval = new mxArray (interleaved, OCTAVE_INT_MX_CLASS, dims (),
+                                   mxREAL);
 
-    OCTAVE_INT_T::val_type *pr = static_cast<OCTAVE_INT_T::val_type *>
-                                 (retval->get_data ());
+    OCTAVE_INT_T::val_type *pd
+      = static_cast<OCTAVE_INT_T::val_type *> (retval->get_data ());
 
     mwSize nel = numel ();
 
-    const OCTAVE_INT_T *p = matrix.data ();
+    const OCTAVE_INT_T *pdata = matrix.data ();
 
     for (mwIndex i = 0; i < nel; i++)
-      pr[i] = p[i].value ();
+      pd[i] = pdata[i].value ();
 
     return retval;
   }
@@ -637,14 +638,15 @@
   // You should not use it anywhere else.
   void * mex_get_data (void) const { return scalar.mex_get_data (); }
 
-  mxArray * as_mxArray (void) const
+  mxArray * as_mxArray (bool interleaved) const
   {
-    mxArray *retval = new mxArray (OCTAVE_INT_MX_CLASS, 1, 1, mxREAL);
+    mxArray *retval = new mxArray (interleaved, OCTAVE_INT_MX_CLASS, 1, 1,
+                                   mxREAL);
 
-    OCTAVE_INT_T::val_type *pr = static_cast<OCTAVE_INT_T::val_type *>
-                                 (retval->get_data ());
+    OCTAVE_INT_T::val_type *pd
+      = static_cast<OCTAVE_INT_T::val_type *> (retval->get_data ());
 
-    pr[0] = scalar.value ();
+    pd[0] = scalar.value ();
 
     return retval;
   }
--- a/libinterp/octave-value/ov-java.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-java.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -37,6 +37,7 @@
 #endif
 
 #include <algorithm>
+#include <array>
 #include <fstream>
 #include <map>
 #include <string>
@@ -254,9 +255,7 @@
 
     void read_java_opts (const std::string& filename)
     {
-      std::string ascii_fname = sys::get_ASCII_filename (filename);
-
-      std::ifstream js (ascii_fname.c_str ());
+      std::ifstream js = sys::ifstream (filename.c_str ());
 
       if (! js.bad () && ! js.fail ())
         {
@@ -376,9 +375,7 @@
 {
   std::string classpath;
 
-  std::string ascii_fname = octave::sys::get_ASCII_filename (filepath);
-
-  std::ifstream fs (ascii_fname.c_str ());
+  std::ifstream fs = octave::sys::ifstream (filepath.c_str ());
 
   if (! fs.bad () && ! fs.fail ())
     {
@@ -517,16 +514,16 @@
   // This assumes that whatever architectures are installed are appropriate for
   // this machine
 #if defined (OCTAVE_USE_WINDOWS_API)
-  std::string subdirs[] = {"bin/client", "bin/server"};
+  const std::array<const std::string, 2> subdirs = {"bin/client", "bin/server"};
 #else
-  std::string subdirs[] = {"jre/lib/server", "jre/lib",
-                           "lib/client", "lib/server",
-                           "jre/lib/amd64/client", "jre/lib/amd64/server",
-                           "jre/lib/i386/client", "jre/lib/i386/server"
-                          };
+  const std::array<const std::string, 8> subdirs =
+    {"jre/lib/server", "jre/lib", "lib/client", "lib/server",
+     "jre/lib/amd64/client", "jre/lib/amd64/server",
+     "jre/lib/i386/client", "jre/lib/i386/server"
+    };
 #endif
 
-  for (size_t i = 0; i < sizeof (subdirs) / sizeof (subdirs[0]); i++)
+  for (size_t i = 0; i < subdirs.size (); i++)
     {
       std::string candidate = java_home_path + "/" + subdirs[i]
                               + "/" LIBJVM_FILE_NAME;
--- a/libinterp/octave-value/ov-lazy-idx.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-lazy-idx.h	Tue Jul 07 19:40:20 2020 -0400
@@ -241,9 +241,9 @@
     return make_value ().mex_get_data ();
   }
 
-  mxArray * as_mxArray (void) const
+  mxArray * as_mxArray (bool interleaved) const
   {
-    return make_value ().as_mxArray ();
+    return make_value ().as_mxArray (interleaved);
   }
 
   octave_value map (unary_mapper_t umap) const
--- a/libinterp/octave-value/ov-mex-fcn.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-mex-fcn.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -46,10 +46,11 @@
                                      "mex function", "mex function");
 
 octave_mex_function::octave_mex_function
-  (void *fptr, bool fmex, const octave::dynamic_library& shl,
+  (void *fptr, bool interleaved, bool fmex, const octave::dynamic_library& shl,
    const std::string& nm)
   : octave_function (nm), m_mex_fcn_ptr (fptr), m_exit_fcn_ptr (nullptr),
-    m_is_fmex (fmex), m_sh_lib (shl)
+    m_sh_lib (shl), m_interleaved (interleaved), m_is_fmex (fmex),
+    m_is_system_fcn_file (false)
 {
   mark_fcn_file_up_to_date (time_parsed ());
 
--- a/libinterp/octave-value/ov-mex-fcn.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-mex-fcn.h	Tue Jul 07 19:40:20 2020 -0400
@@ -52,10 +52,12 @@
 public:
 
   octave_mex_function (void)
-    : m_mex_fcn_ptr (), m_exit_fcn_ptr (), m_is_fmex (), m_sh_lib (),
-      m_time_checked (), m_is_system_fcn_file () { }
+    : m_mex_fcn_ptr (nullptr), m_exit_fcn_ptr (nullptr), m_sh_lib (),
+      m_time_checked (), m_interleaved (false), m_is_fmex (false),
+      m_is_system_fcn_file (false)
+  { }
 
-  octave_mex_function (void *fptr, bool fmex,
+  octave_mex_function (void *fptr, bool interleaved, bool fmex,
                        const octave::dynamic_library& shl,
                        const std::string& nm = "");
 
@@ -88,6 +90,8 @@
 
   bool is_mex_function (void) const { return true; }
 
+  bool use_interleaved_complex (void) const { return m_interleaved; }
+
   octave_value_list
   execute (octave::tree_evaluator& tw, int nargout = 0,
            const octave_value_list& args = octave_value_list ());
@@ -106,14 +110,16 @@
 
   void (*m_exit_fcn_ptr) (void);
 
-  bool m_is_fmex;
-
   octave::dynamic_library m_sh_lib;
 
   // The time the file was last checked to see if it needs to be
   // parsed again.
   mutable octave::sys::time m_time_checked;
 
+  bool m_interleaved;
+
+  bool m_is_fmex;
+
   // True if this function came from a file that is considered to be a
   // system function.  This affects whether we check the time stamp
   // on the file to see if it has changed.
--- a/libinterp/octave-value/ov-perm.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-perm.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -434,9 +434,9 @@
 }
 
 mxArray *
-octave_perm_matrix::as_mxArray (void) const
+octave_perm_matrix::as_mxArray (bool interleaved) const
 {
-  return to_dense ().as_mxArray ();
+  return to_dense ().as_mxArray (interleaved);
 }
 
 bool
--- a/libinterp/octave-value/ov-perm.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-perm.h	Tue Jul 07 19:40:20 2020 -0400
@@ -240,7 +240,7 @@
              oct_data_conv::data_type output_type, int skip,
              octave::mach_info::float_format flt_fmt) const;
 
-  mxArray * as_mxArray (void) const;
+  mxArray * as_mxArray (bool interleaved) const;
 
   bool print_as_scalar (void) const;
 
--- a/libinterp/octave-value/ov-range.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-range.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -771,20 +771,20 @@
 }
 
 mxArray *
-octave_range::as_mxArray (void) const
+octave_range::as_mxArray (bool interleaved) const
 {
-  mxArray *retval = new mxArray (mxDOUBLE_CLASS, dims (), mxREAL);
+  mxArray *retval = new mxArray (interleaved, mxDOUBLE_CLASS, dims (), mxREAL);
 
-  double *pr = static_cast<double *> (retval->get_data ());
+  mxDouble *pd = static_cast<mxDouble *> (retval->get_data ());
 
   mwSize nel = numel ();
 
   Matrix m = matrix_value ();
 
-  const double *p = m.data ();
+  const double *pdata = m.data ();
 
   for (mwSize i = 0; i < nel; i++)
-    pr[i] = p[i];
+    pd[i] = pdata[i];
 
   return retval;
 }
--- a/libinterp/octave-value/ov-range.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-range.h	Tue Jul 07 19:40:20 2020 -0400
@@ -306,7 +306,7 @@
     return os.write (matrix_value (), block_size, output_type, skip, flt_fmt);
   }
 
-  mxArray * as_mxArray (void) const;
+  mxArray * as_mxArray (bool interleaved) const;
 
   octave_value map (unary_mapper_t umap) const
   {
--- a/libinterp/octave-value/ov-re-mat.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-re-mat.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -844,18 +844,18 @@
 }
 
 mxArray *
-octave_matrix::as_mxArray (void) const
+octave_matrix::as_mxArray (bool interleaved) const
 {
-  mxArray *retval = new mxArray (mxDOUBLE_CLASS, dims (), mxREAL);
+  mxArray *retval = new mxArray (interleaved, mxDOUBLE_CLASS, dims (), mxREAL);
 
-  double *pr = static_cast<double *> (retval->get_data ());
+  mxDouble *pd = static_cast<mxDouble *> (retval->get_data ());
 
   mwSize nel = numel ();
 
-  const double *p = matrix.data ();
+  const double *pdata = matrix.data ();
 
   for (mwIndex i = 0; i < nel; i++)
-    pr[i] = p[i];
+    pd[i] = pdata[i];
 
   return retval;
 }
--- a/libinterp/octave-value/ov-re-mat.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-re-mat.h	Tue Jul 07 19:40:20 2020 -0400
@@ -241,7 +241,7 @@
   // You should not use it anywhere else.
   void * mex_get_data (void) const { return matrix.mex_get_data (); }
 
-  mxArray * as_mxArray (void) const;
+  mxArray * as_mxArray (bool interleaved) const;
 
   octave_value map (unary_mapper_t umap) const;
 
--- a/libinterp/octave-value/ov-re-sparse.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-re-sparse.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -861,24 +861,34 @@
 }
 
 mxArray *
-octave_sparse_matrix::as_mxArray (void) const
+octave_sparse_matrix::as_mxArray (bool interleaved) const
 {
   mwSize nz = nzmax ();
   mwSize nr = rows ();
   mwSize nc = columns ();
-  mxArray *retval = new mxArray (mxDOUBLE_CLASS, nr, nc, nz, mxREAL);
-  double *pr = static_cast<double *> (retval->get_data ());
+
+  mxArray *retval = new mxArray (interleaved, mxDOUBLE_CLASS, nr, nc, nz,
+                                 mxREAL);
+
+  mxDouble *pd = static_cast<mxDouble *> (retval->get_data ());
   mwIndex *ir = retval->get_ir ();
-  mwIndex *jc = retval->get_jc ();
+
+  const double *pdata = matrix.data ();
+  const octave_idx_type *pridx = matrix.ridx ();
 
   for (mwIndex i = 0; i < nz; i++)
     {
-      pr[i] = matrix.data (i);
-      ir[i] = matrix.ridx (i);
+      pd[i] = pdata[i];
+
+      ir[i] = pridx[i];
     }
 
+  mwIndex *jc = retval->get_jc ();
+
+  const octave_idx_type *pcidx = matrix.cidx ();
+
   for (mwIndex i = 0; i < nc + 1; i++)
-    jc[i] = matrix.cidx (i);
+    jc[i] = pcidx[i];
 
   return retval;
 }
--- a/libinterp/octave-value/ov-re-sparse.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-re-sparse.h	Tue Jul 07 19:40:20 2020 -0400
@@ -152,7 +152,7 @@
 
   bool load_hdf5 (octave_hdf5_id loc_id, const char *name);
 
-  mxArray * as_mxArray (void) const;
+  mxArray * as_mxArray (bool interleaved) const;
 
   octave_value map (unary_mapper_t umap) const;
 
--- a/libinterp/octave-value/ov-scalar.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-scalar.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -356,13 +356,13 @@
 }
 
 mxArray *
-octave_scalar::as_mxArray (void) const
+octave_scalar::as_mxArray (bool interleaved) const
 {
-  mxArray *retval = new mxArray (mxDOUBLE_CLASS, 1, 1, mxREAL);
+  mxArray *retval = new mxArray (interleaved, mxDOUBLE_CLASS, 1, 1, mxREAL);
 
-  double *pr = static_cast<double *> (retval->get_data ());
+  mxDouble *pd = static_cast<mxDouble *> (retval->get_data ());
 
-  pr[0] = scalar;
+  pd[0] = scalar;
 
   return retval;
 }
--- a/libinterp/octave-value/ov-scalar.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-scalar.h	Tue Jul 07 19:40:20 2020 -0400
@@ -269,7 +269,7 @@
                      skip, flt_fmt);
   }
 
-  mxArray * as_mxArray (void) const;
+  mxArray * as_mxArray (bool interleaved) const;
 
   octave_value map (unary_mapper_t umap) const;
 
--- a/libinterp/octave-value/ov-struct.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-struct.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -1011,7 +1011,7 @@
 }
 
 mxArray *
-octave_struct::as_mxArray (void) const
+octave_struct::as_mxArray (bool interleaved) const
 {
   int nf = nfields ();
   string_vector kv = map_keys ();
@@ -1021,7 +1021,7 @@
   for (int i = 0; i < nf; i++)
     f[i] = kv[i].c_str ();
 
-  mxArray *retval = new mxArray (dims (), nf, f);
+  mxArray *retval = new mxArray (interleaved, dims (), nf, f);
 
   mxArray **elts = static_cast<mxArray **> (retval->get_data ());
 
@@ -1037,7 +1037,7 @@
 
       mwIndex k = 0;
       for (mwIndex j = i; j < ntot; j += nf)
-        elts[j] = new mxArray (p[k++]);
+        elts[j] = new mxArray (interleaved, p[k++]);
     }
 
   return retval;
@@ -1629,7 +1629,7 @@
 }
 
 mxArray *
-octave_scalar_struct::as_mxArray (void) const
+octave_scalar_struct::as_mxArray (bool interleaved) const
 {
   int nf = nfields ();
   string_vector kv = map_keys ();
@@ -1639,7 +1639,7 @@
   for (int i = 0; i < nf; i++)
     f[i] = kv[i].c_str ();
 
-  mxArray *retval = new mxArray (dims (), nf, f);
+  mxArray *retval = new mxArray (interleaved, dims (), nf, f);
 
   mxArray **elts = static_cast<mxArray **> (retval->get_data ());
 
@@ -1655,7 +1655,7 @@
 
       mwIndex k = 0;
       for (mwIndex j = i; j < ntot; j += nf)
-        elts[j] = new mxArray (p[k++]);
+        elts[j] = new mxArray (interleaved, p[k++]);
     }
 
   return retval;
--- a/libinterp/octave-value/ov-struct.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov-struct.h	Tue Jul 07 19:40:20 2020 -0400
@@ -150,7 +150,7 @@
 
   bool load_hdf5 (octave_hdf5_id loc_id, const char *name);
 
-  mxArray * as_mxArray (void) const;
+  mxArray * as_mxArray (bool interleaved) const;
 
   octave_value
   fast_elem_extract (octave_idx_type n) const;
@@ -274,7 +274,7 @@
 
   bool load_hdf5 (octave_hdf5_id loc_id, const char *name);
 
-  mxArray * as_mxArray (void) const;
+  mxArray * as_mxArray (bool interleaved) const;
 
   bool fast_elem_insert_self (void *where, builtin_type_t btyp) const;
 
--- a/libinterp/octave-value/ov.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -2506,103 +2506,95 @@
 
   if (base.isobject () || increment.isobject () || limit.isobject ())
     {
-      std::string dispatch_type;
-
-      if (base.isobject ())
-        dispatch_type = base.class_name ();
-      else if (increment.is_defined () && increment.isobject ())
-        dispatch_type = increment.class_name ();
-      else
-        dispatch_type = limit.class_name ();
-
-      octave::symbol_table& symtab = octave::__get_symbol_table__ ("do_colon_op");
-
-      octave_value meth = symtab.find_method ("colon", dispatch_type);
-
-      if (! meth.is_defined ())
-        error ("colon method not defined for %s class", dispatch_type.c_str ());
-
-      octave_value_list args;
+      octave_value_list tmp1;
 
       if (increment.is_defined ())
         {
-          args(2) = limit;
-          args(1) = increment;
+          tmp1(2) = limit;
+          tmp1(1) = increment;
+          tmp1(0) = base;
         }
       else
-        args(1) = limit;
-
-      args(0) = base;
-
-      octave_value_list tmp = octave::feval (meth.function_value (), args, 1);
-
-      if (tmp.length () > 0)
-        retval = tmp(0);
+        {
+          tmp1(1) = limit;
+          tmp1(0) = base;
+        }
+
+      octave::interpreter& interp = octave::__get_interpreter__ ("do_colon_op");
+
+      octave::symbol_table& symtab = interp.get_symbol_table ();
+
+      octave_value fcn = symtab.find_function ("colon", tmp1);
+
+      if (fcn.is_defined ())
+        {
+          octave_value_list tmp2 = interp.feval (fcn, tmp1, 1);
+
+          return tmp2 (0);
+        }
     }
+
+  bool result_is_str = (base.is_string () && limit.is_string ());
+  bool dq_str = (base.is_dq_string () || limit.is_dq_string ());
+
+  if (base.numel () > 1 || limit.numel () > 1
+      || (increment.is_defined () && increment.numel () > 1))
+    warning_with_id ("Octave:colon-nonscalar-argument",
+                     "colon arguments should be scalars");
+
+  if (base.iscomplex () || limit.iscomplex ()
+      || (increment.is_defined () && increment.iscomplex ()))
+    warning_with_id ("Octave:colon-complex-argument",
+                     "imaginary part of complex colon arguments is ignored");
+
+  Matrix m_base, m_limit, m_increment;
+
+  try
+    {
+      m_base = base.matrix_value (true);
+    }
+  catch (octave::execution_exception& e)
+    {
+      error (e, "invalid base value in colon expression");
+    }
+
+  try
+    {
+      m_limit = limit.matrix_value (true);
+    }
+  catch (octave::execution_exception& e)
+    {
+      error (e, "invalid limit value in colon expression");
+    }
+
+  try
+    {
+      m_increment = (increment.is_defined ()
+                     ? increment.matrix_value (true)
+                     : Matrix (1, 1, 1.0));
+    }
+  catch (octave::execution_exception& e)
+    {
+      error (e, "invalid increment value in colon expression");
+    }
+
+  bool base_empty = m_base.isempty ();
+  bool limit_empty = m_limit.isempty ();
+  bool increment_empty = m_increment.isempty ();
+
+  if (base_empty || limit_empty || increment_empty)
+    retval = Range ();
   else
     {
-      bool result_is_str = (base.is_string () && limit.is_string ());
-      bool dq_str = (base.is_dq_string () || limit.is_dq_string ());
-
-      if (base.numel () > 1 || limit.numel () > 1
-          || (increment.is_defined () && increment.numel () > 1))
-        warning_with_id ("Octave:colon-nonscalar-argument",
-                         "colon arguments should be scalars");
-
-      if (base.iscomplex () || limit.iscomplex ()
-          || (increment.is_defined () && increment.iscomplex ()))
-        warning_with_id ("Octave:colon-complex-argument",
-                         "imaginary part of complex colon arguments is ignored");
-
-      Matrix m_base, m_limit, m_increment;
-
-      try
-        {
-          m_base = base.matrix_value (true);
-        }
-      catch (octave::execution_exception& e)
-        {
-          error (e, "invalid base value in colon expression");
-        }
-
-      try
-        {
-          m_limit = limit.matrix_value (true);
-        }
-      catch (octave::execution_exception& e)
-        {
-          error (e, "invalid limit value in colon expression");
-        }
-
-      try
-        {
-          m_increment = (increment.is_defined ()
-                         ? increment.matrix_value (true)
-                         : Matrix (1, 1, 1.0));
-        }
-      catch (octave::execution_exception& e)
-        {
-          error (e, "invalid increment value in colon expression");
-        }
-
-      bool base_empty = m_base.isempty ();
-      bool limit_empty = m_limit.isempty ();
-      bool increment_empty = m_increment.isempty ();
-
-      if (base_empty || limit_empty || increment_empty)
-        retval = Range ();
-      else
-        {
-          Range r (m_base(0), m_limit(0), m_increment(0));
-
-          // For compatibility with Matlab, don't allow the range used in
-          // a FOR loop expression to be converted to a Matrix.
-
-          retval = octave_value (r, is_for_cmd_expr);
-
-          if (result_is_str)
-            retval = (retval.convert_to_str (false, true, dq_str ? '"' : '\''));
-        }
+      Range r (m_base(0), m_limit(0), m_increment(0));
+
+      // For compatibility with Matlab, don't allow the range used in
+      // a FOR loop expression to be converted to a Matrix.
+
+      retval = octave_value (r, is_for_cmd_expr);
+
+      if (result_is_str)
+        retval = (retval.convert_to_str (false, true, dq_str ? '"' : '\''));
     }
 
   return retval;
@@ -2618,6 +2610,75 @@
   rep->print_info (os, prefix + ' ');
 }
 
+void *
+octave_value::mex_get_data (mxClassID class_id, mxComplexity complexity) const
+{
+  // If class_id is set to mxUNKNOWN_CLASS, return data for any type.
+  // Otherwise, require that REP matches the requested type and
+  // complexity.
+
+  if (class_id != mxUNKNOWN_CLASS)
+    {
+      bool type_ok = false;
+
+      switch (class_id)
+        {
+        case mxDOUBLE_CLASS:
+          type_ok = is_double_type ();
+          break;
+
+        case mxSINGLE_CLASS:
+          type_ok = is_single_type ();
+          break;
+
+        case mxINT8_CLASS:
+          type_ok = is_int8_type ();
+          break;
+
+        case mxINT16_CLASS:
+          type_ok = is_int16_type ();
+          break;
+
+        case mxINT32_CLASS:
+          type_ok = is_int32_type ();
+          break;
+
+        case mxINT64_CLASS:
+          type_ok = is_int64_type ();
+          break;
+
+        case mxUINT8_CLASS:
+          type_ok = is_uint8_type ();
+          break;
+
+        case mxUINT16_CLASS:
+          type_ok = is_uint16_type ();
+          break;
+
+        case mxUINT32_CLASS:
+          type_ok = is_uint32_type ();
+          break;
+
+        case mxUINT64_CLASS:
+          type_ok = is_uint64_type ();
+          break;
+
+        default:
+          // We only expect to see numeric types explicitly requested.
+          error ("mex_get_data: unexpected type requested");
+          break;
+        }
+
+      if (! type_ok)
+        error ("mex_get_data: type mismatch");
+
+      if (complexity == mxCOMPLEX && ! iscomplex ())
+        error ("mex_get_data: objectis not complex as requested");
+    }
+
+  return rep->mex_get_data ();
+}
+
 OCTAVE_NORETURN static void
 err_unary_op (const std::string& on, const std::string& tn)
 {
--- a/libinterp/octave-value/ov.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/octave-value/ov.h	Tue Jul 07 19:40:20 2020 -0400
@@ -59,6 +59,8 @@
 class octave_fcn_handle;
 class octave_value_list;
 
+#include "mxtypes.h"
+
 #include "oct-stream.h"
 #include "ov-base.h"
 
@@ -1322,13 +1324,15 @@
 
   // Unsafe.  These functions exist to support the MEX interface.
   // You should not use them anywhere else.
-  void * mex_get_data (void) const { return rep->mex_get_data (); }
+  void * mex_get_data (mxClassID class_id = mxUNKNOWN_CLASS,
+                       mxComplexity complexity = mxREAL) const;
 
   octave_idx_type * mex_get_ir (void) const { return rep->mex_get_ir (); }
 
   octave_idx_type * mex_get_jc (void) const { return rep->mex_get_jc (); }
 
-  mxArray * as_mxArray (void) const { return rep->as_mxArray (); }
+  mxArray * as_mxArray (bool interleaved = false) const
+  { return rep->as_mxArray (interleaved); }
 
   octave_value diag (octave_idx_type k = 0) const
   { return rep->diag (k); }
--- a/libinterp/op-kw-docs	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/op-kw-docs	Tue Jul 07 19:40:20 2020 -0400
@@ -572,6 +572,13 @@
 Mark the end of a properties block in a classdef definition.
 @seealso{properties}
 @end deftypefn
+endspmd
+@c libinterp/parse-tree/oct-parse.yy
+-*- texinfo -*-
+@deftypefn {} {} endparfor
+Mark the end of an spmd block.  See @code{spmd} for an example.
+@seealso{spmd, parfor}
+@end deftypefn
 endswitch
 @c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
@@ -732,6 +739,31 @@
 Return from a function.
 @seealso{function}
 @end deftypefn
+spmd
+@c libinterp/parse-tree/oct-parse.yy
+-*- texinfo -*-
+@deftypefn  {} {} spmd
+@deftypefnx {} {} spmd (@var{n})
+@deftypefnx {} {} spmd (@var{m}, @var{n})
+Begin a block of statements which may execute in parallel across multiple
+workers.
+
+If Octave has a parallel processing pool enabled, the block of code will be
+executed in parallel across all of the pool's workers.  Otherwise, @code{spmd}
+has no effect and the statements are processed as normal code by the main
+Octave interpreter.
+
+If called with one additional argument @var{n} then use exactly @var{n} workers
+from the pool.  If called with two arguments @var{m}, @var{n} then use a
+minimum of @var{m} workers and a maximum of @var{n} workers from the parallel
+pool.
+
+@strong{Warning:} parallel processing pools are currently unimplemented in
+Octave; @code{spmd} currently does nothing, but is included to avoid breaking
+existing @sc{matlab} code.
+
+@seealso{parfor}
+@end deftypefn
 switch
 @c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
--- a/libinterp/operators/op-range.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/operators/op-range.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -31,63 +31,13 @@
 #include "ovl.h"
 #include "ov.h"
 #include "ov-range.h"
-#include "ov-ch-mat.h"
-#include "ov-scalar.h"
 #include "ov-re-mat.h"
-#include "ov-flt-re-mat.h"
-#include "ov-complex.h"
-#include "ov-cx-mat.h"
-#include "ov-bool.h"
-#include "ov-bool-mat.h"
 #include "ov-typeinfo.h"
 #include "ov-null-mat.h"
 #include "ops.h"
-#include "xpow.h"
 
-// range unary ops.
-
-DEFUNOP (not, range)
-{
-  const octave_range& v = dynamic_cast<const octave_range&> (a);
-
-  return octave_value (! v.matrix_value ());
-}
-
+// Allow +RNG_VAL to avoid conversion to array.
 DEFUNOP_OP (uplus, range, /* no-op */)
-DEFUNOP_OP (uminus, range, -)
-
-DEFUNOP (transpose, range)
-{
-  const octave_range& v = dynamic_cast<const octave_range&> (a);
-
-  return octave_value (v.matrix_value ().transpose ());
-}
-
-DEFBINOP_OP (addrs, range, scalar, +)
-DEFBINOP_OP (addsr, scalar, range, +)
-DEFBINOP_OP (subrs, range, scalar, -)
-DEFBINOP_OP (subsr, scalar, range, -)
-DEFBINOP_OP (mulrs, range, scalar, *)
-DEFBINOP_OP (mulsr, scalar, range, *)
-
-DEFBINOP_FN (el_powsr, scalar, range, elem_xpow)
-DEFBINOP_FN (el_powcsr, complex, range, elem_xpow)
-
-DEFNDCATOP_FN (r_r, range, range, array, array, concat)
-DEFNDCATOP_FN (r_s, range, scalar, array, array, concat)
-DEFNDCATOP_FN (r_m, range, matrix, array, array, concat)
-DEFNDCATOP_FN (r_cs, range, complex, array, complex_array, concat)
-DEFNDCATOP_FN (r_cm, range, complex_matrix, array, complex_array, concat)
-DEFNDCATOP_FN (r_b, range, bool, array, array, concat)
-DEFNDCATOP_FN (r_bm, range, bool_matrix, array, array, concat)
-DEFNDCATOP_FN (r_chm, range, char_matrix, array, char_array, concat)
-DEFNDCATOP_FN (s_r, scalar, range, array, array, concat)
-DEFNDCATOP_FN (m_r, matrix, range, array, array, concat)
-DEFNDCATOP_FN (cs_r, complex, range, complex_array, array, concat)
-DEFNDCATOP_FN (cm_r, complex_matrix, range, complex_array, array, concat)
-DEFNDCATOP_FN (b_r, bool, range, array, array, concat)
-DEFNDCATOP_FN (bm_r, bool_matrix, range, array, array, concat)
-DEFNDCATOP_FN (chm_r, char_matrix, range, char_array, array, concat)
 
 CONVDECL (range_to_matrix)
 {
@@ -99,39 +49,7 @@
 void
 install_range_ops (octave::type_info& ti)
 {
-  INSTALL_UNOP_TI (ti, op_not, octave_range, not);
   INSTALL_UNOP_TI (ti, op_uplus, octave_range, uplus);
-  INSTALL_UNOP_TI (ti, op_uminus, octave_range, uminus);
-  INSTALL_UNOP_TI (ti, op_transpose, octave_range, transpose);
-  INSTALL_UNOP_TI (ti, op_hermitian, octave_range, transpose);
-
-  INSTALL_BINOP_TI (ti, op_add, octave_range, octave_scalar, addrs);
-  INSTALL_BINOP_TI (ti, op_add, octave_scalar, octave_range, addsr);
-  INSTALL_BINOP_TI (ti, op_sub, octave_range, octave_scalar, subrs);
-  INSTALL_BINOP_TI (ti, op_sub, octave_scalar, octave_range, subsr);
-  INSTALL_BINOP_TI (ti, op_mul, octave_range, octave_scalar, mulrs);
-  INSTALL_BINOP_TI (ti, op_mul, octave_scalar, octave_range, mulsr);
-
-  INSTALL_BINOP_TI (ti, op_el_mul, octave_range, octave_scalar, mulrs);
-  INSTALL_BINOP_TI (ti, op_el_mul, octave_scalar, octave_range, mulsr);
-  INSTALL_BINOP_TI (ti, op_el_pow, octave_scalar, octave_range, el_powsr);
-  INSTALL_BINOP_TI (ti, op_el_pow, octave_complex, octave_range, el_powcsr);
-
-  INSTALL_CATOP_TI (ti, octave_range, octave_range, r_r);
-  INSTALL_CATOP_TI (ti, octave_range, octave_scalar, r_s);
-  INSTALL_CATOP_TI (ti, octave_range, octave_matrix, r_m);
-  INSTALL_CATOP_TI (ti, octave_range, octave_complex, r_cs);
-  INSTALL_CATOP_TI (ti, octave_range, octave_complex_matrix, r_cm);
-  INSTALL_CATOP_TI (ti, octave_range, octave_bool, r_b);
-  INSTALL_CATOP_TI (ti, octave_range, octave_bool_matrix, r_bm);
-  INSTALL_CATOP_TI (ti, octave_range, octave_char_matrix, r_chm);
-  INSTALL_CATOP_TI (ti, octave_scalar, octave_range, s_r);
-  INSTALL_CATOP_TI (ti, octave_matrix, octave_range, m_r);
-  INSTALL_CATOP_TI (ti, octave_complex, octave_range, cs_r);
-  INSTALL_CATOP_TI (ti, octave_complex_matrix, octave_range, cm_r);
-  INSTALL_CATOP_TI (ti, octave_bool, octave_range, b_r);
-  INSTALL_CATOP_TI (ti, octave_bool_matrix, octave_range, bm_r);
-  INSTALL_CATOP_TI (ti, octave_char_matrix, octave_range, chm_r);
 
   // FIXME: this would be unnecessary if
   // octave_base_value::numeric_assign always tried converting lhs
@@ -141,7 +59,7 @@
   INSTALL_ASSIGNCONV_TI (ti, octave_range, octave_null_str, octave_matrix);
   INSTALL_ASSIGNCONV_TI (ti, octave_range, octave_null_sq_str, octave_matrix);
 
-  // However, this should probably be here just in case we need it.
+  // Hmm, this one also seems to be needed.
 
   INSTALL_WIDENOP_TI (ti, octave_range, octave_matrix, range_to_matrix);
 }
--- a/libinterp/parse-tree/bp-table.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/parse-tree/bp-table.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -997,12 +997,4 @@
 
     return retval;
   }
-
-  octave_user_code *
-  get_user_code (const std::string& fname)
-  {
-    tree_evaluator& tw = __get_evaluator__ ("get_user_code");
-
-    return tw.get_user_code (fname);
-  }
 }
--- a/libinterp/parse-tree/bp-table.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/parse-tree/bp-table.h	Tue Jul 07 19:40:20 2020 -0400
@@ -164,9 +164,6 @@
     intmap remove_all_breakpoints_in_file_1 (octave_user_code *fcn,
                                              const std::string& fname);
   };
-
-  OCTAVE_DEPRECATED (5, "use 'octave::get_user_code' instead")
-  extern octave_user_code * get_user_code (const std::string& fname = "");
 }
 
 #endif
--- a/libinterp/parse-tree/lex.ll	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/parse-tree/lex.ll	Tue Jul 07 19:40:20 2020 -0400
@@ -2763,7 +2763,6 @@
         m_at_beginning_of_statement = true;
         break;
 
-
       case for_kw:
       case parfor_kw:
       case while_kw:
@@ -2844,6 +2843,15 @@
           }
         break;
 
+      case spmd_kw:
+        m_at_beginning_of_statement = true;
+        break;
+
+      case endspmd_kw:
+        tok_val = new token (endspmd_kw, token::spmd_end, m_tok_beg, m_tok_end);
+        m_at_beginning_of_statement = true;
+        break;
+
       case magic_file_kw:
         {
           if ((m_reading_fcn_file || m_reading_script_file
--- a/libinterp/parse-tree/module.mk	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/parse-tree/module.mk	Tue Jul 07 19:40:20 2020 -0400
@@ -38,6 +38,7 @@
   %reldir%/pt-misc.h \
   %reldir%/pt-pr-code.h \
   %reldir%/pt-select.h \
+  %reldir%/pt-spmd.h \
   %reldir%/pt-stmt.h \
   %reldir%/pt-tm-const.h \
   %reldir%/pt-unop.h \
@@ -87,6 +88,7 @@
   %reldir%/pt-misc.cc \
   %reldir%/pt-pr-code.cc \
   %reldir%/pt-select.cc \
+  %reldir%/pt-spmd.cc \
   %reldir%/pt-stmt.cc \
   %reldir%/pt-tm-const.cc \
   %reldir%/pt-unop.cc \
--- a/libinterp/parse-tree/oct-parse.yy	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/parse-tree/oct-parse.yy	Tue Jul 07 19:40:20 2020 -0400
@@ -205,6 +205,7 @@
 %token <tok_val> END
 %token <tok_val> DQ_STRING SQ_STRING
 %token <tok_val> FOR PARFOR WHILE DO UNTIL
+%token <tok_val> SPMD
 %token <tok_val> IF ELSEIF ELSE
 %token <tok_val> SWITCH CASE OTHERWISE
 %token <tok_val> BREAK CONTINUE FUNC_RET
@@ -253,7 +254,7 @@
 %type <tree_parameter_list_type> param_list1 param_list2
 %type <tree_parameter_list_type> return_list return_list1
 %type <tree_command_type> command select_command loop_command
-%type <tree_command_type> jump_command except_command
+%type <tree_command_type> jump_command spmd_command except_command
 %type <tree_function_def_type> function
 %type <tree_classdef_type> classdef
 %type <tree_command_type> file
@@ -1052,6 +1053,8 @@
                   { $$ = $1; }
                 | jump_command
                   { $$ = $1; }
+                | spmd_command
+                  { $$ = $1; }
                 | except_command
                   { $$ = $1; }
                 | function
@@ -1322,6 +1325,25 @@
                   { $$ = parser.make_return_command ($1); }
                 ;
 
+// =======================
+// Parallel execution pool
+// =======================
+
+spmd_command    : SPMD stash_comment opt_sep opt_list END
+                  {
+                    YYUSE ($3);
+
+                    octave::comment_list *lc = $2;
+                    octave::comment_list *tc = lexer.get_comment ();
+
+                    if (! ($$ = parser.make_spmd_command ($1, $4, $5, lc, tc)))
+                      {
+                        // make_spmd_command deleted $4, LC, and TC.
+                        YYABORT;
+                      }
+                  }
+                ;
+
 // ==========
 // Exceptions
 // ==========
@@ -2455,6 +2477,10 @@
         retval = "endproperties";
         break;
 
+      case token::spmd_end:
+        retval = "endspmd";
+        break;
+
       case token::switch_end:
         retval = "endswitch";
         break;
@@ -3218,6 +3244,34 @@
     return new tree_return_command (l, c);
   }
 
+  // Build an spmd command.
+
+  tree_spmd_command *
+  base_parser::make_spmd_command (token *spmd_tok, tree_statement_list *body,
+                                  token *end_tok, comment_list *lc,
+                                  comment_list *tc)
+  {
+    tree_spmd_command *retval = nullptr;
+
+    if (end_token_ok (end_tok, token::spmd_end))
+      {
+        int l = spmd_tok->line ();
+        int c = spmd_tok->column ();
+
+        retval = new tree_spmd_command (body, lc, tc, l, c);
+      }
+    else
+      {
+        delete body;
+        delete lc;
+        delete tc;
+
+        end_token_error (end_tok, token::spmd_end);
+      }
+
+    return retval;
+  }
+
   // Start an if command.
 
   tree_if_command_list *
@@ -4648,9 +4702,7 @@
   {
     // NAME should be an absolute file name and the file should exist.
 
-    std::string ascii_fname = sys::get_ASCII_filename (name);
-
-    std::ifstream fs (ascii_fname.c_str (), std::ios::in);
+    std::ifstream fs = sys::ifstream (name.c_str (), std::ios::in);
 
     std::string text;
 
@@ -4911,7 +4963,20 @@
     FILE *ffile = nullptr;
 
     if (! full_file.empty ())
+    {
+      // Check that m-file is not overly large which can segfault interpreter.
+      const int max_file_size = 512 * 1024 * 1024;  // 512 MB
+      sys::file_stat fs (full_file);
+
+      if (fs && fs.size () > max_file_size)
+        {
+          error ("file '%s' is too large, > 512 MB", full_file.c_str ());
+
+          return octave_value ();
+        }
+
       ffile = sys::fopen (full_file, "rb");
+    }
 
     if (! ffile)
       {
@@ -5486,23 +5551,6 @@
 
 namespace octave
 {
-  octave_value_list
-  eval_string (const std::string& eval_str, bool silent,
-               int& parse_status, int nargout)
-  {
-    interpreter& interp = __get_interpreter__ ("eval_string");
-
-    return interp.eval_string (eval_str, silent, parse_status, nargout);
-  }
-
-  octave_value
-  eval_string (const std::string& eval_str, bool silent, int& parse_status)
-  {
-    interpreter& interp = __get_interpreter__ ("eval_string");
-
-    return interp.eval_string (eval_str, silent, parse_status);
-  }
-
   void
   cleanup_statement_list (tree_statement_list **lst)
   {
--- a/libinterp/parse-tree/octave.gperf	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/parse-tree/octave.gperf	Tue Jul 07 19:40:20 2020 -0400
@@ -51,6 +51,7 @@
   endmethods_kw,
   endparfor_kw,
   endproperties_kw,
+  endspmd_kw,
   endswitch_kw,
   endwhile_kw,
   enumeration_kw,
@@ -69,6 +70,7 @@
   properties_kw,
   return_kw,
   set_kw,
+  spmd_kw,
   switch_kw,
   try_kw,
   until_kw,
@@ -102,6 +104,7 @@
 endmethods, END, endmethods_kw
 endparfor, END, endparfor_kw
 endproperties, END, endproperties_kw
+endspmd, END, endspmd_kw
 endswitch, END, endswitch_kw
 endwhile, END, endwhile_kw
 enumeration, ENUMERATION, enumeration_kw
@@ -118,6 +121,7 @@
 properties, PROPERTIES, properties_kw
 return, FUNC_RET, return_kw
 set, SET, set_kw
+spmd, SPMD, spmd_kw
 switch, SWITCH, switch_kw
 try, TRY, try_kw
 until, UNTIL, until_kw
--- a/libinterp/parse-tree/parse.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/parse-tree/parse.h	Tue Jul 07 19:40:20 2020 -0400
@@ -81,6 +81,7 @@
   class tree_matrix;
   class tree_matrix;
   class tree_parameter_list;
+  class tree_spmd_command;
   class tree_statement;
   class tree_statement_list;
   class tree_statement_listtree_statement;
@@ -282,6 +283,12 @@
     // Build a return command.
     tree_command * make_return_command (token *return_tok);
 
+    // Build an spmd command.
+
+    tree_spmd_command *
+    make_spmd_command (token *spmd_tok, tree_statement_list *body,
+                       token *end_tok, comment_list *lc, comment_list *tc);
+
     // Start an if command.
     tree_if_command_list *
     start_if_command (tree_expression *expr, tree_statement_list *list);
@@ -690,14 +697,6 @@
   extern OCTINTERP_API octave_value_list
   feval (const octave_value_list& args, int nargout = 0);
 
-  OCTAVE_DEPRECATED (5, "use 'octave::interpreter::eval_string' instead")
-  extern OCTINTERP_API octave_value_list
-  eval_string (const std::string&, bool silent, int& parse_status, int nargout);
-
-  OCTAVE_DEPRECATED (5, "use 'octave::interpreter::eval_string' instead")
-  extern OCTINTERP_API octave_value
-  eval_string (const std::string&, bool silent, int& parse_status);
-
   extern OCTINTERP_API void
   cleanup_statement_list (tree_statement_list **lst);
 }
--- a/libinterp/parse-tree/pt-all.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/parse-tree/pt-all.h	Tue Jul 07 19:40:20 2020 -0400
@@ -52,6 +52,7 @@
 #include "pt-misc.h"
 #include "pt-pr-code.h"
 #include "pt-select.h"
+#include "pt-spmd.h"
 #include "pt-stmt.h"
 #include "pt-unop.h"
 #include "pt-pr-code.h"
--- a/libinterp/parse-tree/pt-arg-list.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/parse-tree/pt-arg-list.h	Tue Jul 07 19:40:20 2020 -0400
@@ -128,10 +128,4 @@
   };
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-// tree_argument_list is derived from a template.
-
 #endif
-
-#endif
--- a/libinterp/parse-tree/pt-classdef.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/parse-tree/pt-classdef.h	Tue Jul 07 19:40:20 2020 -0400
@@ -852,10 +852,4 @@
   };
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-// Hmm, a lot of these are templates, so not sure how to typedef them.
-
 #endif
-
-#endif
--- a/libinterp/parse-tree/pt-colon.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/parse-tree/pt-colon.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -57,52 +57,22 @@
     if (! m_base || ! m_limit)
       return val;
 
-    octave_value ov_base = m_base->evaluate (tw);
-
-    octave_value ov_limit = m_limit->evaluate (tw);
-
-    if (ov_base.isobject () || ov_limit.isobject ())
-      {
-        octave_value_list tmp1;
-
-        if (m_increment)
-          {
-            octave_value ov_increment = m_increment->evaluate (tw);
+    octave_value ov_base;
+    octave_value ov_increment;
+    octave_value ov_limit;
 
-            tmp1(2) = ov_limit;
-            tmp1(1) = ov_increment;
-            tmp1(0) = ov_base;
-          }
-        else
-          {
-            tmp1(1) = ov_limit;
-            tmp1(0) = ov_base;
-          }
-
-        interpreter& interp = tw.get_interpreter ();
-
-        symbol_table& symtab = interp.get_symbol_table ();
-
-        octave_value fcn = symtab.find_function ("colon", tmp1);
-
-        if (! fcn.is_defined ())
-          error ("can not find overloaded colon function");
-
-        octave_value_list tmp2 = feval (fcn, tmp1, 1);
-
-        val = tmp2 (0);
+    if (m_increment)
+      {
+        ov_base = m_base->evaluate (tw);
+        ov_increment = m_increment->evaluate (tw);
+        ov_limit = m_limit->evaluate (tw);
       }
     else
       {
-        octave_value ov_increment = 1.0;
-
-        if (m_increment)
-          ov_increment = m_increment->evaluate (tw);
-
-        val = do_colon_op (ov_base, ov_increment, ov_limit,
-                           is_for_cmd_expr ());
+        ov_base = m_base->evaluate (tw);
+        ov_limit = m_limit->evaluate (tw);
       }
 
-    return val;
+    return do_colon_op (ov_base, ov_increment, ov_limit, is_for_cmd_expr ());
   }
 }
--- a/libinterp/parse-tree/pt-eval.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/parse-tree/pt-eval.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -2694,6 +2694,16 @@
       }
   }
 
+  void tree_evaluator::visit_spmd_command (tree_spmd_command& cmd)
+  {
+    // For now, we just execute the commands serially.
+
+    tree_statement_list *body = cmd.body ();
+
+    if (body)
+      body->accept (*this);
+  }
+
   void
   tree_evaluator::visit_octave_user_script (octave_user_script&)
   {
--- a/libinterp/parse-tree/pt-eval.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/parse-tree/pt-eval.h	Tue Jul 07 19:40:20 2020 -0400
@@ -202,6 +202,8 @@
 
     void visit_complex_for_command (tree_complex_for_command&);
 
+    void visit_spmd_command (tree_spmd_command&);
+
     void visit_octave_user_script (octave_user_script&);
 
     octave_value_list
--- a/libinterp/parse-tree/pt-misc.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/parse-tree/pt-misc.h	Tue Jul 07 19:40:20 2020 -0400
@@ -115,10 +115,4 @@
   };
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-// tree_parameter_list is derived from a template.
-
 #endif
-
-#endif
--- a/libinterp/parse-tree/pt-pr-code.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/parse-tree/pt-pr-code.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -293,6 +293,35 @@
   }
 
   void
+  tree_print_code::visit_spmd_command (tree_spmd_command& cmd)
+  {
+    print_comment_list (cmd.leading_comment ());
+
+    indent ();
+
+    m_os << "spmd";
+
+    newline ();
+
+    tree_statement_list *list = cmd.body ();
+
+    if (list)
+      {
+        increment_indent_level ();
+
+        list->accept (*this);
+
+        decrement_indent_level ();
+      }
+
+    print_indented_comment (cmd.trailing_comment ());
+
+    indent ();
+
+    m_os << "endspmd";
+  }
+
+  void
   tree_print_code::visit_octave_user_script (octave_user_script& fcn)
   {
     reset ();
--- a/libinterp/parse-tree/pt-pr-code.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/parse-tree/pt-pr-code.h	Tue Jul 07 19:40:20 2020 -0400
@@ -88,6 +88,8 @@
 
     void visit_complex_for_command (tree_complex_for_command&);
 
+    void visit_spmd_command (tree_spmd_command&);
+
     void visit_octave_user_script (octave_user_script&);
 
     void visit_octave_user_function (octave_user_function&);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/parse-tree/pt-spmd.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -0,0 +1,42 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2020 The Octave Project Developers
+//
+// See the file COPYRIGHT.md in the top-level directory of this
+// distribution or <https://octave.org/copyright/>.
+//
+// This file is part of Octave.
+//
+// Octave is free software: you can 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
+// <https://www.gnu.org/licenses/>.
+//
+////////////////////////////////////////////////////////////////////////
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#include "comment-list.h"
+#include "pt-spmd.h"
+#include "pt-stmt.h"
+
+namespace octave
+{
+  tree_spmd_command::~tree_spmd_command (void)
+  {
+    delete m_body;
+    delete m_lead_comm;
+    delete m_trail_comm;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/parse-tree/pt-spmd.h	Tue Jul 07 19:40:20 2020 -0400
@@ -0,0 +1,83 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2020 The Octave Project Developers
+//
+// See the file COPYRIGHT.md in the top-level directory of this
+// distribution or <https://octave.org/copyright/>.
+//
+// This file is part of Octave.
+//
+// Octave is free software: you can 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
+// <https://www.gnu.org/licenses/>.
+//
+////////////////////////////////////////////////////////////////////////
+
+#if ! defined (octave_pt_spmd_command_h)
+#define octave_pt_spmd_command_h 1
+
+#include "octave-config.h"
+
+#include "base-list.h"
+#include "pt-cmd.h"
+#include "pt-walk.h"
+
+namespace octave
+{
+  class tree_comment_list;
+  class tree_statement_list;
+
+  // Spmd.
+
+  class tree_spmd_command : public tree_command
+  {
+  public:
+
+    tree_spmd_command (tree_statement_list *body, comment_list *lc,
+                       comment_list *tc, int l = -1, int c = -1)
+      : tree_command (l, c), m_body (body), m_lead_comm (lc), m_trail_comm (tc)
+    { }
+
+    // No copying!
+
+    tree_spmd_command (const tree_spmd_command&) = delete;
+
+    tree_spmd_command& operator = (const tree_spmd_command&) = delete;
+
+    ~tree_spmd_command (void);
+
+    tree_statement_list * body (void) { return m_body; }
+
+    comment_list * leading_comment (void) { return m_lead_comm; }
+
+    comment_list * trailing_comment (void) { return m_trail_comm; }
+
+    void accept (tree_walker& tw)
+    {
+      tw.visit_spmd_command (*this);
+    }
+
+  private:
+
+    // List of commands.
+    tree_statement_list *m_body;
+
+    // Comment preceding SPMD token.
+    comment_list *m_lead_comm;
+
+    // Comment preceding ENDSPMD token.
+    comment_list *m_trail_comm;
+  };
+}
+
+#endif
--- a/libinterp/parse-tree/pt-walk.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/parse-tree/pt-walk.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -174,6 +174,14 @@
       list->accept (*this);
   }
 
+  void tree_walker::visit_spmd_command (tree_spmd_command& cmd)
+  {
+    tree_statement_list *body = cmd.body ();
+
+    if (body)
+      body->accept (*this);
+  }
+
   void tree_walker::visit_octave_user_script (octave_user_script& fcn)
   {
     tree_statement_list *cmd_list = fcn.body ();
--- a/libinterp/parse-tree/pt-walk.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/parse-tree/pt-walk.h	Tue Jul 07 19:40:20 2020 -0400
@@ -53,6 +53,7 @@
   class tree_decl_elt;
   class tree_simple_for_command;
   class tree_complex_for_command;
+  class tree_spmd_command;
   class tree_function_def;
   class tree_identifier;
   class tree_if_clause;
@@ -142,6 +143,8 @@
 
     virtual void visit_complex_for_command (tree_complex_for_command&);
 
+    virtual void visit_spmd_command (tree_spmd_command&);
+
     virtual void visit_octave_user_script (octave_user_script&);
 
     virtual void visit_octave_user_function (octave_user_function&);
--- a/libinterp/parse-tree/token.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/libinterp/parse-tree/token.h	Tue Jul 07 19:40:20 2020 -0400
@@ -65,6 +65,7 @@
       switch_end,
       try_catch_end,
       unwind_protect_end,
+      spmd_end,
       while_end,
     };
 
@@ -123,12 +124,6 @@
       return m_type_tag == keyword_token || m_type_tag == ettype_token;
     }
 
-    OCTAVE_DEPRECATED (5, "use 'octave::iskeyword' instead")
-    bool is_keyword (void) const
-    {
-      return iskeyword ();
-    }
-
     bool is_symbol (void) const
     {
       return m_type_tag == sym_rec_token;
--- a/liboctave/array/Range.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/liboctave/array/Range.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -46,9 +46,9 @@
   // be an integer, even if the limit is not.  If there is one or fewer
   // elements only the base needs to be an integer.
 
-  return (! (octave::math::isnan (rng_base) || octave::math::isnan (rng_inc))
-          && (octave::math::nint_big (rng_base) == rng_base || rng_numel < 1)
-          && (octave::math::nint_big (rng_inc) == rng_inc || rng_numel <= 1));
+  return (! (octave::math::isnan (m_base) || octave::math::isnan (m_inc))
+          && (octave::math::nint_big (m_base) == m_base || m_numel < 1)
+          && (octave::math::nint_big (m_inc) == m_inc || m_numel <= 1));
 }
 
 octave_idx_type
@@ -58,27 +58,26 @@
 
   if (! isempty ())
     {
-      if ((rng_base > 0.0 && rng_limit > 0.0)
-          || (rng_base < 0.0 && rng_limit < 0.0))
+      if ((m_base > 0.0 && m_limit > 0.0) || (m_base < 0.0 && m_limit < 0.0))
         {
           // All elements have the same sign, hence there are no zeros.
-          retval = rng_numel;
+          retval = m_numel;
         }
-      else if (rng_inc != 0.0)
+      else if (m_inc != 0.0)
         {
-          if (rng_base == 0.0 || rng_limit == 0.0)
+          if (m_base == 0.0 || m_limit == 0.0)
             // Exactly one zero at beginning or end of range.
-            retval = rng_numel - 1;
-          else if ((rng_base / rng_inc) != std::floor (rng_base / rng_inc))
+            retval = m_numel - 1;
+          else if ((m_base / m_inc) != std::floor (m_base / m_inc))
             // Range crosses negative/positive without hitting zero.
-            retval = rng_numel;
+            retval = m_numel;
           else
             // Range crosses negative/positive and hits zero.
-            retval = rng_numel - 1;
+            retval = m_numel - 1;
         }
       else
         {
-          // All elements are equal (rng_inc = 0) but not positive or negative,
+          // All elements are equal (m_inc = 0) but not positive or negative,
           // therefore all elements are zero.
           retval = 0;
         }
@@ -90,37 +89,34 @@
 Matrix
 Range::matrix_value (void) const
 {
-  if (rng_numel > 0 && cache.isempty ())
-    {
-      cache.resize (1, rng_numel);
+  Matrix retval (1, m_numel);
 
-      // The first element must always be *exactly* the base.
-      // E.g, -0 would otherwise become +0 in the loop (-0 + 0*increment).
-      cache(0) = rng_base;
+  // The first element must always be *exactly* the base.
+  // E.g, -0 would otherwise become +0 in the loop (-0 + 0*increment).
+  retval(0) = m_base;
 
-      double b = rng_base;
-      double increment = rng_inc;
-      for (octave_idx_type i = 1; i < rng_numel - 1; i++)
-        cache.xelem (i) = b + i * increment;
+  double b = m_base;
+  double increment = m_inc;
+  for (octave_idx_type i = 1; i < m_numel - 1; i++)
+    retval.xelem (i) = b + i * increment;
 
-      cache.xelem (rng_numel - 1) = rng_limit;
-    }
+  retval.xelem (m_numel - 1) = m_limit;
 
-  return cache;
+  return retval;
 }
 
 double
 Range::checkelem (octave_idx_type i) const
 {
-  if (i < 0 || i >= rng_numel)
-    octave::err_index_out_of_range (2, 2, i+1, rng_numel, dims ());
+  if (i < 0 || i >= m_numel)
+    octave::err_index_out_of_range (2, 2, i+1, m_numel, dims ());
 
   if (i == 0)
-    return rng_base;
-  else if (i < rng_numel - 1)
-    return rng_base + i * rng_inc;
+    return m_base;
+  else if (i < m_numel - 1)
+    return m_base + i * m_inc;
   else
-    return rng_limit;
+    return m_limit;
 }
 
 double
@@ -128,7 +124,7 @@
 {
   // Ranges are *always* row vectors.
   if (i != 0)
-    octave::err_index_out_of_range (1, 1, i+1, rng_numel, dims ());
+    octave::err_index_out_of_range (1, 1, i+1, m_numel, dims ());
 
   return checkelem (j);
 }
@@ -137,11 +133,11 @@
 Range::elem (octave_idx_type i) const
 {
   if (i == 0)
-    return rng_base;
-  else if (i < rng_numel - 1)
-    return rng_base + i * rng_inc;
+    return m_base;
+  else if (i < m_numel - 1)
+    return m_base + i * m_inc;
   else
-    return rng_limit;
+    return m_limit;
 }
 
 // Helper class used solely for idx_vector.loop () function call
@@ -173,11 +169,11 @@
 {
   Array<double> retval;
 
-  octave_idx_type n = rng_numel;
+  octave_idx_type n = m_numel;
 
   if (i.is_colon ())
     {
-      retval = matrix_value ().reshape (dim_vector (rng_numel, 1));
+      retval = matrix_value ().reshape (dim_vector (m_numel, 1));
     }
   else
     {
@@ -196,7 +192,7 @@
       // idx_vector loop across all values in i,
       // executing __rangeidx_helper (i) for each i
       i.loop (n, __rangeidx_helper (retval.fortran_vec (),
-                                    rng_base, rng_inc, rng_limit, rng_numel));
+                                    m_base, m_inc, m_limit, m_numel));
     }
 
   return retval;
@@ -209,17 +205,17 @@
 Range::min (void) const
 {
   double retval = 0.0;
-  if (rng_numel > 0)
+  if (m_numel > 0)
     {
-      if (rng_inc > 0)
-        retval = rng_base;
+      if (m_inc > 0)
+        retval = m_base;
       else
         {
-          retval = rng_base + (rng_numel - 1) * rng_inc;
+          retval = m_base + (m_numel - 1) * m_inc;
 
           // Require '<=' test.  See note in max ().
-          if (retval <= rng_limit)
-            retval = rng_limit;
+          if (retval <= m_limit)
+            retval = m_limit;
         }
 
     }
@@ -230,24 +226,24 @@
 Range::max (void) const
 {
   double retval = 0.0;
-  if (rng_numel > 0)
+  if (m_numel > 0)
     {
-      if (rng_inc > 0)
+      if (m_inc > 0)
         {
-          retval = rng_base + (rng_numel - 1) * rng_inc;
+          retval = m_base + (m_numel - 1) * m_inc;
 
           // On some machines (x86 with extended precision floating point
           // arithmetic, for example) it is possible that we can overshoot the
           // limit by approximately the machine precision even though we were
           // very careful in our calculation of the number of elements.
           // Therefore, we clip the result to the limit if it overshoots.
-          // The test also includes equality (>= rng_limit) to have expressions
+          // The test also includes equality (>= m_limit) to have expressions
           // such as -5:1:-0 result in a -0 endpoint.
-          if (retval >= rng_limit)
-            retval = rng_limit;
+          if (retval >= m_limit)
+            retval = m_limit;
         }
       else
-        retval = rng_base;
+        retval = m_base;
     }
   return retval;
 }
@@ -255,12 +251,11 @@
 void
 Range::sort_internal (bool ascending)
 {
-  if ((ascending && rng_base > rng_limit && rng_inc < 0.0)
-      || (! ascending && rng_base < rng_limit && rng_inc > 0.0))
+  if ((ascending && m_base > m_limit && m_inc < 0.0)
+      || (! ascending && m_base < m_limit && m_inc > 0.0))
     {
-      std::swap (rng_base, rng_limit);
-      rng_inc = -rng_inc;
-      clear_cache ();
+      std::swap (m_base, m_limit);
+      m_inc = -m_inc;
     }
 }
 
@@ -275,12 +270,11 @@
 
   bool reverse = false;
 
-  if ((ascending && rng_base > rng_limit && rng_inc < 0.0)
-      || (! ascending && rng_base < rng_limit && rng_inc > 0.0))
+  if ((ascending && m_base > m_limit && m_inc < 0.0)
+      || (! ascending && m_base < m_limit && m_inc > 0.0))
     {
-      std::swap (rng_base, rng_limit);
-      rng_inc = -rng_inc;
-      clear_cache ();
+      std::swap (m_base, m_limit);
+      m_inc = -m_inc;
       reverse = true;
     }
 
@@ -337,9 +331,9 @@
 sortmode
 Range::issorted (sortmode mode) const
 {
-  if (rng_numel > 1 && rng_inc > 0)
+  if (m_numel > 1 && m_inc > 0)
     mode = (mode == DESCENDING) ? UNSORTED : ASCENDING;
-  else if (rng_numel > 1 && rng_inc < 0)
+  else if (m_numel > 1 && m_inc < 0)
     mode = (mode == ASCENDING) ? UNSORTED : DESCENDING;
   else
     mode = (mode == UNSORTED) ? ASCENDING : mode;
@@ -350,9 +344,9 @@
 void
 Range::set_base (double b)
 {
-  if (rng_base != b)
+  if (m_base != b)
     {
-      rng_base = b;
+      m_base = b;
 
       init ();
     }
@@ -361,9 +355,9 @@
 void
 Range::set_limit (double l)
 {
-  if (rng_limit != l)
+  if (m_limit != l)
     {
-      rng_limit = l;
+      m_limit = l;
 
       init ();
     }
@@ -372,9 +366,9 @@
 void
 Range::set_inc (double i)
 {
-  if (rng_inc != i)
+  if (m_inc != i)
     {
-      rng_inc = i;
+      m_inc = i;
 
       init ();
     }
@@ -396,7 +390,7 @@
     }
 
   // Print out the last element exactly, rather than a calculated last element.
-  os << a.rng_limit << "\n";
+  os << a.m_limit << "\n";
 
   return os;
 }
@@ -404,17 +398,17 @@
 std::istream&
 operator >> (std::istream& is, Range& a)
 {
-  is >> a.rng_base;
+  is >> a.m_base;
   if (is)
     {
-      double tmp_rng_limit;
-      is >> tmp_rng_limit;
+      double tmp_limit;
+      is >> tmp_limit;
 
       if (is)
-        is >> a.rng_inc;
+        is >> a.m_inc;
 
-      // Clip the rng_limit to the true limit, rebuild numel, clear cache
-      a.set_limit (tmp_rng_limit);
+      // Clip the m_limit to the true limit, rebuild numel, clear cache
+      a.set_limit (tmp_limit);
     }
 
   return is;
@@ -428,59 +422,32 @@
 
 Range operator + (double x, const Range& r)
 {
-  Range result (x + r.base (), x + r.limit (), r.inc (), r.numel ());
-  // Check whether new range was constructed properly.  A non-finite
-  // value (Inf or NaN) requires that the output be of the same size
-  // as the original range with all values set to the non-finite value.
-  if (result.rng_numel < 0)
-    result.cache = x + r.matrix_value ();
-
-  return result;
+  return Range (x + r.base (), x + r.limit (), r.inc (), r.numel ());
 }
 
 Range operator + (const Range& r, double x)
 {
-  Range result (r.base () + x, r.limit () + x, r.inc (), r.numel ());
-  if (result.rng_numel < 0)
-    result.cache = r.matrix_value () + x;
-
-  return result;
+  return Range (r.base () + x, r.limit () + x, r.inc (), r.numel ());
 }
 
 Range operator - (double x, const Range& r)
 {
-  Range result (x - r.base (), x - r.limit (), -r.inc (), r.numel ());
-  if (result.rng_numel < 0)
-    result.cache = x - r.matrix_value ();
-
-  return result;
+  return Range (x - r.base (), x - r.limit (), -r.inc (), r.numel ());
 }
 
 Range operator - (const Range& r, double x)
 {
-  Range result (r.base () - x, r.limit () - x, r.inc (), r.numel ());
-  if (result.rng_numel < 0)
-    result.cache = r.matrix_value () - x;
-
-  return result;
+  return Range (r.base () - x, r.limit () - x, r.inc (), r.numel ());
 }
 
 Range operator * (double x, const Range& r)
 {
-  Range result (x * r.base (), x * r.limit (), x * r.inc (), r.numel ());
-  if (result.rng_numel < 0)
-    result.cache = x * r.matrix_value ();
-
-  return result;
+  return Range (x * r.base (), x * r.limit (), x * r.inc (), r.numel ());
 }
 
 Range operator * (const Range& r, double x)
 {
-  Range result (r.base () * x, r.limit () * x, r.inc () * x, r.numel ());
-  if (result.rng_numel < 0)
-    result.cache = r.matrix_value () * x;
-
-  return result;
+  return Range (r.base () * x, r.limit () * x, r.inc () * x, r.numel ());
 }
 
 // C  See Knuth, Art Of Computer Programming, Vol. 1, Problem 1.2.4-5.
@@ -560,9 +527,9 @@
 {
   octave_idx_type retval = -1;
 
-  if (rng_inc == 0
-      || (rng_limit > rng_base && rng_inc < 0)
-      || (rng_limit < rng_base && rng_inc > 0))
+  if (m_inc == 0
+      || (m_limit > m_base && m_inc < 0)
+      || (m_limit < m_base && m_inc > 0))
     {
       retval = 0;
     }
@@ -570,7 +537,7 @@
     {
       double ct = 3.0 * std::numeric_limits<double>::epsilon ();
 
-      double tmp = tfloor ((rng_limit - rng_base + rng_inc) / rng_inc, ct);
+      double tmp = tfloor ((m_limit - m_base + m_inc) / m_inc, ct);
 
       octave_idx_type n_elt = (tmp > 0.0 ? static_cast<octave_idx_type> (tmp)
                                          : 0);
@@ -584,11 +551,11 @@
       // using tfloor as above.  For example, without it, the expression
       // 1.8:0.05:1.9 fails to produce the expected result of [1.8, 1.85, 1.9].
 
-      if (! teq (rng_base + (n_elt - 1) * rng_inc, rng_limit))
+      if (! teq (m_base + (n_elt - 1) * m_inc, m_limit))
         {
-          if (teq (rng_base + (n_elt - 2) * rng_inc, rng_limit))
+          if (teq (m_base + (n_elt - 2) * m_inc, m_limit))
             n_elt--;
-          else if (teq (rng_base + n_elt * rng_inc, rng_limit))
+          else if (teq (m_base + n_elt * m_inc, m_limit))
             n_elt++;
         }
 
@@ -604,7 +571,7 @@
 {
   double new_limit;
 
-  if (rng_inc > 0)
+  if (m_inc > 0)
     new_limit = max ();
   else
     new_limit = min ();
@@ -619,8 +586,6 @@
 void
 Range::init (void)
 {
-  rng_numel = numel_internal ();
-  rng_limit = limit_internal ();
-
-  clear_cache ();
+  m_numel = numel_internal ();
+  m_limit = limit_internal ();
 }
--- a/liboctave/array/Range.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/liboctave/array/Range.h	Tue Jul 07 19:40:20 2020 -0400
@@ -41,7 +41,8 @@
 public:
 
   Range (void)
-    : rng_base (0), rng_limit (0), rng_inc (0), rng_numel (0), cache (1, 0) { }
+    : m_base (0), m_limit (0), m_inc (0), m_numel (0)
+  { }
 
   Range (const Range& r) = default;
 
@@ -50,43 +51,44 @@
   ~Range (void) = default;
 
   Range (double b, double l)
-    : rng_base (b), rng_limit (l), rng_inc (1),
-      rng_numel (numel_internal ()), cache ()
+    : m_base (b), m_limit (l), m_inc (1), m_numel (numel_internal ())
   {
-    rng_limit = limit_internal ();
+    m_limit = limit_internal ();
   }
 
   Range (double b, double l, double i)
-    : rng_base (b), rng_limit (l), rng_inc (i),
-      rng_numel (numel_internal ()), cache ()
+    : m_base (b), m_limit (l), m_inc (i), m_numel (numel_internal ())
   {
-    rng_limit = limit_internal ();
+    m_limit = limit_internal ();
   }
 
+  // NOTE: The following constructor may be deprecated and removed after
+  // the arithmetic operators are removed.
+
   // For operators' usage (to preserve element count).
+
   Range (double b, double i, octave_idx_type n)
-    : rng_base (b), rng_limit (b + (n-1) * i), rng_inc (i),
-      rng_numel (n), cache ()
+    : m_base (b), m_limit (b + (n-1) * i), m_inc (i), m_numel (n)
   {
     if (! octave::math::isfinite (b) || ! octave::math::isfinite (i)
-        || ! octave::math::isfinite (rng_limit))
-      rng_numel = -2;
+        || ! octave::math::isfinite (m_limit))
+      m_numel = -2;
     else
       {
         // Code below is only needed if the resulting range must be 100%
         // correctly constructed.  If the Range object created is only
         // a temporary one used by operators this may be unnecessary.
-        rng_limit = limit_internal ();
+        m_limit = limit_internal ();
       }
   }
 
-  double base (void) const { return rng_base; }
-  double limit (void) const { return rng_limit; }
-  double inc (void) const { return rng_inc; }
+  double base (void) const { return m_base; }
+  double limit (void) const { return m_limit; }
+  double inc (void) const { return m_inc; }
 
-  octave_idx_type numel (void) const { return rng_numel; }
+  octave_idx_type numel (void) const { return m_numel; }
 
-  dim_vector dims (void) const { return dim_vector (1, rng_numel); }
+  dim_vector dims (void) const { return dim_vector (1, m_numel); }
 
   octave_idx_type rows (void) const { return 1; }
 
@@ -150,13 +152,11 @@
 
 private:
 
-  double rng_base;
-  double rng_limit;
-  double rng_inc;
+  double m_base;
+  double m_limit;
+  double m_inc;
 
-  octave_idx_type rng_numel;
-
-  mutable Matrix cache;
+  octave_idx_type m_numel;
 
   octave_idx_type numel_internal (void) const;
 
@@ -164,27 +164,40 @@
 
   void init (void);
 
-  void clear_cache (void) const { cache.resize (0, 0); }
+protected:
 
-protected:
+  // NOTE: The following constructor may be removed when the arithmetic
+  // operators are removed.
 
   // For operators' usage (to allow all values to be set directly).
   Range (double b, double l, double i, octave_idx_type n)
-    : rng_base (b), rng_limit (l), rng_inc (i),
-      rng_numel (n), cache ()
+    : m_base (b), m_limit (l), m_inc (i), m_numel (n)
   {
     if (! octave::math::isfinite (b) || ! octave::math::isfinite (i)
         || ! octave::math::isfinite (l))
-      rng_numel = -2;
+      m_numel = -2;
   }
 };
 
+OCTAVE_DEPRECATED (7, "arithmetic operations on Range objects are unreliable")
 extern OCTAVE_API Range operator - (const Range& r);
+
+OCTAVE_DEPRECATED (7, "arithmetic operations on Range objects are unreliable")
 extern OCTAVE_API Range operator + (double x, const Range& r);
+
+OCTAVE_DEPRECATED (7, "arithmetic operations on Range objects are unreliable")
 extern OCTAVE_API Range operator + (const Range& r, double x);
+
+OCTAVE_DEPRECATED (7, "arithmetic operations on Range objects are unreliable")
 extern OCTAVE_API Range operator - (double x, const Range& r);
+
+OCTAVE_DEPRECATED (7, "arithmetic operations on Range objects are unreliable")
 extern OCTAVE_API Range operator - (const Range& r, double x);
+
+OCTAVE_DEPRECATED (7, "arithmetic operations on Range objects are unreliable")
 extern OCTAVE_API Range operator * (double x, const Range& r);
+
+OCTAVE_DEPRECATED (7, "arithmetic operations on Range objects are unreliable")
 extern OCTAVE_API Range operator * (const Range& r, double x);
 
 #endif
--- a/liboctave/system/lo-sysdep.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/liboctave/system/lo-sysdep.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -27,12 +27,11 @@
 #  include "config.h"
 #endif
 
-#include <string>
-
 #include "dir-ops.h"
 #include "file-ops.h"
 #include "lo-error.h"
 #include "lo-sysdep.h"
+#include "localcharset-wrapper.h"
 #include "putenv-wrapper.h"
 #include "uniconv-wrappers.h"
 #include "unistd-wrappers.h"
@@ -42,8 +41,9 @@
 #  include <windows.h>
 #  include <wchar.h>
 
+#  include "filepos-wrappers.h"
 #  include "lo-hash.h"
-#  include "filepos-wrappers.h"
+#  include "oct-locbuf.h"
 #  include "unwind-prot.h"
 #endif
 
@@ -365,6 +365,48 @@
 #endif
     }
 
+    std::fstream
+    fstream (const std::string& filename, const std::ios::openmode mode)
+    {
+#if defined (OCTAVE_USE_WINDOWS_API)
+
+      std::wstring wfilename = u8_to_wstring (filename);
+
+      return std::fstream (wfilename.c_str (), mode);
+
+#else
+      return std::fstream (filename.c_str (), mode);
+#endif
+    }
+
+    std::ifstream
+    ifstream (const std::string& filename, const std::ios::openmode mode)
+    {
+#if defined (OCTAVE_USE_WINDOWS_API)
+
+      std::wstring wfilename = u8_to_wstring (filename);
+
+      return std::ifstream (wfilename.c_str (), mode);
+
+#else
+      return std::ifstream (filename.c_str (), mode);
+#endif
+    }
+
+    std::ofstream
+    ofstream (const std::string& filename, const std::ios::openmode mode)
+    {
+#if defined (OCTAVE_USE_WINDOWS_API)
+
+      std::wstring wfilename = u8_to_wstring (filename);
+
+      return std::ofstream (wfilename.c_str (), mode);
+
+#else
+      return std::ofstream (filename.c_str (), mode);
+#endif
+    }
+
     void
     putenv_wrapper (const std::string& name, const std::string& value)
     {
@@ -483,11 +525,16 @@
     // checks whether there are any non-ASCII characters in the passed
     // file name.  If there are not, it returns the original name.
 
-    // Otherwise, it tries to obtain the short file name (8.3 naming
-    // scheme) which only consists of ASCII characters and are safe to
-    // pass.  However, short file names can be disabled for performance
-    // reasons on the file system level with NTFS.  So there is no
-    // guarantee that these exist.
+    // Otherwise, it optionally tries to convert the file name to the locale
+    // charset.
+
+    // If the file name contains characters that cannot be converted to the
+    // locale charset (or that step is skipped), it tries to obtain the short
+    // file name (8.3 naming scheme) which only consists of ASCII characters
+    // and are safe to pass.  However, short file names can be disabled for
+    // performance reasons on the file system level with NTFS and they are not
+    // stored on other file systems (e.g. ExFAT).  So there is no guarantee
+    // that these exist.
 
     // If short file names are not stored, a hard link to the file is
     // created.  For this the path to the file is split at the deepest
@@ -508,7 +555,8 @@
     // For Unixy systems, this function does nothing.
 
     std::string
-    get_ASCII_filename (const std::string& orig_file_name)
+    get_ASCII_filename (const std::string& orig_file_name,
+                        const bool allow_locale)
     {
 #if defined (OCTAVE_USE_WINDOWS_API)
 
@@ -518,7 +566,7 @@
       // This is useful for passing file names to functions that are not
       // aware of the character encoding we are using.
 
-      // 1. Check whether filename contains non-ASCII (UTF-8) characters.
+      // 0. Check whether filename contains non-ASCII (UTF-8) characters.
 
       std::string::const_iterator first_non_ASCII
         = std::find_if (orig_file_name.begin (), orig_file_name.end (),
@@ -527,6 +575,28 @@
       if (first_non_ASCII == orig_file_name.end ())
         return orig_file_name;
 
+      // 1. Optionally, check if all characters in the path can be successfully
+      // converted to the locale charset
+      if (allow_locale)
+        {
+          const char *locale = octave_locale_charset_wrapper ();
+          if (locale)
+            {
+              const uint8_t *name_u8 = reinterpret_cast<const uint8_t *>
+                                         (orig_file_name.c_str ());
+              size_t length = 0;
+              char *name_locale = octave_u8_conv_to_encoding_strict
+                                    (locale, name_u8,
+                                     orig_file_name.length () + 1, &length);
+              if (name_locale)
+                {
+                  std::string file_name_locale (name_locale, length);
+                  free (name_locale);
+                  return file_name_locale;
+                }
+            }
+        }
+
       // 2. Check if file system stores short filenames (always
       // ASCII-only).
 
@@ -549,7 +619,7 @@
           // Dynamically allocate the correct size (terminating null char
           // was included in length).
 
-          wchar_t *w_short_file_name = new wchar_t[length];
+          OCTAVE_LOCAL_BUFFER (wchar_t, w_short_file_name, length);
           GetShortPathNameW (w_full_file_name, w_short_file_name, length);
 
           std::wstring w_short_file_name_str
@@ -611,6 +681,10 @@
       if (CreateHardLinkW (w_filename_hash, w_orig_file_name, nullptr))
         return filename_hash;
 
+#else
+
+      octave_unused_parameter (allow_locale);
+
 #endif
 
       return orig_file_name;
--- a/liboctave/system/lo-sysdep.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/liboctave/system/lo-sysdep.h	Tue Jul 07 19:40:20 2020 -0400
@@ -28,6 +28,7 @@
 
 #include "octave-config.h"
 
+#include <fstream>
 #include <string>
 
 #include <sys/types.h>
@@ -49,6 +50,16 @@
 
     extern std::FILE * fopen (const std::string& name, const std::string& mode);
 
+    extern std::fstream fstream (const std::string& name,
+                                 const std::ios::openmode mode =
+                                   std::ios::in | std::ios::out);
+
+    extern std::ifstream ifstream (const std::string& name,
+                                   const std::ios::openmode mode = std::ios::in);
+
+    extern std::ofstream ofstream (const std::string& name,
+                                   const std::ios::openmode mode = std::ios::out);
+
     extern void putenv_wrapper (const std::string& name,
                                 const std::string& value);
 
@@ -60,7 +71,8 @@
 
     extern std::string u8_from_wstring (const std::wstring&);
 
-    extern std::string get_ASCII_filename (const std::string& long_file_name);
+    extern std::string get_ASCII_filename (const std::string& long_file_name,
+                                           const bool allow_locale = false);
   }
 }
 
--- a/liboctave/util/cmd-hist.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/liboctave/util/cmd-hist.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -37,6 +37,7 @@
 #include "cmd-hist.h"
 #include "file-ops.h"
 #include "lo-error.h"
+#include "lo-sysdep.h"
 #include "singleton-cleanup.h"
 #include "str-vec.h"
 
@@ -399,7 +400,7 @@
 
                     if (! fs)
                       {
-                        std::fstream tmp (f, std::ios::out);
+                        std::ofstream tmp = sys::ofstream (f, std::ios::out);
                         tmp.close ();
                       }
 
--- a/liboctave/util/file-info.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/liboctave/util/file-info.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -83,9 +83,8 @@
 
     size_t sz = fs.size ();
 
-    std::string ascii_fname = sys::get_ASCII_filename (fname);
-
-    std::ifstream file (ascii_fname.c_str (), std::ios::in | std::ios::binary);
+    std::ifstream file = sys::ifstream (fname.c_str (),
+                                        std::ios::in | std::ios::binary);
 
     if (file)
       {
--- a/liboctave/util/url-transfer.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/liboctave/util/url-transfer.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -121,8 +121,9 @@
               {
                 std::string realfile = target + directory + sep + sv(i);
 
-                std::ofstream ofile (realfile.c_str (),
-                                     std::ios::out | std::ios::binary);
+                std::ofstream ofile =
+                  sys::ofstream (realfile.c_str (),
+                                 std::ios::out | std::ios::binary);
 
                 if (! ofile.is_open ())
                   {
@@ -206,10 +207,9 @@
               else
                 {
                   // FIXME: Does ascii mode need to be flagged here?
-                  std::string ascii_fname = sys::get_ASCII_filename (realfile);
-
-                  std::ifstream ifile (ascii_fname.c_str (),
-                                       std::ios::in | std::ios::binary);
+                  std::ifstream ifile =
+                    sys::ifstream (realfile.c_str (),
+                                   std::ios::in | std::ios::binary);
 
                   if (! ifile.is_open ())
                     {
--- a/liboctave/wrappers/uniconv-wrappers.c	Tue Jul 07 18:34:23 2020 -0400
+++ b/liboctave/wrappers/uniconv-wrappers.c	Tue Jul 07 19:40:20 2020 -0400
@@ -57,11 +57,19 @@
 }
 
 char *
+octave_u8_conv_to_encoding_strict (const char *tocode, const uint8_t *src,
+                                   size_t srclen, size_t *lengthp)
+{
+  return u8_conv_to_encoding (tocode, iconveh_error,
+                              src, srclen, NULL, NULL, lengthp);
+}
+
+char *
 octave_u32_conv_to_encoding_strict (const char *tocode, const uint32_t *src,
-                            size_t srclen, size_t *lengthp)
+                                    size_t srclen, size_t *lengthp)
 {
   return u32_conv_to_encoding (tocode, iconveh_error,
-                              src, srclen, NULL, NULL, lengthp);
+                               src, srclen, NULL, NULL, lengthp);
 }
 
 char *
--- a/liboctave/wrappers/uniconv-wrappers.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/liboctave/wrappers/uniconv-wrappers.h	Tue Jul 07 19:40:20 2020 -0400
@@ -50,6 +50,10 @@
                             size_t srclen, size_t *lengthp);
 
 extern char *
+octave_u8_conv_to_encoding_strict (const char *tocode, const uint8_t *src,
+                                   size_t srclen, size_t *lengthp);
+
+extern char *
 octave_u32_conv_to_encoding_strict (const char *tocode, const uint32_t *src,
                                     size_t srclen, size_t *lengthp);
 
--- a/liboctave/wrappers/unistr-wrappers.c	Tue Jul 07 18:34:23 2020 -0400
+++ b/liboctave/wrappers/unistr-wrappers.c	Tue Jul 07 19:40:20 2020 -0400
@@ -49,6 +49,27 @@
   return u8_strmbtouc (puc, src);
 }
 
+uint8_t *
+octave_u16_to_u8_wrapper (const uint16_t *src, size_t src_len,
+                          uint8_t *result_buf, size_t *lengthp)
+{
+  return u16_to_u8 (src, src_len, result_buf, lengthp);
+}
+
+uint8_t *
+octave_u32_to_u8_wrapper (const uint32_t *src, size_t src_len,
+                          uint8_t *result_buf, size_t *lengthp)
+{
+  return u32_to_u8 (src, src_len, result_buf, lengthp);
+}
+
+uint16_t *
+octave_u8_to_u16_wrapper (const uint8_t *src, size_t src_len,
+                          uint16_t *result_buf, size_t *lengthp)
+{
+  return u8_to_u16 (src, src_len, result_buf, lengthp);
+}
+
 uint32_t *
 octave_u8_to_u32_wrapper (const uint8_t *src, size_t src_len,
                           uint32_t *result_buf, size_t *lengthp)
--- a/liboctave/wrappers/unistr-wrappers.h	Tue Jul 07 18:34:23 2020 -0400
+++ b/liboctave/wrappers/unistr-wrappers.h	Tue Jul 07 19:40:20 2020 -0400
@@ -39,6 +39,18 @@
 extern int
 octave_u8_strmbtouc_wrapper (uint32_t *puc, const uint8_t *src);
 
+extern uint8_t *
+octave_u16_to_u8_wrapper (const uint16_t *src, size_t src_len,
+                          uint8_t *result_buf, size_t *lengthp);
+
+extern uint8_t *
+octave_u32_to_u8_wrapper (const uint32_t *src, size_t src_len,
+                          uint8_t *result_buf, size_t *lengthp);
+
+extern uint16_t *
+octave_u8_to_u16_wrapper (const uint8_t *src, size_t src_len,
+                          uint16_t *result_buf, size_t *lengthp);
+
 extern uint32_t *
 octave_u8_to_u32_wrapper (const uint8_t *src, size_t src_len,
                           uint32_t *result_buf, size_t *lengthp);
--- a/liboctave/wrappers/wait-wrappers.c	Tue Jul 07 18:34:23 2020 -0400
+++ b/liboctave/wrappers/wait-wrappers.c	Tue Jul 07 19:40:20 2020 -0400
@@ -35,6 +35,10 @@
 #include <sys/types.h>
 #include <sys/wait.h>
 
+#if defined (__WIN32__) && ! defined (__CYGWIN__)
+#  include <windows.h>
+#endif
+
 #include "wait-wrappers.h"
 
 #if ! defined (WCONTINUE)
@@ -57,14 +61,42 @@
 octave_waitpid_wrapper (pid_t pid, int *statusp, int options)
 {
 #if defined (__WIN32__) && ! defined (__CYGWIN__)
+  // gnulib's waitpid replacement currently uses _cwait, which
+  // apparently only works with console applications.
+  // Implement our own wrapper using win32 API functions.
 
-  octave_unused_parameter (pid);
   octave_unused_parameter (options);
 
-  // gnulib's waitpid replacement currently uses _cwait, which
-  // apparently only works with console applications.
-  *statusp = 0;
-  return -1;
+  pid_t retval = -1;
+  DWORD status = 0;
+
+  HANDLE hProcess = OpenProcess (PROCESS_QUERY_INFORMATION | SYNCHRONIZE,
+                                 false, pid);
+
+  if (! hProcess)
+    return retval;
+
+  if (WaitForSingleObject (hProcess, INFINITE) != WAIT_OBJECT_0)
+    {
+      CloseHandle (hProcess);
+      return retval;
+    }
+
+  if (! GetExitCodeProcess (hProcess, &status))
+    {
+      CloseHandle (hProcess);
+      return retval;
+    }
+
+  CloseHandle (hProcess);
+
+  if (statusp)
+    *statusp = status;
+
+  retval = pid;
+
+  return retval;
+
 #else
   return waitpid (pid, statusp, options);
 #endif
--- a/m4/acinclude.m4	Tue Jul 07 18:34:23 2020 -0400
+++ b/m4/acinclude.m4	Tue Jul 07 19:40:20 2020 -0400
@@ -369,86 +369,6 @@
   fi
 ])
 dnl
-dnl Check whether the Qt class QAbstractItemModel exists and has the
-dnl beginResetModel and endResetModel member functions.  These member
-dnl functions were introduced in Qt 4.6.
-dnl
-dnl FIXME: Delete this entirely when we can safely assume that Qt 4.6 or later
-dnl is in use everywhere, or when we drop support for Qt 4.
-dnl
-AC_DEFUN([OCTAVE_CHECK_FUNC_QABSTRACTITEMMODEL_BEGINRESETMODEL], [
-  AC_CACHE_CHECK([for QAbstractItemModel::beginResetModel in <QAbstractItemModel>],
-    [octave_cv_func_qabstractitemmodel_beginresetmodel],
-    [AC_LANG_PUSH(C++)
-    ac_octave_save_CPPFLAGS="$CPPFLAGS"
-    ac_octave_save_CXXFLAGS="$CXXFLAGS"
-    CPPFLAGS="$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS"
-    CXXFLAGS="$CXXPICFLAG $CXXFLAGS"
-    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-        #include <QAbstractItemModel>
-        class item_model : public QAbstractItemModel
-        {
-        public:
-          item_model (QObject *parent = 0) : QAbstractItemModel (parent) {}
-          ~item_model () {}
-          QModelIndex index (int, int, const QModelIndex& m) const { return m; }
-          QModelIndex parent (const QModelIndex& m) const { return m; }
-          int columnCount (const QModelIndex&) const { return 0; }
-          int rowCount (const QModelIndex&) const { return 0; }
-          QVariant data (const QModelIndex&, int) const { return QVariant(); }
-          void update_model ()
-          {
-            this->beginResetModel ();
-            this->endResetModel ();
-          }
-        };
-        ]], [[
-        item_model model;
-        model.update_model ();
-        ]])],
-      octave_cv_func_qabstractitemmodel_beginresetmodel=yes,
-      octave_cv_func_qabstractitemmodel_beginresetmodel=no)
-    CPPFLAGS="$ac_octave_save_CPPFLAGS"
-    CXXFLAGS="$ac_octave_save_CXXFLAGS"
-    AC_LANG_POP(C++)
-  ])
-  if test $octave_cv_func_qabstractitemmodel_beginresetmodel = yes; then
-    AC_DEFINE(HAVE_QABSTRACTITEMMODEL_BEGINRESETMODEL, 1,
-      [Define to 1 if you have the `QAbstractItemModel::beginResetModel' member function.])
-  fi
-])
-dnl
-dnl Check whether the Qt QComboBox class has the setCurrentText
-dnl function.  This function was introduced in Qt 5.
-dnl
-dnl FIXME: Delete this entirely when we drop support for Qt 4.
-dnl
-AC_DEFUN([OCTAVE_CHECK_FUNC_QCOMBOBOX_SETCURRENTTEXT], [
-  AC_CACHE_CHECK([for QComboBox::setCurrentText],
-    [octave_cv_func_qcombobox_setcurrenttext],
-    [AC_LANG_PUSH(C++)
-    ac_octave_save_CPPFLAGS="$CPPFLAGS"
-    ac_octave_save_CXXFLAGS="$CXXFLAGS"
-    CPPFLAGS="$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS"
-    CXXFLAGS="$CXXPICFLAG $CPPFLAGS"
-    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-        #include <QComboBox>
-        ]], [[
-        QComboBox combo_box (nullptr);
-        combo_box.setCurrentText ("text");
-        ]])],
-      octave_cv_func_qcombobox_setcurrenttext=yes,
-      octave_cv_func_qcombobox_setcurrenttext=no)
-    CPPFLAGS="$ac_octave_save_CPPFLAGS"
-    CXXFLAGS="$ac_octave_save_CXXFLAGS"
-    AC_LANG_POP(C++)
-  ])
-  if test $octave_cv_func_qcombobox_setcurrenttext = yes; then
-    AC_DEFINE(HAVE_QCOMBOBOX_SETCURRENTTEXT, 1,
-      [Define to 1 if you have the `QComboBox::setCurrentText' member function.])
-  fi
-])
-dnl
 dnl Check whether the Qt QGuiApplication class has the setDesktopFileName
 dnl static member function.  This function was introduced in Qt 5.7.
 dnl
@@ -479,99 +399,6 @@
   fi
 ])
 dnl
-dnl Check whether the Qt QHeaderView class has the setSectionResizeMode
-dnl function.  This function was introduced in Qt 5.
-dnl
-dnl FIXME: Delete this entirely when we drop support for Qt 4.
-dnl
-AC_DEFUN([OCTAVE_CHECK_FUNC_QHEADERVIEW_SETSECTIONRESIZEMODE], [
-  AC_CACHE_CHECK([for QHeaderView::setSectionResizeMode],
-    [octave_cv_func_qheaderview_setsectionresizemode],
-    [AC_LANG_PUSH(C++)
-    ac_octave_save_CPPFLAGS="$CPPFLAGS"
-    ac_octave_save_CXXFLAGS="$CXXFLAGS"
-    CPPFLAGS="$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS"
-    CXXFLAGS="$CXXPICFLAG $CPPFLAGS"
-    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-        #include <QHeaderView>
-        ]], [[
-        QHeaderView header_view (Qt::Horizontal);
-        header_view.setSectionResizeMode (QHeaderView::Interactive);
-        ]])],
-      octave_cv_func_qheaderview_setsectionresizemode=yes,
-      octave_cv_func_qheaderview_setsectionresizemode=no)
-    CPPFLAGS="$ac_octave_save_CPPFLAGS"
-    CXXFLAGS="$ac_octave_save_CXXFLAGS"
-    AC_LANG_POP(C++)
-  ])
-  if test $octave_cv_func_qheaderview_setsectionresizemode = yes; then
-    AC_DEFINE(HAVE_QHEADERVIEW_SETSECTIONRESIZEMODE, 1,
-      [Define to 1 if you have the `QHeaderView::setSectionResizeMode' member function.])
-  fi
-])
-dnl
-dnl Check whether the Qt QHeaderView class has the setSectionsClickable
-dnl function.  This function was introduced in Qt 5.
-dnl
-dnl FIXME: Delete this entirely when we drop support for Qt 4.
-dnl
-AC_DEFUN([OCTAVE_CHECK_FUNC_QHEADERVIEW_SETSECTIONSCLICKABLE], [
-  AC_CACHE_CHECK([for QHeaderView::setSectionsClickable],
-    [octave_cv_func_qheaderview_setsectionsclickable],
-    [AC_LANG_PUSH(C++)
-    ac_octave_save_CPPFLAGS="$CPPFLAGS"
-    ac_octave_save_CXXFLAGS="$CXXFLAGS"
-    CPPFLAGS="$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS"
-    CXXFLAGS="$CXXPICFLAG $CPPFLAGS"
-    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-        #include <QHeaderView>
-        ]], [[
-        QHeaderView header_view (Qt::Horizontal);
-        header_view.setSectionsClickable (true);
-        ]])],
-      octave_cv_func_qheaderview_setsectionsclickable=yes,
-      octave_cv_func_qheaderview_setsectionsclickable=no)
-    CPPFLAGS="$ac_octave_save_CPPFLAGS"
-    CXXFLAGS="$ac_octave_save_CXXFLAGS"
-    AC_LANG_POP(C++)
-  ])
-  if test $octave_cv_func_qheaderview_setsectionsclickable = yes; then
-    AC_DEFINE(HAVE_QHEADERVIEW_SETSECTIONSCLICKABLE, 1,
-      [Define to 1 if you have the `QHeaderView::setSectionsClickable' member function.])
-  fi
-])
-dnl
-dnl Check whether the Qt QHeaderView class has the setSectionsMovable
-dnl function.  This function was introduced in Qt 5.
-dnl
-dnl FIXME: Delete this entirely when we drop support for Qt 4.
-dnl
-AC_DEFUN([OCTAVE_CHECK_FUNC_QHEADERVIEW_SETSECTIONSMOVABLE], [
-  AC_CACHE_CHECK([for QHeaderView::setSectionsMovable],
-    [octave_cv_func_qheaderview_setsectionsmovable],
-    [AC_LANG_PUSH(C++)
-    ac_octave_save_CPPFLAGS="$CPPFLAGS"
-    ac_octave_save_CXXFLAGS="$CXXFLAGS"
-    CPPFLAGS="$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS"
-    CXXFLAGS="$CXXPICFLAG $CPPFLAGS"
-    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-        #include <QHeaderView>
-        ]], [[
-        QHeaderView header_view (Qt::Horizontal);
-        header_view.setSectionsMovable (true);
-        ]])],
-      octave_cv_func_qheaderview_setsectionsmovable=yes,
-      octave_cv_func_qheaderview_setsectionsmovable=no)
-    CPPFLAGS="$ac_octave_save_CPPFLAGS"
-    CXXFLAGS="$ac_octave_save_CXXFLAGS"
-    AC_LANG_POP(C++)
-  ])
-  if test $octave_cv_func_qheaderview_setsectionsmovable = yes; then
-    AC_DEFINE(HAVE_QHEADERVIEW_SETSECTIONSMOVABLE, 1,
-      [Define to 1 if you have the `QHeaderView::setSectionsMovable' member function.])
-  fi
-])
-dnl
 dnl Check whether the Qt QHelpSearchQueryWidget class has the searchInput
 dnl member function.  This function was introduced in Qt 5.9.
 dnl
@@ -604,133 +431,6 @@
   fi
 ])
 dnl
-dnl Check whether the Qt function qInstallMessageHandler is available.
-dnl This function was introduced in Qt 5.
-dnl
-dnl FIXME: Delete this entirely when we drop support for Qt 4.
-dnl
-AC_DEFUN([OCTAVE_CHECK_FUNC_QINSTALLMESSAGEHANDLER], [
-  AC_CACHE_CHECK([for qInstallMessageHandler],
-    [octave_cv_func_qinstallmessagehandler],
-    [AC_LANG_PUSH(C++)
-    ac_octave_save_CPPFLAGS="$CPPFLAGS"
-    ac_octave_save_CXXFLAGS="$CXXFLAGS"
-    CPPFLAGS="$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS"
-    CXXFLAGS="$CXXPICFLAG $CPPFLAGS"
-    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-        #include <QtGlobal>
-        ]], [[
-        qInstallMessageHandler (nullptr);
-        ]])],
-      octave_cv_func_qinstallmessagehandler=yes,
-      octave_cv_func_qinstallmessagehandler=no)
-    CPPFLAGS="$ac_octave_save_CPPFLAGS"
-    CXXFLAGS="$ac_octave_save_CXXFLAGS"
-    AC_LANG_POP(C++)
-  ])
-  if test $octave_cv_func_qinstallmessagehandler = yes; then
-    AC_DEFINE(HAVE_QINSTALLMESSAGEHANDLER, 1,
-      [Define to 1 if you have the `qInstallMessageHandler' function.])
-  fi
-])
-dnl
-dnl Check whether the Qt class QLineEdit has the setPlaceholderText member
-dnl function.  This member function was introduced in Qt 4.7.
-dnl
-dnl FIXME: Delete this entirely when we can safely assume that Qt 4.7 or later
-dnl is in use everywhere, or when we drop support for Qt 4.
-dnl
-AC_DEFUN([OCTAVE_CHECK_FUNC_QLINEEDIT_SETPLACEHOLDERTEXT], [
-  AC_CACHE_CHECK([for QLineEdit::setPlaceholderText in <QLinedEdit>],
-    [octave_cv_func_qlineedit_setplaceholdertext],
-    [AC_LANG_PUSH(C++)
-    ac_octave_save_CPPFLAGS="$CPPFLAGS"
-    ac_octave_save_CXXFLAGS="$CXXFLAGS"
-    CPPFLAGS="$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS"
-    CXXFLAGS="$CXXPICFLAG $CPPFLAGS"
-    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-        #include <QLineEdit>
-        ]], [[
-        QLineEdit line_edit;
-        line_edit.setPlaceholderText ("placeholder text");
-        ]])],
-      octave_cv_func_qlineedit_setplaceholdertext=yes,
-      octave_cv_func_qlineedit_setplaceholdertext=no)
-    CPPFLAGS="$ac_octave_save_CPPFLAGS"
-    CXXFLAGS="$ac_octave_save_CXXFLAGS"
-    AC_LANG_POP(C++)
-  ])
-  if test $octave_cv_func_qlineedit_setplaceholdertext = yes; then
-    AC_DEFINE(HAVE_QLINEEDIT_SETPLACEHOLDERTEXT, 1,
-      [Define to 1 if you have the `QLineEdit::setPlaceholderText' member function.])
-  fi
-])
-dnl
-dnl Check whether the Qt QMouseEvent class has the localPos function.
-dnl This function was introduced in Qt 5.
-dnl
-dnl FIXME: Delete this entirely when we drop support for Qt 4.
-dnl
-AC_DEFUN([OCTAVE_CHECK_FUNC_QMOUSEEVENT_LOCALPOS], [
-  AC_CACHE_CHECK([for QMouseEvent::localPos],
-    [octave_cv_func_qmouseevent_localpos],
-    [AC_LANG_PUSH(C++)
-    ac_octave_save_CPPFLAGS="$CPPFLAGS"
-    ac_octave_save_CXXFLAGS="$CXXFLAGS"
-    CPPFLAGS="$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS"
-    CXXFLAGS="$CXXPICFLAG $CPPFLAGS"
-    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-        #include <QMouseEvent>
-        ]], [[
-        QMouseEvent *event;
-        event->localPos ();
-        ]])],
-      octave_cv_func_qmouseevent_localpos=yes,
-      octave_cv_func_qmouseevent_localpos=no)
-    CPPFLAGS="$ac_octave_save_CPPFLAGS"
-    CXXFLAGS="$ac_octave_save_CXXFLAGS"
-    AC_LANG_POP(C++)
-  ])
-  if test $octave_cv_func_qmouseevent_localpos = yes; then
-    AC_DEFINE(HAVE_QMOUSEEVENT_LOCALPOS, 1,
-      [Define to 1 if you have the `QMouseEvent::localPos' member function.])
-  fi
-])
-dnl
-dnl Check whether QObject::findChildren accepts Qt::FindChildOptions
-dnl argument.
-dnl
-dnl FIXME: Delete this entirely when we drop support for Qt 4.
-dnl
-AC_DEFUN([OCTAVE_CHECK_FUNC_QOBJECT_FINDCHILDREN_ACCEPTS_FINDCHILDOPTIONS], [
-  AC_CACHE_CHECK([whether QObject::findChildren accepts Qt::FindChildOptions],
-    [octave_cv_func_qobject_findchildren_accepts_findchildoptions],
-    [AC_LANG_PUSH(C++)
-    ac_octave_save_CPPFLAGS="$CPPFLAGS"
-    ac_octave_save_CXXFLAGS="$CXXFLAGS"
-    CPPFLAGS="$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS"
-    CXXFLAGS="$CXXPICFLAG $CXXFLAGS"
-    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-        #include <QList>
-        #include <QObject>
-        #include <QWidget>
-        ]], [[
-        QObject obj;
-        QList<QWidget *> widgets
-          = obj.findChildren<QWidget *> ("name", Qt::FindDirectChildrenOnly);
-        ]])],
-      octave_cv_func_qobject_findchildren_accepts_findchildoptions=yes,
-      octave_cv_func_qobject_findchildren_accepts_findchildoptions=no)
-    CPPFLAGS="$ac_octave_save_CPPFLAGS"
-    CXXFLAGS="$ac_octave_save_CXXFLAGS"
-    AC_LANG_POP(C++)
-  ])
-  if test $octave_cv_func_qobject_findchildren_accepts_findchildoptions = yes; then
-    AC_DEFINE(QOBJECT_FINDCHILDREN_ACCEPTS_FINDCHILDOPTIONS, 1,
-      [Define to 1 if 'QObject::findChildren' accepts 'Qt::FindChildOptions' argument.])
-  fi
-])
-dnl
 dnl Check whether the Qt class QScreen has the devicePixelRatio member function.
 dnl This member function was introduced in Qt 5.5.
 dnl
@@ -761,112 +461,6 @@
   fi
 ])
 dnl
-dnl Check whether the Qt class QTabWidget has the setMovable member function.
-dnl This member function was introduced in Qt 4.5.
-dnl
-dnl FIXME: Delete this entirely when we can safely assume that Qt 4.5 or later
-dnl is in use everywhere, or when we drop support for Qt 4.
-dnl
-AC_DEFUN([OCTAVE_CHECK_FUNC_QTABWIDGET_SETMOVABLE], [
-  AC_CACHE_CHECK([for QTabWidget::setMovable in <QTabWidget>],
-    [octave_cv_func_qtabwidget_setmovable],
-    [AC_LANG_PUSH(C++)
-    ac_octave_save_CPPFLAGS="$CPPFLAGS"
-    ac_octave_save_CXXFLAGS="$CXXFLAGS"
-    CPPFLAGS="$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS"
-    CXXFLAGS="$CXXPICFLAG $CXXFLAGS"
-    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-        #include <QTabWidget>
-        class tab_widget : public QTabWidget
-        {
-        public:
-          tab_widget (QWidget *parent = 0) : QTabWidget (parent) { this->setMovable (true); }
-          ~tab_widget () {}
-        };
-        ]], [[
-        tab_widget tw;
-        ]])],
-      octave_cv_func_qtabwidget_setmovable=yes,
-      octave_cv_func_qtabwidget_setmovable=no)
-    CPPFLAGS="$ac_octave_save_CPPFLAGS"
-    CXXFLAGS="$ac_octave_save_CXXFLAGS"
-    AC_LANG_POP(C++)
-  ])
-  if test $octave_cv_func_qtabwidget_setmovable = yes; then
-    AC_DEFINE(HAVE_QTABWIDGET_SETMOVABLE, 1,
-      [Define to 1 if you have the `QTabWidget::setMovable' member function.])
-  fi
-])
-dnl
-dnl Check whether the Qt class QWheelEvent has the angleDelta member function.
-dnl This member function was introduced in Qt 5.
-dnl
-dnl FIXME: Delete this entirely when we drop support for Qt 4.
-dnl
-AC_DEFUN([OCTAVE_CHECK_FUNC_QWHEELEVENT_ANGLEDELTA], [
-  AC_CACHE_CHECK([for QWheelEvent::angleDelta in <QWheelEvent>],
-    [octave_cv_func_qwheelevent_angledelta],
-    [AC_LANG_PUSH(C++)
-    ac_octave_save_CPPFLAGS="$CPPFLAGS"
-    ac_octave_save_CXXFLAGS="$CXXFLAGS"
-    CPPFLAGS="$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS"
-    CXXFLAGS="$CXXPICFLAG $CXXFLAGS"
-    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-        #include <QWheelEvent>
-        class wheel_event : public QWheelEvent
-        {
-        public:
-          wheel_event (QWidget *parent = 0) : QWheelEvent (parent) { this->angleDelta (); }
-          ~wheel_event () {}
-        };
-        ]], [[
-        wheel_event tw;
-        ]])],
-      octave_cv_func_qwheelevent_angledelta=yes,
-      octave_cv_func_qwheelevent_angledelta=no)
-    CPPFLAGS="$ac_octave_save_CPPFLAGS"
-    CXXFLAGS="$ac_octave_save_CXXFLAGS"
-    AC_LANG_POP(C++)
-  ])
-  if test $octave_cv_func_qwheelevent_angledelta = yes; then
-    AC_DEFINE(HAVE_QWHEELEVENT_ANGLEDELTA, 1,
-      [Define to 1 if you have the `QWheelEvent::angleDelta' member function.])
-  fi
-])
-dnl
-dnl Check whether Qt message handler function accepts QMessageLogContext
-dnl argument.  This change was introduced in Qt 5.
-dnl
-dnl FIXME: Delete this entirely when we drop support for Qt 4.
-dnl
-AC_DEFUN([OCTAVE_CHECK_FUNC_QTMESSAGEHANDLER_ACCEPTS_QMESSAGELOGCONTEXT], [
-  AC_CACHE_CHECK([whether Qt message handler accepts QMessageLogContext],
-    [octave_cv_func_qtmessagehandler_accepts_qmessagelogcontext],
-    [AC_LANG_PUSH(C++)
-    ac_octave_save_CPPFLAGS="$CPPFLAGS"
-    ac_octave_save_CXXFLAGS="$CXXFLAGS"
-    CPPFLAGS="$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS"
-    CXXFLAGS="$CXXPICFLAG $CXXFLAGS"
-    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-        #include <QtGlobal>
-        static void
-        msg_handler (QtMsgType, const QMessageLogContext &, const QString &)
-        { }
-        ]], [[
-        QtMessageHandler fptr = msg_handler;
-        ]])],
-      octave_cv_func_qtmessagehandler_accepts_qmessagelogcontext=yes,
-      octave_cv_func_qtmessagehandler_accepts_qmessagelogcontext=no)
-    CPPFLAGS="$ac_octave_save_CPPFLAGS"
-    CXXFLAGS="$ac_octave_save_CXXFLAGS"
-    AC_LANG_POP(C++)
-  ])
-  if test $octave_cv_func_qtmessagehandler_accepts_qmessagelogcontext = yes; then
-    AC_DEFINE(QTMESSAGEHANDLER_ACCEPTS_QMESSAGELOGCONTEXT, 1,
-      [Define to 1 if Qt message handler accepts 'QMessageLogContext' argument.])
-  fi
-])
-dnl
 dnl Check whether HDF5 library has version 1.6 API functions.
 dnl
 AC_DEFUN([OCTAVE_CHECK_HDF5_HAS_VER_16_API], [
@@ -920,7 +514,7 @@
     no)
       ifelse([$#], 10,
         [AC_MSG_ERROR([--without-m4_tolower($1) specified but $2 is required.])],
-        [warn_$1="--without-m4_tolower($1) specified.  Functions or features that depend on $2 will be disabled."
+        [warn_$1=""
          m4_toupper([$1])_LIBS=])
     ;;
     yes | "")
@@ -1648,68 +1242,6 @@
   AC_SUBST(TERM_LIBS)
 ])
 dnl
-dnl Check whether the Qt class QFont has the ForceIntegerMetrics enumerated
-dnl type member.  This property was introduced in Qt 4.7.
-dnl
-dnl FIXME: Delete this entirely when we can safely assume that Qt 4.7 or later
-dnl is in use everywhere, or when we drop support for Qt 4.
-dnl
-AC_DEFUN([OCTAVE_CHECK_MEMBER_QFONT_FORCE_INTEGER_METRICS], [
-  AC_CACHE_CHECK([for QFont::ForceIntegerMetrics in <QFont>],
-    [octave_cv_decl_qfont_force_integer_metrics],
-    [AC_LANG_PUSH(C++)
-    ac_octave_save_CPPFLAGS="$CPPFLAGS"
-    ac_octave_save_CXXFLAGS="$CXXFLAGS"
-    CPPFLAGS="$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS"
-    CXXFLAGS="$CXXPICFLAG $CXXFLAGS"
-    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-        #include <QFont>
-        ]], [[
-        QFont::StyleStrategy strategy = QFont::ForceIntegerMetrics;
-        ]])],
-      octave_cv_decl_qfont_force_integer_metrics=yes,
-      octave_cv_decl_qfont_force_integer_metrics=no)
-    CPPFLAGS="$ac_octave_save_CPPFLAGS"
-    CXXFLAGS="$ac_octave_save_CXXFLAGS"
-    AC_LANG_POP(C++)
-  ])
-  if test $octave_cv_decl_qfont_force_integer_metrics = yes; then
-    AC_DEFINE(HAVE_QFONT_FORCE_INTEGER_METRICS, 1,
-      [Define to 1 if `ForceIntegerMetrics' is a member of `QFont'.])
-  fi
-])
-dnl
-dnl Check whether the Qt class QFont has the Monospace enumerated type member.
-dnl This property was introduced in Qt 4.7.
-dnl
-dnl FIXME: Delete this entirely when we can safely assume that Qt 4.7 or later
-dnl is in use everywhere, or when we drop support for Qt 4.
-dnl
-AC_DEFUN([OCTAVE_CHECK_MEMBER_QFONT_MONOSPACE], [
-  AC_CACHE_CHECK([for QFont::Monospace in <QFont>],
-    [octave_cv_decl_qfont_monospace],
-    [AC_LANG_PUSH(C++)
-    ac_octave_save_CPPFLAGS="$CPPFLAGS"
-    ac_octave_save_CXXFLAGS="$CXXFLAGS"
-    CPPFLAGS="$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS"
-    CXXFLAGS="$CXXPICFLAG $CXXFLAGS"
-    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-        #include <QFont>
-        ]], [[
-        QFont::StyleHint hint = QFont::Monospace;
-        ]])],
-      octave_cv_decl_qfont_monospace=yes,
-      octave_cv_decl_qfont_monospace=no)
-    CPPFLAGS="$ac_octave_save_CPPFLAGS"
-    CXXFLAGS="$ac_octave_save_CXXFLAGS"
-    AC_LANG_POP(C++)
-  ])
-  if test $octave_cv_decl_qfont_monospace = yes; then
-    AC_DEFINE(HAVE_QFONT_MONOSPACE, 1,
-      [Define to 1 if `Monospace' is a member of `QFont'.])
-  fi
-])
-dnl
 dnl Check for the Qhull version.
 dnl
 AC_DEFUN([OCTAVE_CHECK_QHULL_VERSION], [
@@ -1764,9 +1296,6 @@
 
   ## Check for Qt libraries
   case "$qt_version" in
-    4)
-      octave_qscintilla_libnames="qscintilla2-qt4 qscintilla2_qt4 qt4scintilla2 qscintilla2"
-    ;;
     5)
       octave_qscintilla_libnames="qscintilla2-qt5 qscintilla2_qt5 qt5scintilla2"
     ;;
@@ -1892,11 +1421,6 @@
 
   if test $build_qt_gui = yes; then
     BUILD_QT_SUMMARY_MSG="yes (version: $have_qt_version)"
-    if test x"$have_qt_version" = x4; then
-      AC_DEFINE(HAVE_QT4, 1, [Define to 1 if using Qt version 4.])
-      warn_qt_ver="Use of Qt version 4 is deprecated.  Support will be removed in Octave version 7."
-      OCTAVE_CONFIGURE_WARNING([warn_qt_ver])
-    fi
     if test x"$have_qt_version" = x5; then
       AC_DEFINE(HAVE_QT5, 1, [Define to 1 if using Qt version 5.])
     fi
@@ -2104,10 +1628,6 @@
 
   ## Check for Qt libraries
   case "$qt_version" in
-    4)
-      QT_OPENGL_MODULE="QtOpenGL"
-      QT_MODULES="QtCore QtGui QtNetwork QtHelp QtXml"
-    ;;
     5)
       QT_OPENGL_MODULE="Qt5OpenGL"
       QT_MODULES="Qt5Core Qt5Gui Qt5Network Qt5PrintSupport Qt5Help Qt5Xml"
@@ -2159,14 +1679,6 @@
         fi
       ;;
     esac
-
-    if test $qt_version = 4; then
-      ## Check for Qt4
-      if ! `$PKG_CONFIG --atleast-version=4.0.0 QtCore`; then
-        build_qt_gui=no
-        warn_qt_version="Qt >= 4.0.0 not found; disabling Qt GUI"
-      fi
-    fi
   fi
 
   QT_TOOLS_AVAILABLE=
@@ -2231,18 +1743,6 @@
   fi
 
   if test $build_qt_gui = yes; then
-    OCTAVE_CHECK_FUNC_QABSTRACTITEMMODEL_BEGINRESETMODEL
-
-    if test $octave_cv_func_qabstractitemmodel_beginresetmodel = no; then
-      build_qt_gui=no
-      warn_qt_abstract_item_model="QAbstractItemModel::beginResetModel not found; disabling Qt GUI"
-      ## Invalidate cache so that this test will be done again if we
-      ## perform the test with a different Qt version.
-      $as_unset octave_cv_func_qabstractitemmodel_beginresetmodel
-    fi
-  fi
-
-  if test $build_qt_gui = yes; then
     ## We have what we need to build the Qt GUI.  The remaining
     ## checks below are for optional features related to the Qt GUI.
 
@@ -2260,23 +1760,9 @@
     ## tests if they fail because we have already decided that the Qt
     ## version that we are testing now will be the one used.
 
-    OCTAVE_CHECK_FUNC_QCOMBOBOX_SETCURRENTTEXT
     OCTAVE_CHECK_FUNC_QGUIAPPLICATION_SETDESKTOPFILENAME
-    OCTAVE_CHECK_FUNC_QHEADERVIEW_SETSECTIONRESIZEMODE
-    OCTAVE_CHECK_FUNC_QHEADERVIEW_SETSECTIONSCLICKABLE
-    OCTAVE_CHECK_FUNC_QHEADERVIEW_SETSECTIONSMOVABLE
     OCTAVE_CHECK_FUNC_QHELPSEARCHQUERYWIDGET_SEARCHINPUT
-    OCTAVE_CHECK_FUNC_QINSTALLMESSAGEHANDLER
-    OCTAVE_CHECK_FUNC_QLINEEDIT_SETPLACEHOLDERTEXT
-    OCTAVE_CHECK_FUNC_QMOUSEEVENT_LOCALPOS
-    OCTAVE_CHECK_FUNC_QOBJECT_FINDCHILDREN_ACCEPTS_FINDCHILDOPTIONS
     OCTAVE_CHECK_FUNC_QSCREEN_DEVICEPIXELRATIO
-    OCTAVE_CHECK_FUNC_QTABWIDGET_SETMOVABLE
-    OCTAVE_CHECK_FUNC_QTMESSAGEHANDLER_ACCEPTS_QMESSAGELOGCONTEXT
-    OCTAVE_CHECK_FUNC_QWHEELEVENT_ANGLEDELTA
-    OCTAVE_CHECK_MEMBER_QFONT_FORCE_INTEGER_METRICS
-    OCTAVE_CHECK_MEMBER_QFONT_MONOSPACE
-    OCTAVE_HAVE_QGUIAPPLICATION
 
     if test -n "$OPENGL_LIBS"; then
       OCTAVE_CHECK_QT_OPENGL_OK([build_qt_graphics=yes],
@@ -2736,36 +2222,6 @@
   fi
 ])
 dnl
-dnl Check whether the Qt class QGuiApplication exists.
-dnl This class  was introduced in Qt 5.0.
-dnl
-dnl FIXME: Delete this entirely when we drop support for Qt 4.
-dnl
-AC_DEFUN([OCTAVE_HAVE_QGUIAPPLICATION], [
-  AC_CACHE_CHECK([for QGuiApplication],
-    [octave_cv_decl_qguiapplication],
-    [AC_LANG_PUSH(C++)
-    ac_octave_save_CPPFLAGS="$CPPFLAGS"
-    ac_octave_save_CXXFLAGS="$CXXFLAGS"
-    CPPFLAGS="$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS"
-    CXXFLAGS="$CXXPICFLAG $CXXFLAGS"
-    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-        #include <QGuiApplication>
-        ]], [[
-        QScreen *pscreen = QGuiApplication::primaryScreen ();
-        ]])],
-      octave_cv_decl_qguiapplication=yes,
-      octave_cv_decl_qguiapplication=no)
-    CPPFLAGS="$ac_octave_save_CPPFLAGS"
-    CXXFLAGS="$ac_octave_save_CXXFLAGS"
-    AC_LANG_POP(C++)
-  ])
-  if test $octave_cv_decl_qguiapplication = yes; then
-    AC_DEFINE(HAVE_QGUIAPPLICATION, 1,
-      [Define to 1 if `QGuiApplication' class is available.])
-  fi
-])
-dnl
 dnl Check for IEEE 754 data format.
 dnl
 AC_DEFUN([OCTAVE_IEEE754_DATA_FORMAT], [
--- a/scripts/audio/@audioplayer/audioplayer.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/audio/@audioplayer/audioplayer.m	Tue Jul 07 19:40:20 2020 -0400
@@ -175,6 +175,15 @@
 %! properties = get (player, {"SampleRate", "Tag", "UserData"});
 %! assert (properties, {8000, "tag", [1, 2; 3, 4]});
 
+%!testif HAVE_PORTAUDIO; audiodevinfo (0) > 0
+%! ## Verify nbits option only accepts 8, 16, 24
+%! fail ("audioplayer (1, 8e3, 9)", "NBITS must be 8, 16, or 24");
+%! fail ("audioplayer (1, 8e3, 32)", "NBITS must be 8, 16, or 24");
+%! player = audioplayer (1, 8e3, 8);
+%! player = audioplayer (1, 8e3, 16);
+%! player = audioplayer (1, 8e3, 24);
+
+## FIXME: Callbacks do not work currently (5/31/2020) so BIST tests commented.
 #%!function [sound, status] = callback (samples)
 #%!  sound = rand (samples, 2) - 0.5;
 #%!  status = 0;
--- a/scripts/deprecated/module.mk	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/deprecated/module.mk	Tue Jul 07 19:40:20 2020 -0400
@@ -1,7 +1,6 @@
 FCN_FILE_DIRS += %reldir%
 
 %canon_reldir%_FCN_FILES = \
-  %reldir%/output_max_field_width.m \
   %reldir%/runtests.m
 
 %canon_reldir%dir = $(fcnfiledir)/deprecated
--- a/scripts/deprecated/output_max_field_width.m	Tue Jul 07 18:34:23 2020 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-########################################################################
-##
-## Copyright (C) 2018-2020 The Octave Project Developers
-##
-## See the file COPYRIGHT.md in the top-level directory of this
-## distribution or <https://octave.org/copyright/>.
-##
-## This file is part of Octave.
-##
-## Octave is free software: you can 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
-## <https://www.gnu.org/licenses/>.
-##
-########################################################################
-
-## -*- texinfo -*-
-## @deftypefn  {} {@var{val} =} output_max_field_width ()
-## @deftypefnx {} {@var{old_val} =} output_max_field_width (@var{new_val})
-## @deftypefnx {} {} output_max_field_width (@var{new_val}, "local")
-##
-## @code{output_max_field_width} is deprecated and will be removed in Octave
-## version 7.  Use @code{output_precision} instead.
-##
-## Query or set the internal variable that specifies the maximum width
-## of a numeric output field.
-##
-## When called from inside a function with the @qcode{"local"} option, the
-## variable is changed locally for the function and any subroutines it calls.
-## The original variable value is restored when exiting the function.
-## @seealso{format, fixed_point_format, output_precision}
-## @end deftypefn
-
-## FIXME: DEPRECATED: Remove in version 7.
-
-function retval = output_max_field_width (varargin)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "output_max_field_width is obsolete and will be removed from a future version of Octave, please use output_precision instead\n");
-  endif
-
-  retval = 20;
-
-endfunction
--- a/scripts/general/cart2pol.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/general/cart2pol.m	Tue Jul 07 19:40:20 2020 -0400
@@ -28,21 +28,47 @@
 ## @deftypefnx {} {[@var{theta}, @var{r}, @var{z}] =} cart2pol (@var{x}, @var{y}, @var{z})
 ## @deftypefnx {} {[@var{theta}, @var{r}] =} cart2pol (@var{C})
 ## @deftypefnx {} {[@var{theta}, @var{r}, @var{z}] =} cart2pol (@var{C})
-## @deftypefnx {} {@var{P} =} cart2pol (@dots{})
 ##
 ## Transform Cartesian coordinates to polar or cylindrical coordinates.
 ##
 ## The inputs @var{x}, @var{y} (, and @var{z}) must be the same shape, or
 ## scalar.  If called with a single matrix argument then each row of @var{C}
-## represents the Cartesian coordinate (@var{x}, @var{y} (, @var{z})).
+## represents the Cartesian coordinate pair (@var{x}, @var{y}) or triplet
+## (@var{x}, @var{y}, @var{z}).
 ##
-## @var{theta} describes the angle relative to the positive x-axis.
+## The outputs @var{theta}, @var{r} (, and @var{z}) match the shape of the
+## inputs.  For a matrix input @var{C} the outputs will be column vectors with
+## rows corresponding to the rows of the input matrix.
+##
+## @var{theta} describes the angle relative to the positive x-axis measured in
+## the xy-plane.
 ##
 ## @var{r} is the distance to the z-axis @w{(0, 0, z)}.
 ##
-## If only a single return argument is requested then return a matrix @var{P}
-## where each row represents one polar/(cylindrical) coordinate
-## (@var{theta}, @var{phi} (, @var{z})).
+## @var{z}, if present, is unchanged by the transformation.
+##
+## The coordinate transformation is computed using:
+##
+## @tex
+## $$ \theta = \arctan \left ( {y \over x} \right ) $$
+## $$ r = \sqrt{x^2 + y^2} $$
+## $$ z = z $$
+## @end tex
+## @ifnottex
+##
+## @example
+## @group
+## @var{theta} = arctan (@var{y} / @var{x})
+## @var{r} = sqrt (@var{x}^2 + @var{y}^2)
+## @var{z} = @var{z}
+## @end group
+## @end example
+##
+## @end ifnottex
+##
+## @c FIXME: Remove this note in Octave 9.1 (two releases after 7.1).
+## Note: For @sc{matlab} compatibility, this function no longer returns a full
+## coordinate matrix when called with a single return argument.
 ## @seealso{pol2cart, cart2sph, sph2cart}
 ## @end deftypefn
 
@@ -53,44 +79,54 @@
   endif
 
   if (nargin == 1)
-    if (! (isnumeric (x) && ismatrix (x)
-           && (columns (x) == 2 || columns (x) == 3)))
-      error ("cart2pol: matrix input must have 2 or 3 columns [X, Y (, Z)]");
+    if (! (isnumeric (x) && ismatrix (x)))
+      error ("cart2pol: matrix input must be 2-D numeric array");
     endif
-    if (columns (x) == 3)
-      z = x(:,3);
+    if (isvector (x))
+      n = numel (x);
+      if (n != 2 && n != 3)
+        error ("cart2pol: matrix input must be a 2- or 3-element vector or a 2- or 3-column array");
+      endif
+      if (n == 3)
+        z = x(3);
+      endif
+      y = x(2);
+      x = x(1);
+    else
+      ncols = columns (x);
+      if (ncols != 2 && ncols != 3)
+        error ("cart2pol: matrix input must be a 2- or 3-element vector or a 2- or 3-column array");
+      endif
+
+      if (ncols == 3)
+        z = x(:,3);
+      endif
+      y = x(:,2);
+      x = x(:,1);
     endif
-    y = x(:,2);
-    x = x(:,1);
+
   elseif (nargin == 2)
-    if (! isnumeric (x) || ! isnumeric (y))
-      error ("cart2pol: X, Y must be numeric arrays of the same size, or scalar");
+    if (! (isnumeric (x) && isnumeric (y)))
+      error ("cart2pol: X, Y must be numeric arrays or scalars");
     endif
     [err, x, y] = common_size (x, y);
     if (err)
-      error ("cart2pol: X, Y must be numeric arrays of the same size, or scalar");
+      error ("cart2pol: X, Y must be the same size or scalars");
     endif
+
   elseif (nargin == 3)
-    if (! isnumeric (x) || ! isnumeric (y) || ! isnumeric (z))
-      error ("cart2pol: X, Y, Z must be numeric arrays of the same size, or scalar");
+    if (! (isnumeric (x) && isnumeric (y) && isnumeric (z)))
+      error ("cart2pol: X, Y, Z must be numeric arrays or scalars");
     endif
     [err, x, y, z] = common_size (x, y, z);
     if (err)
-      error ("cart2pol: X, Y, Z must be numeric arrays of the same size, or scalar");
+      error ("cart2pol: X, Y, Z must be the same size or scalars");
     endif
   endif
 
   theta = atan2 (y, x);
   r = sqrt (x .^ 2 + y .^ 2);
 
-  if (nargout <= 1)
-    if (isempty (z))
-      theta = [theta(:), r(:)];
-    else
-      theta = [theta(:), r(:), z(:)];
-    endif
-  endif
-
 endfunction
 
 
@@ -104,9 +140,16 @@
 %!test
 %! x = [0, 1, 2];
 %! y = [0, 1, 2];
-%! P = cart2pol (x, y);
-%! assert (P(:,1), [0; pi/4; pi/4], sqrt (eps));
-%! assert (P(:,2), sqrt (2)*[0; 1; 2], sqrt (eps));
+%! [t, r] = cart2pol (x, y);
+%! assert (t, [0, pi/4, pi/4], eps);
+%! assert (r, sqrt (2)*[0, 1, 2], eps);
+
+%!test
+%! x = [0, 1, 2]';
+%! y = [0, 1, 2]';
+%! [t, r] = cart2pol (x, y);
+%! assert (t, [0; pi/4; pi/4], eps);
+%! assert (r, sqrt (2)*[0; 1; 2], eps);
 
 %!test
 %! x = [0, 1, 2];
@@ -146,13 +189,23 @@
 
 %!test
 %! C = [0, 0; 1, 1; 2, 2];
-%! P = [0, 0; pi/4, sqrt(2); pi/4, 2*sqrt(2)];
-%! assert (cart2pol (C), P, sqrt (eps));
+%! [t, r] = cart2pol (C);
+%! assert (t, [0; 1; 1]*pi/4, eps);
+%! assert (r, [0; 1; 2]*sqrt(2), eps);
 
 %!test
 %! C = [0, 0, 0; 1, 1, 1; 2, 2, 2];
-%! P = [0, 0, 0; pi/4, sqrt(2), 1; pi/4, 2*sqrt(2), 2];
-%! assert (cart2pol (C), P, sqrt (eps));
+%! [t, r, z] = cart2pol (C);
+%! assert (t, [0; 1; 1]*pi/4, eps);
+%! assert (r, [0; 1; 2]*sqrt(2), eps);
+%! assert (z, [0; 1; 2]);
+
+%!test
+%! C = [0, 0, 0; 1, 1, 1; 2, 2, 2;1, 1, 1];
+%! [t, r, z] = cart2pol (C);
+%! assert (t, [0; 1; 1; 1]*pi/4, eps);
+%! assert (r, [0; 1; 2; 1]*sqrt(2), eps);
+%! assert (z, [0; 1; 2; 1]);
 
 %!test
 %! x = zeros (1, 1, 1, 2);
@@ -179,15 +232,17 @@
 ## Test input validation
 %!error cart2pol ()
 %!error cart2pol (1,2,3,4)
-%!error <matrix input must have 2 or 3 columns> cart2pol ({1,2,3})
-%!error <matrix input must have 2 or 3 columns> cart2pol (ones (3,3,2))
-%!error <matrix input must have 2 or 3 columns> cart2pol ([1])
-%!error <matrix input must have 2 or 3 columns> cart2pol ([1,2,3,4])
-%!error <numeric arrays of the same size> cart2pol ({1,2,3}, [1,2,3])
-%!error <numeric arrays of the same size> cart2pol ([1,2,3], {1,2,3})
-%!error <numeric arrays of the same size> cart2pol (ones (3,3,3), ones (3,2,3))
-%!error <numeric arrays of the same size> cart2pol ({1,2,3}, [1,2,3], [1,2,3])
-%!error <numeric arrays of the same size> cart2pol ([1,2,3], {1,2,3}, [1,2,3])
-%!error <numeric arrays of the same size> cart2pol ([1,2,3], [1,2,3], {1,2,3})
-%!error <numeric arrays of the same size> cart2pol (ones (3,3,3), 1, ones (3,2,3))
-%!error <numeric arrays of the same size> cart2pol (ones (3,3,3), ones (3,2,3), 1)
+%!error <matrix input must be 2-D numeric array> cart2pol ({1,2,3})
+%!error <matrix input must be 2-D numeric array> cart2pol (ones (3,3,2))
+%!error <matrix input must be a 2- or 3-element> cart2pol ([1])
+%!error <matrix input must be a 2- or 3-element> cart2pol ([1,2,3,4])
+%!error <must be numeric arrays or scalars> cart2pol ({1,2,3}, [1,2,3])
+%!error <must be numeric arrays or scalars> cart2pol ([1,2,3], {1,2,3})
+%!error <must be the same size or scalars> cart2pol (ones (3,3,3), ones (3,2,3))
+%!error <must be the same size or scalars> cart2pol ([1; 1], [2, 2])
+%!error <must be the same size or scalars> cart2pol ([1; 1], [2, 2], [3, 3])
+%!error <must be numeric arrays or scalars> cart2pol ({1,2,3}, [1,2,3], [1,2,3])
+%!error <must be numeric arrays or scalars> cart2pol ([1,2,3], {1,2,3}, [1,2,3])
+%!error <must be numeric arrays or scalars> cart2pol ([1,2,3], [1,2,3], {1,2,3})
+%!error <must be the same size or scalars> cart2pol (ones (3,3,3), 1, ones (3,2,3))
+%!error <must be the same size or scalars> cart2pol (ones (3,3,3), ones (3,2,3), 1)
--- a/scripts/general/cart2sph.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/general/cart2sph.m	Tue Jul 07 19:40:20 2020 -0400
@@ -26,22 +26,45 @@
 ## -*- texinfo -*-
 ## @deftypefn  {} {[@var{theta}, @var{phi}, @var{r}] =} cart2sph (@var{x}, @var{y}, @var{z})
 ## @deftypefnx {} {[@var{theta}, @var{phi}, @var{r}] =} cart2sph (@var{C})
-## @deftypefnx {} {@var{S} =} cart2sph (@dots{})
 ## Transform Cartesian coordinates to spherical coordinates.
 ##
 ## The inputs @var{x}, @var{y}, and @var{z} must be the same shape, or scalar.
-## If called with a single matrix argument then each row of @var{C} represents
-## the Cartesian coordinate (@var{x}, @var{y}, @var{z}).
+## If called with a single matrix argument then each row of @var{C} must
+## represent a Cartesian coordinate triplet (@var{x}, @var{y}, @var{z}).
 ##
-## @var{theta} describes the angle relative to the positive x-axis.
+## The outputs @var{theta}, @var{phi}, @var{r} match the shape of the inputs.
+## For a matrix input @var{C} the outputs will be column vectors with rows
+## corresponding to the rows of the input matrix.
 ##
-## @var{phi} is the angle relative to the xy-plane.
+## @var{theta} describes the azimuth angle relative to the positive x-axis
+## measured in the xy-plane.
+##
+## @var{phi} is the elevation angle measured relative to the xy-plane.
 ##
 ## @var{r} is the distance to the origin @w{(0, 0, 0)}.
 ##
-## If only a single return argument is requested then return a matrix @var{S}
-## where each row represents one spherical coordinate
-## (@var{theta}, @var{phi}, @var{r}).
+## The coordinate transformation is computed using:
+##
+## @tex
+## $$ \theta = \arctan \left ({y \over x} \right ) $$
+## $$ \phi = \arctan \left ( {z \over {\sqrt{x^2+y^2}}} \right ) $$
+## $$ r = \sqrt{x^2 + y^2 + z^2} $$
+## @end tex
+## @ifnottex
+##
+## @example
+## @group
+## @var{theta} = arctan (@var{y} / @var{x})
+## @var{phi} = arctan (@var{z} / sqrt (@var{x}^2 + @var{y}^2))
+## @var{r} = sqrt (@var{x}^2 + @var{y}^2 + @var{z}^2)
+## @end group
+## @end example
+##
+## @end ifnottex
+##
+## @c FIXME: Remove this note in Octave 9.1 (two releases after 7.1).
+## Note: For @sc{matlab} compatibility, this function no longer returns a full
+## coordinate matrix when called with a single return argument.
 ## @seealso{sph2cart, cart2pol, pol2cart}
 ## @end deftypefn
 
@@ -52,19 +75,29 @@
   endif
 
   if (nargin == 1)
-    if (! (isnumeric (x) && ismatrix (x) && columns (x) == 3))
-      error ("cart2sph: matrix input must have 3 columns [X, Y, Z]");
+    if (! (isnumeric (x) && ismatrix (x)))
+      error ("cart2sph: matrix input C must be a 2-D numeric array");
+    elseif (columns (x) != 3 && numel (x) != 3)
+      error ("cart2sph: matrix input C must be a 3-element vector or 3-column array");
     endif
-    z = x(:,3);
-    y = x(:,2);
-    x = x(:,1);
+
+    if (numel (x) == 3)
+      z = x(3);
+      y = x(2);
+      x = x(1);
+    else
+      z = x(:,3);
+      y = x(:,2);
+      x = x(:,1);
+    endif
+
   else
-    if (! isnumeric (x) || ! isnumeric (y) || ! isnumeric (z))
-      error ("cart2sph: X, Y, Z must be numeric arrays of the same size, or scalar");
+    if (! (isnumeric (x) && isnumeric (y) && isnumeric (z)))
+      error ("cart2sph: X, Y, Z must be numeric arrays or scalars");
     endif
     [err, x, y, z] = common_size (x, y, z);
     if (err)
-      error ("cart2sph: X, Y, Z must be numeric arrays of the same size, or scalar");
+      error ("cart2sph: X, Y, Z must be the same size or scalars");
     endif
   endif
 
@@ -72,10 +105,6 @@
   phi = atan2 (z, sqrt (x .^ 2 + y .^ 2));
   r = sqrt (x .^ 2 + y .^ 2 + z .^ 2);
 
-  if (nargout <= 1)
-    theta = [theta(:), phi(:), r(:)];
-  endif
-
 endfunction
 
 
@@ -89,13 +118,22 @@
 %! assert (r, [0, 1, 2]*sqrt (3), eps);
 
 %!test
+%! x = [0; 1; 2];
+%! y = [0; 1; 2];
+%! z = [0; 1; 2];
+%! [t, p, r] = cart2sph (x, y, z);
+%! assert (t, [0; pi/4; pi/4], eps);
+%! assert (p, [0; 1; 1] * atan (sqrt (0.5)), eps);
+%! assert (r, [0; 1; 2] * sqrt (3), eps);
+
+%!test
 %! x = 0;
 %! y = [0, 1, 2];
 %! z = [0, 1, 2];
-%! S = cart2sph (x, y, z);
-%! assert (S(:,1), [0; 1; 1] * pi/2, eps);
-%! assert (S(:,2), [0; 1; 1] * pi/4, eps);
-%! assert (S(:,3), [0; 1; 2] * sqrt (2), eps);
+%! [t, p, r] = cart2sph (x, y, z);
+%! assert (t, [0, 1, 1] * pi/2, eps);
+%! assert (p, [0, 1, 1] * pi/4, eps);
+%! assert (r, [0, 1, 2] * sqrt (2), eps);
 
 %!test
 %! x = [0, 1, 2];
@@ -103,17 +141,17 @@
 %! z = [0, 1, 2];
 %! [t, p, r] = cart2sph (x, y, z);
 %! assert (t, [0, 0, 0]);
-%! assert (p, [0, 1, 1] * pi/4);
-%! assert (r, [0, 1, 2] * sqrt (2));
+%! assert (p, [0, 1, 1] * pi/4, eps);
+%! assert (r, [0, 1, 2] * sqrt (2), eps);
 
 %!test
 %! x = [0, 1, 2];
 %! y = [0, 1, 2];
 %! z = 0;
 %! [t, p, r] = cart2sph (x, y, z);
-%! assert (t, [0, 1, 1] * pi/4);
+%! assert (t, [0, 1, 1] * pi/4, eps);
 %! assert (p, [0, 0, 0]);
-%! assert (r, [0, 1, 2] * sqrt (2));
+%! assert (r, [0, 1, 2] * sqrt (2), eps);
 
 %!test
 %! x = 0;
@@ -121,13 +159,22 @@
 %! z = [0, 1, 2];
 %! [t, p, r] = cart2sph (x, y, z);
 %! assert (t, [0, 0, 0]);
-%! assert (p, [0, 1, 1] * pi/2);
+%! assert (p, [0, 1, 1] * pi/2, eps);
 %! assert (r, [0, 1, 2]);
 
 %!test
 %! C = [0, 0, 0; 1, 0, 1; 2, 0, 2];
-%! S = [0, 0, 0; 0, pi/4, sqrt(2); 0, pi/4, 2*sqrt(2)];
-%! assert (cart2sph (C), S, eps);
+%! [t, p, r] = cart2sph (C);
+%! assert (t, [0; 0; 0]);
+%! assert (p, [0; 1; 1] * pi/4, eps);
+%! assert (r, [0; 1; 2] * sqrt (2), eps);
+
+%!test
+%! C = [0, 0, 0; 1, 0, 1; 2, 0, 2; 1, 0, 1];
+%! [t, p, r] = cart2sph (C);
+%! assert (t, [0; 0; 0; 0]);
+%! assert (p, [0; 1; 1; 1] * pi/4, eps);
+%! assert (r, [0; 1; 2; 1] * sqrt (2), eps);
 
 %!test
 %! [x, y, z] = meshgrid ([0, 1], [0, 1], [0, 1]);
@@ -145,11 +192,13 @@
 %!error cart2sph ()
 %!error cart2sph (1,2)
 %!error cart2sph (1,2,3,4)
-%!error <matrix input must have 3 columns> cart2sph ({1,2,3})
-%!error <matrix input must have 3 columns> cart2sph (ones (3,3,2))
-%!error <matrix input must have 3 columns> cart2sph ([1,2,3,4])
-%!error <numeric arrays of the same size> cart2sph ({1,2,3}, [1,2,3], [1,2,3])
-%!error <numeric arrays of the same size> cart2sph ([1,2,3], {1,2,3}, [1,2,3])
-%!error <numeric arrays of the same size> cart2sph ([1,2,3], [1,2,3], {1,2,3})
-%!error <numeric arrays of the same size> cart2sph (ones (3,3,3), 1, ones (3,2,3))
-%!error <numeric arrays of the same size> cart2sph (ones (3,3,3), ones (3,2,3), 1)
+%!error <matrix input C must be a 2-D numeric array> cart2sph ({1,2,3})
+%!error <matrix input C must be a 2-D numeric array> cart2sph (ones (3,3,2))
+%!error <matrix input C must be a 3-element> cart2sph ([1,2,3,4])
+%!error <matrix input C must be a 3-element> cart2sph ([1,2,3,4; 1,2,3,4; 1,2,3,4])
+%!error <must be numeric arrays or scalars> cart2sph ({1,2,3}, [1,2,3], [1,2,3])
+%!error <must be numeric arrays or scalars> cart2sph ([1,2,3], {1,2,3}, [1,2,3])
+%!error <must be numeric arrays or scalars> cart2sph ([1,2,3], [1,2,3], {1,2,3})
+%!error <must be the same size or scalars> cart2sph ([1,2,3], [1,2,3], [1,2,3]')
+%!error <must be the same size or scalars> cart2sph (ones (3,3,3), 1, ones (3,2,3))
+%!error <must be the same size or scalars> cart2sph (ones (3,3,3), ones (3,2,3), 1)
--- a/scripts/general/module.mk	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/general/module.mk	Tue Jul 07 19:40:20 2020 -0400
@@ -60,6 +60,7 @@
   %reldir%/repelem.m \
   %reldir%/repmat.m \
   %reldir%/rescale.m \
+  %reldir%/rng.m \
   %reldir%/rot90.m \
   %reldir%/rotdim.m \
   %reldir%/shift.m \
--- a/scripts/general/pol2cart.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/general/pol2cart.m	Tue Jul 07 19:40:20 2020 -0400
@@ -28,21 +28,43 @@
 ## @deftypefnx {} {[@var{x}, @var{y}, @var{z}] =} pol2cart (@var{theta}, @var{r}, @var{z})
 ## @deftypefnx {} {[@var{x}, @var{y}] =} pol2cart (@var{P})
 ## @deftypefnx {} {[@var{x}, @var{y}, @var{z}] =} pol2cart (@var{P})
-## @deftypefnx {} {@var{C} =} pol2cart (@dots{})
 ## Transform polar or cylindrical coordinates to Cartesian coordinates.
 ##
 ## The inputs @var{theta}, @var{r}, (and @var{z}) must be the same shape, or
 ## scalar.  If called with a single matrix argument then each row of @var{P}
-## represents the polar/(cylindrical) coordinate (@var{theta}, @var{r}
-## (, @var{z})).
+## represents the polar coordinate pair (@var{theta}, @var{r}) or the
+## cylindrical triplet (@var{theta}, @var{r}, @var{z}).
+##
+## The outputs @var{x}, @var{y} (, and @var{z}) match the shape of the inputs.
+## For a matrix input @var{P} the outputs will be column vectors with rows
+## corresponding to the rows of the input matrix.
 ##
-## @var{theta} describes the angle relative to the positive x-axis.
+## @var{theta} describes the angle relative to the positive x-axis measured in
+## the xy-plane.
+##
+## @var{r} is the distance to the z-axis @w{(0, 0, z)}.
+##
+## @var{z}, if present, is unchanged by the transformation.
+##
+## The coordinate transformation is computed using:
 ##
-## @var{r} is the distance to the z-axis (0, 0, z).
+## @tex
+## $$ x = r \cos \theta $$
+## $$ y = r \sin \theta $$
+## $$ z = z $$
+## @end tex
+## @ifnottex
 ##
-## If only a single return argument is requested then return a matrix @var{C}
-## where each row represents one Cartesian coordinate
-## (@var{x}, @var{y} (, @var{z})).
+## @example
+## @var{x} = @var{r} * cos (@var{theta})
+## @var{y} = @var{r} * sin (@var{theta})
+## @var{z} = @var{z}
+## @end example
+##
+## @end ifnottex
+## @c FIXME: Remove this note in Octave 9.1 (two releases after 7.1).
+## Note: For @sc{matlab} compatibility, this function no longer returns a full
+## coordinate matrix when called with a single return argument.
 ## @seealso{cart2pol, sph2cart, cart2sph}
 ## @end deftypefn
 
@@ -53,44 +75,55 @@
   endif
 
   if (nargin == 1)
-    if (! (isnumeric (theta) && ismatrix (theta)
-           && (columns (theta) == 2 || columns (theta) == 3)))
-      error ("pol2cart: matrix input must have 2 or 3 columns [THETA, R (, Z)]");
+    if (! (isnumeric (theta) && ismatrix (theta)))
+      error ("cart2pol: matrix input P must be 2-D numeric array");
     endif
-    if (columns (theta) == 3)
-      z = theta(:,3);
+    if (isvector (theta))
+      n = numel (theta);
+      if (n != 2 && n != 3)
+        error ("cart2pol: matrix input must be a 2- or 3-element vector or a 2- or 3-column array");
+      endif
+      if (n == 3)
+        z = theta(3);
+      endif
+      r = theta(2);
+      theta = theta(1);
+
+    else
+      ncols = columns(theta);
+      if (ncols != 2 && ncols != 3)
+        error ("cart2pol: matrix input must be a 2- or 3-element vector or a 2- or 3-column array");
+      endif
+
+      if (ncols == 3)
+        z = theta(:,3);
+      endif
+      r = theta(:,2);
+      theta = theta(:,1);
     endif
-    r = theta(:,2);
-    theta = theta(:,1);
+
   elseif (nargin == 2)
-    if (! isnumeric (theta) || ! isnumeric (r))
-      error ("pol2cart: THETA, R must be numeric arrays of the same size, or scalar");
+    if (! (isnumeric (theta) && isnumeric (r)))
+      error ("pol2cart: THETA, R must be numeric arrays or scalars");
     endif
     [err, theta, r] = common_size (theta, r);
     if (err)
-      error ("pol2cart: THETA, R must be numeric arrays of the same size, or scalar");
+      error ("pol2cart: THETA, R must be the same size or scalars");
     endif
+
   elseif (nargin == 3)
-    if (! isnumeric (theta) || ! isnumeric (r) || ! isnumeric (z))
-      error ("pol2cart: THETA, R, Z must be numeric arrays of the same size, or scalar");
+    if (! (isnumeric (theta) && isnumeric (r) && isnumeric (z)))
+      error ("pol2cart: THETA, R, Z must be numeric arrays or scalars");
     endif
     [err, theta, r, z] = common_size (theta, r, z);
     if (err)
-      error ("pol2cart: THETA, R, Z must be numeric arrays of the same size, or scalar");
+      error ("pol2cart: THETA, R, Z must be the same size or scalars");
     endif
   endif
 
   x = r .* cos (theta);
   y = r .* sin (theta);
 
-  if (nargout <= 1)
-    if (isempty (z))
-      x = [x(:), y(:)];
-    else
-      x = [x(:), y(:), z(:)];
-    endif
-  endif
-
 endfunction
 
 
@@ -98,32 +131,42 @@
 %! t = [0, 0.5, 1] * pi;
 %! r = 1;
 %! [x, y] = pol2cart (t, r);
-%! assert (x, [1, 0, -1], sqrt (eps));
-%! assert (y, [0, 1,  0], sqrt (eps));
+%! assert (x, [1, 0, -1], eps);
+%! assert (y, [0, 1,  0], eps);
 
 %!test
 %! t = [0, 1, 1] * pi/4;
 %! r = sqrt (2) * [0, 1, 2];
-%! C = pol2cart (t, r);
-%! assert (C(:,1), [0; 1; 2], sqrt (eps));
-%! assert (C(:,2), [0; 1; 2], sqrt (eps));
+%! [x, y] = pol2cart (t, r);
+%! assert (x, [0, 1, 2], 2*eps);
+%! assert (y, [0, 1, 2], 2*eps);
 
 %!test
 %! t = [0, 1, 1] * pi/4;
 %! r = sqrt (2) * [0, 1, 2];
 %! z = [0, 1, 2];
 %! [x, y, z2] = pol2cart (t, r, z);
-%! assert (x, [0, 1, 2], sqrt (eps));
-%! assert (y, [0, 1, 2], sqrt (eps));
+%! assert (x, [0, 1, 2], 2*eps);
+%! assert (y, [0, 1, 2], 2*eps);
 %! assert (z2, z);
 
 %!test
+%! t = [0; 1; 1] * pi/4;
+%! r = sqrt (2) * [0; 1; 2];
+%! z = [0; 1; 2];
+%! [x, y, z2] = pol2cart (t, r, z);
+%! assert (x, [0; 1; 2], 2*eps);
+%! assert (y, [0; 1; 2], 2*eps);
+%! assert (z2, z);
+
+
+%!test
 %! t = 0;
 %! r = [0, 1, 2];
 %! z = [0, 1, 2];
 %! [x, y, z2] = pol2cart (t, r, z);
-%! assert (x, [0, 1, 2], sqrt (eps));
-%! assert (y, [0, 0, 0], sqrt (eps));
+%! assert (x, [0, 1, 2], eps);
+%! assert (y, [0, 0, 0], eps);
 %! assert (z2, z);
 
 %!test
@@ -146,13 +189,23 @@
 
 %!test
 %! P = [0, 0; pi/4, sqrt(2); pi/4, 2*sqrt(2)];
-%! C = [0, 0; 1, 1; 2, 2];
-%! assert (pol2cart (P), C, sqrt (eps));
+%! [x, y] = pol2cart(P);
+%! assert (x, [0; 1; 2], 2*eps);
+%! assert (y, [0; 1; 2], 2*eps);
 
 %!test
 %! P = [0, 0, 0; pi/4, sqrt(2), 1; pi/4, 2*sqrt(2), 2];
-%! C = [0, 0, 0; 1, 1, 1; 2, 2, 2];
-%! assert (pol2cart (P), C, sqrt (eps));
+%! [x, y, z] = pol2cart(P);
+%! assert (x, [0; 1; 2], 2*eps);
+%! assert (y, [0; 1; 2], 2*eps);
+%! assert (z, P(:,3), 2*eps);
+
+%!test
+%! P = [0, 0, 0; pi/4, sqrt(2), 1; pi/4, 2*sqrt(2), 2; 0, 0, 0];
+%! [x, y, z] = pol2cart(P);
+%! assert (x, [0; 1; 2; 0], 2*eps);
+%! assert (y, [0; 1; 2; 0], 2*eps);
+%! assert (z, P(:,3), 2*eps);
 
 %!test
 %! r = ones (1, 1, 1, 2);
@@ -182,15 +235,17 @@
 ## Test input validation
 %!error pol2cart ()
 %!error pol2cart (1,2,3,4)
-%!error <matrix input must have 2 or 3 columns> pol2cart ({1,2,3})
-%!error <matrix input must have 2 or 3 columns> pol2cart (ones (3,3,2))
-%!error <matrix input must have 2 or 3 columns> pol2cart ([1])
-%!error <matrix input must have 2 or 3 columns> pol2cart ([1,2,3,4])
-%!error <numeric arrays of the same size> pol2cart ({1,2,3}, [1,2,3])
-%!error <numeric arrays of the same size> pol2cart ([1,2,3], {1,2,3})
-%!error <numeric arrays of the same size> pol2cart (ones (3,3,3), ones (3,2,3))
-%!error <numeric arrays of the same size> pol2cart ({1,2,3}, [1,2,3], [1,2,3])
-%!error <numeric arrays of the same size> pol2cart ([1,2,3], {1,2,3}, [1,2,3])
-%!error <numeric arrays of the same size> pol2cart ([1,2,3], [1,2,3], {1,2,3})
-%!error <numeric arrays of the same size> pol2cart (ones (3,3,3), 1, ones (3,2,3))
-%!error <numeric arrays of the same size> pol2cart (ones (3,3,3), ones (3,2,3), 1)
+%!error <matrix input P must be 2-D numeric array> pol2cart ({1,2,3})
+%!error <matrix input P must be 2-D numeric array> pol2cart (ones (3,3,2))
+%!error <matrix input must be a 2- or 3-element> pol2cart ([1])
+%!error <matrix input must be a 2- or 3-element> pol2cart ([1,2,3,4])
+%!error <must be numeric arrays or scalars> pol2cart ({1,2,3}, [1,2,3])
+%!error <must be numeric arrays or scalars> pol2cart ([1,2,3], {1,2,3})
+%!error <must be the same size or scalars> pol2cart (ones (3,3,3), ones (3,2,3))
+%!error <must be the same size or scalars> pol2cart ([1; 1], [2, 2])
+%!error <must be the same size or scalars> pol2cart ([1; 1], [2, 2], [3, 3])
+%!error <must be numeric arrays or scalars> pol2cart ({1,2,3}, [1,2,3], [1,2,3])
+%!error <must be numeric arrays or scalars> pol2cart ([1,2,3], {1,2,3}, [1,2,3])
+%!error <must be numeric arrays or scalars> pol2cart ([1,2,3], [1,2,3], {1,2,3})
+%!error <must be the same size or scalars> pol2cart (ones (3,3,3), 1, ones (3,2,3))
+%!error <must be the same size or scalars> pol2cart (ones (3,3,3), ones (3,2,3), 1)
--- a/scripts/general/randi.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/general/randi.m	Tue Jul 07 19:40:20 2020 -0400
@@ -189,13 +189,9 @@
 
 ## Test that no warning thrown if IMAX is exactly on the limits of the range
 %!function test_no_warning (func, varargin)
-%!  state = warning ("query");
-%!  unwind_protect
-%!    warning ("error", "all");
-%!    func (varargin{:});
-%!  unwind_protect_cleanup
-%!    warning (state);
-%!  end_unwind_protect
+%!  lastwarn ("");
+%!  func (varargin{:});
+%!  assert (lastwarn (), "");
 %!endfunction
 %!test test_no_warning (@randi, max_int8, "int8");
 %!test test_no_warning (@randi, max_uint8, "uint8");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/general/rng.m	Tue Jul 07 19:40:20 2020 -0400
@@ -0,0 +1,303 @@
+########################################################################
+##
+## Copyright (C) 2020 The Octave Project Developers
+##
+## See the file COPYRIGHT.md in the top-level directory of this
+## distribution or <https://octave.org/copyright/>.
+##
+## This file is part of Octave.
+##
+## Octave is free software: you can 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
+## <https://www.gnu.org/licenses/>.
+##
+########################################################################
+
+## -*- texinfo -*-
+## @deftypefn  {} {} rng (@var{seed})
+## @deftypefnx {} {} rng (@var{seed}, "@var{generator}")
+## @deftypefnx {} {} rng ("shuffle")
+## @deftypefnx {} {} rng ("shuffle", "@var{generator}")
+## @deftypefnx {} {} rng ("default")
+## @deftypefnx {} {@var{s} =} rng ()
+## @deftypefnx {} {} rng (@var{s})
+## @deftypefnx {} {@var{s} =} rng (@dots{})
+## Set or query the seed of the random number generator used by @code{rand} and
+## @code{randn}.
+##
+## The input @code{seed} is a scalar numeric value used to initialize the state
+## vector of the random number generator.
+##
+## The optional string @var{generator} specifies the type of random number
+## generator to be used.  Its value can be @qcode{"twister"},
+## @qcode{"v5uniform"}, or @qcode{"v5normal"}.  The @qcode{"twister"} keyword
+## is described below.  @qcode{"v5uniform"} and @qcode{"v5normal"} refer to
+## older versions of Octave that used to use a different random number
+## generator.
+##
+## The state or seed of the random number generator can be reset to a new
+## random value using the @qcode{"shuffle"} keyword.
+##
+## The random number generator can be reset to default values using the
+## @qcode{"default"} keyword.  The default values are to use the Mersenne
+## Twister generator with a seed of 0.
+##
+## The optional return value @var{s} contains the state of the random number
+## generator at the time the function is called (i.e., before it might be
+## modified according to the input arguments).  It is encoded as a structure
+## variable with three fields: @qcode{"Type"}, @qcode{"Seed"}, and
+## @qcode{"State"}.  The random number generator can be restored to the state
+## @var{s} using @code{rng (@var{s})}.  This is useful when the identical
+## sequence of pseudo-random numbers is required for an algorithm. 
+##
+## By default, and with the @qcode{"twister"} option, pseudo-random sequences
+## are computed using the Mersenne Twister with a period of @math{2^{19937}-1}
+## (See @nospell{M. Matsumoto and T. Nishimura},
+## @cite{Mersenne Twister: A 623-dimensionally equidistributed uniform
+## pseudorandom number generator},
+## @nospell{ACM} Trans.@: on Modeling and Computer Simulation Vol.@: 8, No.@: 1,
+## pp.@: 3--30, January 1998,
+## @url{http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html}).
+## Do @strong{not} use for cryptography without securely hashing several
+## returned values together, otherwise the generator state can be learned after
+## reading 624 consecutive values.
+##
+## @seealso{rand, randn}
+## @end deftypefn
+
+function retval = rng (varargin)
+
+  if (nargin > 2)
+    print_usage ();
+  endif
+
+  ## Store current settings of random number generator
+  ## FIXME: there doesn't seem to be a way to query the type of generator
+  ##        currently used in Octave - assume "twister".
+  ## FIXME: there doesn't seem to be a way to query the seed initialization
+  ##        value - use "Not applicable".
+  ## FIXME: rand and randn use different generators - storing both states.
+  ## For older Matlab generators (v4, v5), the settings are stored like this:
+  ##   struct ("Type","Legacy", "Seed", "Not applicable", "State",{[],[],...})
+
+  ## Type is the generator name.
+  ## Seed is the initial seed value.
+  ## State is a structure describing internal state of the generator.
+  s = struct ("Type", "twister",
+              "Seed", "Not applicable",
+              "State", {{rand("state"), randn("state")}});
+
+  if (nargin == 0)
+    retval = s;
+    return;
+  endif
+
+  arg1 = varargin{1};
+  if (isscalar (arg1) && isnumeric (arg1) && isreal (arg1) && arg1 >= 0)
+    s_rand = s_randn = arg1;
+    generator = check_generator (varargin(2:end));
+
+  elseif (ischar (arg1) && strcmpi (arg1, "shuffle"))
+    ## Seed the random number generator based on the current time
+    s_rand = s_randn = "reset";  # or sum (1000*clock)
+    generator = check_generator (varargin(2:end));
+
+  elseif (ischar (arg1) && strcmpi (arg1, "default") && nargin == 1)
+    generator = "twister";
+    s_rand = s_randn = 0;  # FIXME: In Matlab, seed 0 corresponds to 5489
+
+  elseif (isstruct (arg1) && isscalar (arg1) && nargin == 1)
+    if (numfields (arg1) != 3
+        || ! all (isfield (arg1, {"Type", "Seed", "State"})))
+      error ('rng: input structure requires "Type", "Seed", "State" fields"');
+    endif
+    ## Only the internal state "State" and generator type "Type" are needed
+    generator = arg1.Type;
+    if (iscell (arg1.State))
+      [s_rand, s_randn] = deal (arg1.State{:});
+    else
+      s_rand = s_randn = arg1.State;
+    endif
+
+  else
+    print_usage ();
+  endif
+
+  ## Set the type of random number generator and seed it
+  if (isempty (generator))
+    generator = s.Type;
+  endif
+  switch (generator)
+    case "twister"
+      rand ("state", s_rand);
+      randn ("state", s_randn);
+
+    case "legacy"
+      rand ("seed", s_rand);
+      randn ("seed", s_randn);
+
+    case "v5uniform"
+      rand ("seed", s_rand);
+
+    case "v5normal"
+      randn ("seed", s_randn);
+
+    otherwise
+      error ('rng: invalid GENERATOR: "%s"', generator);
+
+  endswitch
+
+  if (nargout > 0)
+    retval = s;
+  endif
+
+endfunction
+
+
+function gen = check_generator (val)
+  if (isempty (val))
+    gen = "";
+    return;
+  elseif (! iscellstr (val))
+    error ("rng: GENERATOR must be a string");
+  endif
+  gen = tolower (char (val));
+  if (any (strcmp (gen, {"simdtwister", "combrecursive", "philox", "threefry", "multfibonacci", "v4"})))
+    error ('rng: random number generator "%s" is not available in Octave', gen);
+  elseif (! any (strcmp (gen, {"twister", "v5uniform", "v5normal"})))
+    error ('rng: unknown random number generator "%s"', gen);
+  endif
+endfunction
+
+
+%!test
+%! state = rng ();
+%! unwind_protect
+%!   rng (42);
+%!   ru1 = rand ();
+%!   rn1 = randn ();
+%!   rng (42);
+%!   ru2 = rand ();
+%!   rn2 = randn ();
+%!   assert (ru2, ru1);
+%!   assert (rn2, rn1);
+%!   s1 = rng ();
+%!   s2 = rng (42);
+%!   assert (isequal (s1, s2));
+%!   ru1 = rand ();
+%!   rn1 = randn ();
+%!   s3 = rng (42);
+%!   ru2 = rand ();
+%!   rn2 = randn ();
+%!   assert (ru2, ru1);
+%!   assert (rn2, rn1);
+%! unwind_protect_cleanup
+%!   rng (state);
+%! end_unwind_protect
+
+%!test
+%! state = rng ();
+%! unwind_protect
+%!   rng (42, "twister");
+%!   ru1 = rand ();
+%!   rn1 = randn ();
+%!   rng (42, "twister");
+%!   ru2 = rand ();
+%!   rn2 = randn ();
+%!   assert (ru2, ru1);
+%!   assert (rn2, rn1);
+%!   s1 = rng ();
+%!   s2 = rng (42, "twister");
+%!   assert (isequal (s1, s2));
+%!   ru1 = rand ();
+%!   rn1 = randn ();
+%!   s3 = rng (42, "twister");
+%!   ru2 = rand ();
+%!   rn2 = randn ();
+%!   assert (ru2, ru1);
+%!   assert (rn2, rn1);
+%! unwind_protect_cleanup
+%!   rng (state);
+%! end_unwind_protect
+
+%!test
+%! state = rng ();
+%! unwind_protect
+%!   rng ("shuffle");
+%!   rng ("shuffle", "twister");
+%!   s = rng ("shuffle");
+%!   assert (! isequal (s, rng ("shuffle")));
+%!   s = rng ("shuffle", "twister");
+%!   assert (! isequal (s, rng ("shuffle", "twister")));
+%! unwind_protect_cleanup
+%!   rng (state);
+%! end_unwind_protect
+
+%!test
+%! state = rng ();
+%! unwind_protect
+%!   rng ("default");
+%!   ru1 = rand ();
+%!   rn1 = randn ();
+%!   rng (0, "twister");
+%!   ru2 = rand ();
+%!   rn2 = randn ();
+%!   assert (ru2, ru1);
+%!   assert (rn2, rn1);
+%!   rng (0, "twister");
+%!   s = rng ("default");
+%!   assert (isequal (s, rng ()));
+%! unwind_protect_cleanup
+%!   rng (state);
+%! end_unwind_protect
+
+%!test
+%! state = rng ();
+%! unwind_protect
+%!   s = rng ();
+%!   ru1 = rand ();
+%!   rn1 = randn ();
+%!   rng (s);
+%!   ru2 = rand ();
+%!   rn2 = randn ();
+%!   assert (ru2, ru1);
+%!   assert (rn2, rn1);
+%!   rng (42);  rand (1,2);  x = rand (1,2);
+%!   rng (42);  rand (1,2);  s = rng ();  y = rand (1,2);
+%!   assert (x, y);
+%!   rng (s);  z = rand (1,2);
+%!   assert (x, z);
+%!   s1 = rng ();
+%!   s2 = rng (s1);
+%!   assert (isequal (s1, s2));
+%! unwind_protect_cleanup
+%!   rng (state);
+%! end_unwind_protect
+
+## Test input validation
+%!error <Invalid call> rng (1, 2, 3)
+%!error <Invalid call> rng (eye (2))
+%!error <Invalid call> rng ({})
+%!error <Invalid call> rng (2i)
+%!error <Invalid call> rng (-2)
+%!error <Invalid call> rng ("foobar")
+%!error <Invalid call> rng ("default", "twister")
+%!error <Invalid call> rng (struct ("Seed", {1, 2}))
+%!error <Invalid call> rng (struct ("Type",[],"State",[],"Seed",[]), "twister")
+%!error <input structure requires "Type"> rng (struct ())
+%!error <input structure requires "Type">
+%! rng (struct ("Type1",[],"State",[],"Seed",[]));
+%!error <GENERATOR must be a string> rng (0, struct ())
+%!error <"philox" is not available in Octave> rng (0, "philox")
+%!error <GENERATOR must be a string> rng ("shuffle", struct ())
+%!error <unknown random number generator "foobar"> rng ("shuffle", "foobar")
--- a/scripts/general/sph2cart.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/general/sph2cart.m	Tue Jul 07 19:40:20 2020 -0400
@@ -26,22 +26,43 @@
 ## -*- texinfo -*-
 ## @deftypefn  {} {[@var{x}, @var{y}, @var{z}] =} sph2cart (@var{theta}, @var{phi}, @var{r})
 ## @deftypefnx {} {[@var{x}, @var{y}, @var{z}] =} sph2cart (@var{S})
-## @deftypefnx {} {@var{C} =} sph2cart (@dots{})
 ## Transform spherical coordinates to Cartesian coordinates.
 ##
 ## The inputs @var{theta}, @var{phi}, and @var{r} must be the same shape, or
 ## scalar.  If called with a single matrix argument then each row of @var{S}
-## represents the spherical coordinate (@var{theta}, @var{phi}, @var{r}).
+## must represent a spherical coordinate triplet (@var{theta}, @var{phi},
+## @var{r}).
 ##
-## @var{theta} describes the angle relative to the positive x-axis.
+## The outputs @var{x}, @var{y}, @var{z} match the shape of the inputs.  For a
+## matrix input @var{S} the outputs are column vectors with rows corresponding
+## to the rows of the input matrix.
 ##
-## @var{phi} is the angle relative to the xy-plane.
+## @var{theta} describes the azimuth angle relative to the positive x-axis
+## measured in the xy-plane.
+##
+## @var{phi} is the elevation angle measured relative to the xy-plane.
 ##
 ## @var{r} is the distance to the origin @w{(0, 0, 0)}.
 ##
-## If only a single return argument is requested then return a matrix @var{C}
-## where each row represents one Cartesian coordinate
-## (@var{x}, @var{y}, @var{z}).
+## The coordinate transformation is computed using:
+##
+## @tex
+## $$ x = r \cos \phi  \cos \theta $$
+## $$ y = r \cos \phi  \sin \theta $$
+## $$ z = r \sin \phi $$
+## @end tex
+## @ifnottex
+##
+## @example
+## @var{x} = r * cos (@var{phi}) * cos (@var{theta})
+## @var{y} = r * cos (@var{phi}) * sin (@var{theta})
+## @var{z} = r * sin (@var{phi})
+## @end example
+##
+## @end ifnottex
+## @c FIXME: Remove this note in Octave 9.1 (two releases after 7.1).
+## Note: For @sc{matlab} compatibility, this function no longer returns a full
+## coordinate matrix when called with a single return argument.
 ## @seealso{cart2sph, pol2cart, cart2pol}
 ## @end deftypefn
 
@@ -52,19 +73,30 @@
   endif
 
   if (nargin == 1)
-    if (! (isnumeric (theta) && ismatrix (theta) && columns (theta) == 3))
-      error ("sph2cart: matrix input must have 3 columns [THETA, PHI, R]");
+    if (! (isnumeric (theta) && ismatrix (theta)))
+      error ("sph2cart: matrix input must be a 2-D numeric array");
+    endif
+    if (columns (theta) != 3 && numel (theta) != 3)
+      error ("sph2cart: matrix input must be a 3-element vector or 3-column array");
     endif
-    r = theta(:,3);
-    phi = theta(:,2);
-    theta = theta(:,1);
+
+    if (numel (theta) == 3)
+      r = theta(3);
+      phi = theta(2);
+      theta = theta(1);
+    else
+      r = theta(:,3);
+      phi = theta(:,2);
+      theta = theta(:,1);
+    endif
+
   else
-    if (! isnumeric (theta) || ! isnumeric (phi) || ! isnumeric (r))
-      error ("sph2cart: THETA, PHI, R must be numeric arrays of the same size, or scalar");
+    if (! (isnumeric (theta) && isnumeric (phi) && isnumeric (r)))
+      error ("sph2cart: THETA, PHI, R must be numeric arrays or scalars");
     endif
     [err, theta, phi, r] = common_size (theta, phi, r);
     if (err)
-      error ("sph2cart: THETA, PHI, R must be numeric arrays of the same size, or scalar");
+      error ("sph2cart: THETA, PHI, R must be the same size or scalars");
     endif
   endif
 
@@ -72,10 +104,6 @@
   y = r .* cos (phi) .* sin (theta);
   z = r .* sin (phi);
 
-  if (nargout <= 1)
-    x = [x(:), y(:), z(:)];
-  endif
-
 endfunction
 
 
@@ -89,13 +117,22 @@
 %! assert (z, [0, 0, 0]);
 
 %!test
+%! t = [0; 0; 0];
+%! p = [0; 0; 0];
+%! r = [0; 1; 2];
+%! [x, y, z] = sph2cart (t, p, r);
+%! assert (x, [0; 1; 2]);
+%! assert (y, [0; 0; 0]);
+%! assert (z, [0; 0; 0]);
+
+%!test
 %! t = 0;
 %! p = [0, 0, 0];
 %! r = [0, 1, 2];
-%! C = sph2cart (t, p, r);
-%! assert (C(:,1), r(:));
-%! assert (C(:,2), [0; 0; 0]);
-%! assert (C(:,3), [0; 0; 0]);
+%! [x, y, z] = sph2cart (t, p, r);
+%! assert (x, [0, 1, 2]);
+%! assert (y, [0, 0, 0]);
+%! assert (z, [0, 0, 0]);
 
 %!test
 %! t = [0, 0, 0];
@@ -123,8 +160,18 @@
 
 %!test
 %! S = [ 0, 0, 1; 0.5*pi, 0, 1; pi, 0, 1];
-%! C = [ 1, 0, 0; 0, 1, 0; -1, 0, 0];
-%! assert (sph2cart (S), C, eps);
+%! [x, y, z] = sph2cart (S);
+%! assert (x, [1; 0; -1], eps);
+%! assert (y, [0; 1; 0], eps);
+%! assert (z, [0; 0; 0], eps);
+
+%!test
+%! S = [ 0, 0, 1; 0.5*pi, 0, 1; pi, 0, 1; pi, pi, 1];
+%! [x, y, z] = sph2cart (S);
+%! assert (x, [1; 0; -1; 1], eps);
+%! assert (y, [0; 1; 0; 0], eps);
+%! assert (z, [0; 0; 0; 0], eps);
+
 
 %!test
 %! [t, p, r] = meshgrid ([0, pi/2], [0, pi/2], [0, 1]);
@@ -143,11 +190,13 @@
 %!error sph2cart ()
 %!error sph2cart (1,2)
 %!error sph2cart (1,2,3,4)
-%!error <matrix input must have 3 columns> sph2cart ({1,2,3})
-%!error <matrix input must have 3 columns> sph2cart (ones (3,3,2))
-%!error <matrix input must have 3 columns> sph2cart ([1,2,3,4])
-%!error <numeric arrays of the same size> sph2cart ({1,2,3}, [1,2,3], [1,2,3])
-%!error <numeric arrays of the same size> sph2cart ([1,2,3], {1,2,3}, [1,2,3])
-%!error <numeric arrays of the same size> sph2cart ([1,2,3], [1,2,3], {1,2,3})
-%!error <numeric arrays of the same size> sph2cart (ones (3,3,3), 1, ones (3,2,3))
-%!error <numeric arrays of the same size> sph2cart (ones (3,3,3), ones (3,2,3), 1)
+%!error <matrix input must be a 2-D numeric array> sph2cart ({1,2,3})
+%!error <matrix input must be a 2-D numeric array> sph2cart (ones (3,3,2))
+%!error <matrix input must be a 3-element> sph2cart ([1,2,3,4])
+%!error <matrix input must be a 3-element> sph2cart ([1,2,3,4; 1,2,3,4; 1,2,3,4])
+%!error <must be numeric arrays or scalars> sph2cart ({1,2,3}, [1,2,3], [1,2,3])
+%!error <must be numeric arrays or scalars> sph2cart ([1,2,3], {1,2,3}, [1,2,3])
+%!error <must be numeric arrays or scalars> sph2cart ([1,2,3], [1,2,3], {1,2,3})
+%!error <must be the same size or scalars> sph2cart ([1,2,3], [1,2,3], [1,2,3]')
+%!error <must be the same size or scalars> sph2cart (ones (3,3,3), 1, ones (3,2,3))
+%!error <must be the same size or scalars> sph2cart (ones (3,3,3), ones (3,2,3), 1)
--- a/scripts/geometry/griddata.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/geometry/griddata.m	Tue Jul 07 19:40:20 2020 -0400
@@ -27,123 +27,232 @@
 ## @deftypefn  {} {@var{zi} =} griddata (@var{x}, @var{y}, @var{z}, @var{xi}, @var{yi})
 ## @deftypefnx {} {@var{zi} =} griddata (@var{x}, @var{y}, @var{z}, @var{xi}, @var{yi}, @var{method})
 ## @deftypefnx {} {[@var{xi}, @var{yi}, @var{zi}] =} griddata (@dots{})
+## @deftypefnx {} {@var{vi} =} griddata (@var{x}, @var{y}, @var{z}, @var{v}, @var{xi}, @var{yi}, @var{zi})
+## @deftypefnx {} {@var{vi} =} griddata (@var{x}, @var{y}, @var{z}, @var{v}, @var{xi}, @var{yi}, @var{zi}, @var{method})
+## @deftypefnx {} {@var{vi} =} griddata (@var{x}, @var{y}, @var{z}, @var{v}, @var{xi}, @var{yi}, @var{zi}, @var{method}, @var{options})
 ##
-## Generate a regular mesh from irregular data using interpolation.
+## Interpolate irregular 2-D and 3-D source data at specified points.
+##
+## For 2-D interpolation, the inputs @var{x} and @var{y} define the points
+## where the function @code{@var{z} = f (@var{x}, @var{y})} is evaluated.
+## The inputs @var{x}, @var{y}, @var{z} are either vectors of the same length,
+## or the unequal vectors @var{x}, @var{y} are expanded to a 2-D grid with
+## @code{meshgrid} and @var{z} is a 2-D matrix matching the resulting size of
+## the X-Y grid.
+##
+## The interpolation points are (@var{xi}, @var{yi}).  If, and only if,
+## @var{xi} is a row vector and @var{yi} is a column vector, then
+## @code{meshgrid} will be used to create a mesh of interpolation points.
 ##
-## The function is defined by @code{@var{z} = f (@var{x}, @var{y})}.  Inputs
-## @code{@var{x}, @var{y}, @var{z}} are vectors of the same length or
-## @code{@var{x}, @var{y}} are vectors and @code{@var{z}} is matrix.
+## For 3-D interpolation, the inputs @var{x}, @var{y}, and @var{z} define the
+## points where the function @code{@var{v} = f (@var{x}, @var{y}, @var{z})}
+## is evaluated.  The inputs @var{x}, @var{y}, @var{z} are either vectors of
+## the same length, or if they are of unequal length, then they are expanded to
+## a 3-D grid with @code{meshgrid}.  The size of the input @var{v} must match
+## the size of the original data, either as a vector or a matrix.
 ##
-## The interpolation points are all @code{(@var{xi}, @var{yi})}.  If @var{xi},
-## @var{yi} are vectors then they are made into a 2-D mesh.
+## The optional input interpolation @var{method} can be @qcode{"nearest"},
+## @qcode{"linear"}, or for 2-D data @qcode{"v4"}.  When the method is
+## @qcode{"nearest"}, the output @var{vi} will be the closest point in the
+## original data (@var{x}, @var{y}, @var{z}) to the query point (@var{xi},
+## @var{yi}, @var{zi}).  When the method is @qcode{"linear"}, the output
+## @var{vi} will be a linear interpolation between the two closest points in
+## the original source data in each dimension.  For 2-D cases only, the
+## @qcode{"v4"} method is also available which implements a biharmonic spline
+## interpolation.  If @var{method} is omitted or empty, it defaults to
+## @qcode{"linear"}.
 ##
-## The interpolation method can be @qcode{"nearest"}, @qcode{"cubic"} or
-## @qcode{"linear"}.  If method is omitted it defaults to @qcode{"linear"}.
+## For 3-D interpolation, the optional argument @var{options} is passed
+## directly to Qhull when computing the Delaunay triangulation used for
+## interpolation.  See @code{delaunayn} for information on the defaults and
+## how to pass different values.
+##
+## Programming Notes: If the input is complex the real and imaginary parts
+## are interpolated separately.  Interpolation is normally based on a
+## Delaunay triangulation.  Any query values outside the convex hull of the
+## input points will return @code{NaN}.  However, the @qcode{"v4"} method does
+## not use the triangulation and will return values outside the original data
+## (extrapolation).
 ## @seealso{griddata3, griddatan, delaunay}
 ## @end deftypefn
 
-## Algorithm: xi and yi are not "meshgridded" if both are vectors
-##            of the same size (for compatibility)
+function [rx, ry, rz] = griddata (x, y, z, varargin)
 
-function [rx, ry, rz] = griddata (x, y, z, xi, yi, method = "linear")
-
-  if (nargin < 5 || nargin > 7)
+  if (nargin < 5)
     print_usage ();
   endif
 
-  if (ischar (method))
-    method = tolower (method);
-  endif
-
-  ## Meshgrid if x and y are vectors but z is matrix
-  if (isvector (x) && isvector (y) && all ([numel(y), numel(x)] == size (z)))
-    [x, y] = meshgrid (x, y);
-  endif
-
-  if (isvector (x) && isvector (y) && isvector (z))
-    if (! isequal (length (x), length (y), length (z)))
-      error ("griddata: X, Y, and Z must be vectors of the same length");
-    endif
-  elseif (! size_equal (x, y, z))
-    error ("griddata: lengths of X, Y must match the columns and rows of Z");
-  endif
-
-  ## Meshgrid xi and yi if they are a row and column vector.
-  if (rows (xi) == 1 && columns (yi) == 1)
-    [xi, yi] = meshgrid (xi, yi);
-  elseif (isvector (xi) && isvector (yi))
-    ## Otherwise, convert to column vectors
-    xi = xi(:);
-    yi = yi(:);
-  endif
-
-  if (! size_equal (xi, yi))
-    error ("griddata: XI and YI must be vectors or matrices of same size");
-  endif
-
-  x = x(:);
-  y = y(:);
-  z = z(:);
-
-  ## Triangulate data.
-  tri = delaunay (x, y);
-  zi = NaN (size (xi));
-
-  if (strcmp (method, "cubic"))
-    error ("griddata: cubic interpolation not yet implemented");
+  if (nargin > 6)
+    ## Current 2D implementation has nargin max = 6, since no triangulation
+    ## options are passed to the 2D algorithm. 3D algorithm requires nargin >=7
 
-  elseif (strcmp (method, "nearest"))
-    ## Search index of nearest point.
-    idx = dsearch (x, y, tri, xi, yi);
-    valid = ! isnan (idx);
-    zi(valid) = z(idx(valid));
-
-  elseif (strcmp (method, "linear"))
-    ## Search for every point the enclosing triangle.
-    tri_list = tsearch (x, y, tri, xi(:), yi(:));
-
-    ## Only keep the points within triangles.
-    valid = ! isnan (tri_list);
-    tri_list = tri_list(valid);
-    nr_t = rows (tri_list);
-
-    tri = tri(tri_list,:);
-
-    ## Assign x,y,z for each point of triangle.
-    x1 = x(tri(:,1));
-    x2 = x(tri(:,2));
-    x3 = x(tri(:,3));
-
-    y1 = y(tri(:,1));
-    y2 = y(tri(:,2));
-    y3 = y(tri(:,3));
-
-    z1 = z(tri(:,1));
-    z2 = z(tri(:,2));
-    z3 = z(tri(:,3));
-
-    ## Calculate norm vector.
-    N = cross ([x2-x1, y2-y1, z2-z1], [x3-x1, y3-y1, z3-z1]);
-    ## Normalize.
-    N = diag (norm (N, "rows")) \ N;
-
-    ## Calculate D of plane equation
-    ## Ax+By+Cz+D = 0;
-    D = -(N(:,1) .* x1 + N(:,2) .* y1 + N(:,3) .* z1);
-
-    ## Calculate zi by solving plane equation for xi, yi.
-    zi(valid) = -(N(:,1).*xi(:)(valid) + N(:,2).*yi(:)(valid) + D) ./ N(:,3);
+    if (nargout > 1)
+      error ("griddata: only one output argument valid for 3-D interpolation");
+    endif
+    rx = griddata3 (x, y, z, varargin{:});
 
   else
-    error ("griddata: unknown interpolation METHOD");
-  endif
+    ## for nargin 5 or 6, assign varargin terms to variables for 2D algorithm
+    xi = varargin{1};
+    yi = varargin{2};
+
+    ## Meshgrid if x and y are vectors but z is matrix
+    if (isvector (x) && isvector (y) && all ([numel(y), numel(x)] == size (z)))
+      [x, y] = meshgrid (x, y);
+    endif
+
+    if (isvector (x) && isvector (y) && isvector (z))
+      if (! isequal (length (x), length (y), length (z)))
+        error ("griddata: X, Y, and Z must be vectors of the same length");
+      endif
+    elseif (! size_equal (x, y, z))
+      error ("griddata: lengths of X, Y must match the columns and rows of Z");
+    endif
+
+    ## Meshgrid xi and yi if they are a row and column vector, but not
+    ## if they are simply vectors of the same size (for compatibility).
+    if (isrow (xi) && iscolumn (yi))
+      [xi, yi] = meshgrid (xi, yi);
+    elseif (isvector (xi) && isvector (yi))
+      ## Otherwise, convert to column vectors
+      xi = xi(:);
+      yi = yi(:);
+    endif
+
+    if (! size_equal (xi, yi))
+      error ("griddata: XI and YI must be vectors or matrices of same size");
+    endif
+
+    if (nargin == 6)
+      method = varargin{3};
+      if (isempty (method))
+        method = "linear";
+      elseif (! ischar (method))
+        error ("griddata: METHOD must be a string");
+      else
+        method = tolower (method);
+      endif
+
+      if (any (strcmp (method, {"linear", "nearest", "v4"})))
+        ## Do nothing, these are implemented methods
+      elseif (any (strcmp (method, {"cubic", "natural"})))
+        ## FIXME: implement missing interpolation methods.
+        error ('griddata: "%s" interpolation not yet implemented', method);
+      else
+        error ('griddata: unknown interpolation METHOD: "%s"', method);
+      endif
+    else
+      method = "linear";
+    endif
+
+    x = x(:);
+    y = y(:);
+    z = z(:);
+
+    ## Triangulate data.
+    if (! strcmp (method, "v4"))
+      tri = delaunay (x, y);
+    endif
+    zi = NaN (size (xi));
+
+    if (strcmp (method, "linear"))
+      ## Search for every point the enclosing triangle.
+      tri_list = tsearch (x, y, tri, xi(:), yi(:));
+
+      ## Only keep the points within triangles.
+      valid = ! isnan (tri_list);
+      tri_list = tri_list(valid);
+      nr_t = rows (tri_list);
+
+      tri = tri(tri_list,:);
+
+      ## Assign x,y,z for each point of triangle.
+      x1 = x(tri(:,1));
+      x2 = x(tri(:,2));
+      x3 = x(tri(:,3));
 
-  if (nargout > 1)
-    rx = xi;
-    ry = yi;
-    rz = zi;
-  else
-    rx = zi;
+      y1 = y(tri(:,1));
+      y2 = y(tri(:,2));
+      y3 = y(tri(:,3));
+
+      z1 = z(tri(:,1));
+      z2 = z(tri(:,2));
+      z3 = z(tri(:,3));
+
+      ## Calculate norm vector.
+      N = cross ([x2-x1, y2-y1, z2-z1], [x3-x1, y3-y1, z3-z1]);
+      ## Normalize.
+      N = diag (norm (N, "rows")) \ N;
+
+      ## Calculate D of plane equation: Ax+By+Cz+D = 0
+      D = -(N(:,1) .* x1 + N(:,2) .* y1 + N(:,3) .* z1);
+
+      ## Calculate zi by solving plane equation for xi, yi.
+      zi(valid) = -(N(:,1).*xi(:)(valid) + N(:,2).*yi(:)(valid) + D) ./ N(:,3);
+
+    elseif (strcmp (method, "nearest"))
+      ## Search index of nearest point.
+      idx = dsearch (x, y, tri, xi, yi);
+      valid = ! isnan (idx);
+      zi(valid) = z(idx(valid));
+
+    elseif (strcmp (method, "v4"))
+      ## Use Biharmonic Spline Interpolation Green's Function method.
+      ## Compatible with Matlab v4 interpolation method, based on
+      ## D. Sandwell 1987 and Deng & Tang 2011.
+
+      ## The free space Green Function which solves the two dimensional
+      ## Biharmonic PDE
+      ##
+      ## Delta(Delta(G(X))) = delta(X)
+      ##
+      ## for a point source yields
+      ##
+      ## G(X) = |X|^2 * (ln|X|-1) / (8 * pi)
+      ##
+      ## An N-point Biharmonic Interpolation at the point X is given by
+      ##
+      ## z(X) = sum_j_N (alpha_j * G(X-Xj))
+      ##      = sum_j_N (alpha_j * G(rj))
+      ##
+      ## in which the coefficients alpha_j are the unknowns.  rj is the
+      ## Euclidean distance between X and Xj.
+      ## From N datapoints {zi, Xi} an equation system can be formed:
+      ##
+      ## zi(Xi) = sum_j_N (alpha_j * G(Xi-Xj))
+      ##        = sum_j_N (alpha_j * G(rij))
+      ##
+      ## Its inverse yields the unknowns alpha_j.
+
+      ## Step1: Solve for weight coefficients alpha_j depending on the
+      ## Euclidean distances and the training data set {x,y,z}
+      r = sqrt ((x - x.').^2 + (y - y.').^2);  # size N^2
+      D = (r.^2) .* (log (r) - 1);
+      D(isnan (D)) = 0;  # Fix Green Function for r=0
+      alpha_j = D \ z;
+
+      ## Step2 - Use alphas and Green's functions to get interpolated points.
+      ## Use dim3 projection for vectorized calculation to avoid loops.
+      ## Memory usage is proportional to Ni x N.
+      ## FIXME: if this approach is too memory intensive, revert portion to loop
+      x = permute (x, [3, 2, 1]);
+      y = permute (y, [3, 2, 1]);
+      alpha_j = permute (alpha_j, [3, 2, 1]);
+      r_i = sqrt ((xi - x).^2 + (yi - y).^2);  # size Ni x N
+      Di = (r_i.^2) .* (log (r_i) - 1);
+      Di(isnan (Di)) = 0;  # Fix Green's Function for r==0
+      zi = sum (Di .* alpha_j, 3);
+
+    endif
+
+    if (nargout > 1)
+      rx = xi;
+      ry = yi;
+      rz = zi;
+    else
+      rx = zi;
+    endif
+
   endif
 
 endfunction
@@ -155,10 +264,22 @@
 %! x = 2*rand (100,1) - 1;
 %! y = 2*rand (size (x)) - 1;
 %! z = sin (2*(x.^2 + y.^2));
-%! [xx,yy] = meshgrid (linspace (-1,1,32));
+%! [xx,yy] = meshgrid (linspace (-1, 1, 32));
 %! zz = griddata (x,y,z,xx,yy);
 %! mesh (xx, yy, zz);
-%! title ("nonuniform grid sampled at 100 points");
+%! title ("non-uniform grid sampled at 100 points");
+
+%!demo
+%! clf;
+%! colormap ("default");
+%! x = 2*rand (1000,1) - 1;
+%! y = 2*rand (size (x)) - 1;
+%! z = sin (2*(x.^2 + y.^2));
+%! [xx,yy] = meshgrid (linspace (-1, 1, 32));
+%! zz = griddata (x,y,z,xx,yy);
+%! mesh (xx, yy, zz);
+%! title ({"non-uniform grid sampled at 1,000 points",
+%!         'method = "linear"'});
 
 %!demo
 %! clf;
@@ -166,45 +287,63 @@
 %! x = 2*rand (1000,1) - 1;
 %! y = 2*rand (size (x)) - 1;
 %! z = sin (2*(x.^2 + y.^2));
-%! [xx,yy] = meshgrid (linspace (-1,1,32));
-%! zz = griddata (x,y,z,xx,yy);
-%! mesh (xx, yy, zz);
-%! title ("nonuniform grid sampled at 1000 points");
-
-%!demo
-%! clf;
-%! colormap ("default");
-%! x = 2*rand (1000,1) - 1;
-%! y = 2*rand (size (x)) - 1;
-%! z = sin (2*(x.^2 + y.^2));
-%! [xx,yy] = meshgrid (linspace (-1,1,32));
+%! [xx,yy] = meshgrid (linspace (-1, 1, 32));
 %! zz = griddata (x,y,z,xx,yy,"nearest");
 %! mesh (xx, yy, zz);
-%! title ("nonuniform grid sampled at 1000 points with nearest neighbor");
+%! title ({"non-uniform grid sampled at 1,000 points",
+%!         'method = "nearest neighbor"'});
 
 %!testif HAVE_QHULL
-%! [xx,yy] = meshgrid (linspace (-1,1,32));
+%! [xx, yy] = meshgrid (linspace (-1, 1, 32));
 %! x = xx(:);
 %! x = x + 10*(2*round (rand (size (x))) - 1) * eps;
 %! y = yy(:);
 %! y = y + 10*(2*round (rand (size (y))) - 1) * eps;
 %! z = sin (2*(x.^2 + y.^2));
-%! zz = griddata (x,y,z,xx,yy,"linear");
+%! zz = griddata (x,y,z,xx,yy, "linear");
 %! zz2 = sin (2*(xx.^2 + yy.^2));
 %! zz2(isnan (zz)) = NaN;
 %! assert (zz, zz2, 100*eps);
 
+%!testif HAVE_QHULL
+%! [xx, yy] = meshgrid (linspace (-1, 1, 5));
+%! x = xx(:);
+%! x = x + 10*(2*round (rand (size (x))) - 1) * eps;
+%! y = yy(:);
+%! y = y + 10*(2*round (rand (size (y))) - 1) * eps;
+%! z = 2*(x.^2 + y.^2);
+%! zz = griddata (x,y,z,xx,yy, "v4");
+%! zz2 = 2*(xx.^2 + yy.^2);
+%! zz2(isnan (zz)) = NaN;
+%! assert (zz, zz2, 100*eps);
+
+%!testif HAVE_QHULL
+%! [xx, yy] = meshgrid (linspace (-1, 1, 5));
+%! x = xx(:);
+%! x = x + 10*(2*round (rand (size (x))) - 1) * eps;
+%! y = yy(:);
+%! y = y + 10*(2*round (rand (size (y))) - 1) * eps;
+%! z = 2*(x.^2 + y.^2);
+%! zz = griddata (x,y,z,xx,yy, "nearest");
+%! zz2 = 2*(xx.^2 + yy.^2);
+%! zz2(isnan (zz)) = NaN;
+%! assert (zz, zz2, 100*eps);
+
 ## Test input validation
 %!error griddata ()
 %!error griddata (1)
 %!error griddata (1,2)
 %!error griddata (1,2,3)
 %!error griddata (1,2,3,4)
-%!error griddata (1,2,3,4,5,6,7)
+%!error <only one output argument> [xi,yi] = griddata (1,2,3,4,5,6,7)
+%!error <vectors of the same length> griddata (1:4, 1:3, 1:3, 1:3, 1:3)
+%!error <vectors of the same length> griddata (1:3, 1:4, 1:3, 1:3, 1:3)
 %!error <vectors of the same length> griddata (1:3, 1:3, 1:4, 1:3, 1:3)
-%!error <vectors of the same length> griddata (1:3, 1:4, 1:3, 1:3, 1:3)
-%!error <vectors of the same length> griddata (1:4, 1:3, 1:3, 1:3, 1:3)
 %!error <the columns and rows of Z> griddata (1:4, 1:3, ones (4,4), 1:3, 1:3)
 %!error <the columns and rows of Z> griddata (1:4, 1:3, ones (3,5), 1:3, 1:3)
-%!error <matrices of same size> griddata (1:3, 1:3, 1:3, 1:4, 1:3)
-%!error <matrices of same size> griddata (1:3, 1:3, 1:3, 1:3, 1:4)
+%!error <XI and YI .* matrices of same size> griddata (1:3, 1:3, 1:3, 1:4, 1:3)
+%!error <XI and YI .* matrices of same size> griddata (1:3, 1:3, 1:3, 1:3, 1:4)
+%!error <METHOD must be a string> griddata (1,2,3,4,5, {"linear"})
+%!error <"cubic" .* not yet implemented> griddata (1,2,3,4,5, "cubic")
+%!error <"natural" .* not yet implemented> griddata (1,2,3,4,5, "natural")
+%!error <unknown interpolation METHOD: "foobar"> griddata (1,2,3,4,5, "foobar")
--- a/scripts/geometry/griddata3.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/geometry/griddata3.m	Tue Jul 07 19:40:20 2020 -0400
@@ -28,18 +28,34 @@
 ## @deftypefnx {} {@var{vi} =} griddata3 (@var{x}, @var{y}, @var{z}, @var{v}, @var{xi}, @var{yi}, @var{zi}, @var{method})
 ## @deftypefnx {} {@var{vi} =} griddata3 (@var{x}, @var{y}, @var{z}, @var{v}, @var{xi}, @var{yi}, @var{zi}, @var{method}, @var{options})
 ##
-## Generate a regular mesh from irregular data using interpolation.
+## Interpolate irregular 3-D source data at specified points.
 ##
-## The function is defined by @code{@var{v} = f (@var{x}, @var{y}, @var{z})}.
+## The inputs @var{x}, @var{y}, and @var{z} define the points where the
+## function @code{@var{v} = f (@var{x}, @var{y}, @var{z})} is evaluated.  The
+## inputs @var{x}, @var{y}, @var{z} are either vectors of the same length, or
+## if they are of unequal length, then they are expanded to a 3-D grid with
+## @code{meshgrid}.  The size of the input @var{v} must match the size of the
+## original data, either as a vector or a matrix.
+##
 ## The interpolation points are specified by @var{xi}, @var{yi}, @var{zi}.
 ##
-## The interpolation method can be @qcode{"nearest"} or @qcode{"linear"}.
-## If method is omitted it defaults to @qcode{"linear"}.
+## The optional input interpolation @var{method} can be @qcode{"nearest"} or
+## @qcode{"linear"}.  When the method is @qcode{"nearest"}, the output @var{vi}
+## will be the closest point in the original data (@var{x}, @var{y}, @var{z})
+## to the query point (@var{xi}, @var{yi}, @var{zi}).  When the method is
+## @qcode{"linear"}, the output @var{vi} will be a linear interpolation between
+## the two closest points in the original source data in each dimension.
+## If @var{method} is omitted or empty, it defaults to @qcode{"linear"}.
 ##
 ## The optional argument @var{options} is passed directly to Qhull when
 ## computing the Delaunay triangulation used for interpolation.  See
 ## @code{delaunayn} for information on the defaults and how to pass different
 ## values.
+##
+## Programming Notes: If the input is complex the real and imaginary parts
+## are interpolated separately.  Interpolation is based on a Delaunay
+## triangulation and any query values outside the convex hull of the input
+## points will return @code{NaN}.
 ## @seealso{griddata, griddatan, delaunayn}
 ## @end deftypefn
 
@@ -105,3 +121,7 @@
 %! vi = griddata3 (x, y, z, v, xi, yi, zi, "nearest");
 %! vv = vi - xi.^2 - yi.^2 - zi.^2;
 %! assert (max (abs (vv(:))), 0.385, 0.1);
+
+## FIXME: Ideally, there should be BIST tests for input validation.
+## However, this function is deprecated in Matlab and it probably isn't worth
+## the coding time to work on a function that will be removed soon.
--- a/scripts/geometry/griddatan.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/geometry/griddatan.m	Tue Jul 07 19:40:20 2020 -0400
@@ -28,18 +28,56 @@
 ## @deftypefnx {} {@var{yi} =} griddatan (@var{x}, @var{y}, @var{xi}, @var{method})
 ## @deftypefnx {} {@var{yi} =} griddatan (@var{x}, @var{y}, @var{xi}, @var{method}, @var{options})
 ##
-## Generate a regular mesh from irregular data using interpolation.
+## Interpolate irregular source data @var{x}, @var{y} at points specified by
+## @var{xi}.
 ##
-## The function is defined by @code{@var{y} = f (@var{x})}.
-## The interpolation points are all @var{xi}.
+## The input @var{x} is an MxN matrix representing M points in an N-dimensional
+## space.  The input @var{y} is a single-valued column vector (Mx1)
+## representing a function evaluated at the points @var{x}, i.e.,
+## @code{@var{y} = fcn (@var{x})}.  The input @var{xi} is a list of points
+## for which the function output @var{yi} should be approximated through
+## interpolation.  @var{xi} must have the same number of columns (@var{N})
+## as @var{x} so that the dimensionality matches.
 ##
-## The interpolation method can be @qcode{"nearest"} or @qcode{"linear"}.
-## If method is omitted it defaults to @qcode{"linear"}.
+## The optional input interpolation @var{method} can be @qcode{"nearest"} or
+## @qcode{"linear"}.  When the method is @qcode{"nearest"}, the output @var{yi}
+## will be the closest point in the original data @var{x} to the query point
+## @var{xi}.  When the method is @qcode{"linear"}, the output @var{yi} will
+## be a linear interpolation between the two closest points in the original
+## source data.  If @var{method} is omitted or empty, it defaults to
+## @qcode{"linear"}.
 ##
 ## The optional argument @var{options} is passed directly to Qhull when
 ## computing the Delaunay triangulation used for interpolation.  See
 ## @code{delaunayn} for information on the defaults and how to pass different
 ## values.
+##
+## Example
+##
+## @example
+## @group
+## ## Evaluate sombrero() function at irregular data points
+## x = 16*gallery ("uniformdata", [200,1], 1) - 8;
+## y = 16*gallery ("uniformdata", [200,1], 11) - 8;
+## z = sin (sqrt (x.^2 + y.^2)) ./ sqrt (x.^2 + y.^2);
+## ## Create a regular grid and interpolate data
+## [xi, yi] = ndgrid (linspace (-8, 8, 50));
+## zi = griddatan ([x, y], z, [xi(:), yi(:)]);
+## zi = reshape (zi, size (xi));
+## ## Plot results
+## clf ();
+## plot3 (x, y, z, "or");
+## hold on
+## surf (xi, yi, zi);
+## legend ("Original Data", "Interpolated Data");
+## @end group
+## @end example
+##
+## Programming Notes: If the input is complex the real and imaginary parts
+## are interpolated separately.  Interpolation is based on a Delaunay
+## triangulation and any query values outside the convex hull of the input
+## points will return @code{NaN}.  For 2-D and 3-D data additional
+## interpolation methods are available by using the @code{griddata} function.
 ## @seealso{griddata, griddata3, delaunayn}
 ## @end deftypefn
 
@@ -49,15 +87,41 @@
     print_usage ();
   endif
 
-  if (ischar (method))
-    method = tolower (method);
-  endif
-
   [m, n] = size (x);
   [mi, ni] = size (xi);
 
-  if (n != ni || rows (y) != m || columns (y) != 1)
-    error ("griddatan: dimensional mismatch");
+  if (m < n + 1)
+    error ("griddatan: number of points in X (rows of X) must be greater than dimensionality of data + 1 (columns of X + 1)");
+  endif
+  if (! iscolumn (y) || rows (y) != m)
+    error ("griddatan: Y must be a column vector with the same number of points (rows) as X");
+  endif
+  if (n != ni)
+    error ("griddatan: dimension of query data XI (columns) must match X");
+  endif
+
+  if (nargin > 3)
+    if (isempty (method))
+      method = "linear";
+    elseif (! ischar (method))
+      error ("griddatan: METHOD must be a string");
+    else
+      method = tolower (method);
+    endif
+
+    if (strcmp (method, "linear") || strcmp (method, "nearest"))
+      ## Do nothing, these are implemented methods
+    elseif (strcmp (method, "v4"))
+      error ('griddatan: "%s" METHOD is available for 2-D inputs by using "griddata"', method);
+
+    elseif (any (strcmp (method, {"cubic", "natural"})))
+      ## FIXME: Remove when griddata.m supports these methods.
+      error ('griddatan: "%s" interpolation METHOD not yet implemented', method);
+
+    else
+      error ('griddatan: unknown interpolation METHOD: "%s"', method);
+    endif
+
   endif
 
   ## triangulate data
@@ -65,13 +129,7 @@
 
   yi = NaN (mi, 1);
 
-  if (strcmp (method, "nearest"))
-    ## search index of nearest point
-    idx = dsearchn (x, tri, xi);
-    valid = ! isnan (idx);
-    yi(valid) = y(idx(valid));
-
-  elseif (strcmp (method, "linear"))
+  if (strcmp (method, "linear"))
     ## search for every point the enclosing triangle
     [tri_list, bary_list] = tsearchn (x, tri, xi);
 
@@ -90,7 +148,11 @@
     endif
 
   else
-    error ("griddatan: unknown interpolation METHOD");
+    ## search index of nearest point
+    idx = dsearchn (x, tri, xi);
+    valid = ! isnan (idx);
+    yi(valid) = y(idx(valid));
+
   endif
 
 endfunction
@@ -102,8 +164,8 @@
 %! x = 2*rand (100,2) - 1;
 %! x = [x;1,1;1,-1;-1,-1;-1,1];
 %! y = sin (2 * sum (x.^2,2));
-%! zz = griddatan (x,y,xi,"linear");
-%! zz2 = griddata (x(:,1),x(:,2),y,xi(:,1),xi(:,2),"linear");
+%! zz = griddatan (x,y,xi, "linear");
+%! zz2 = griddata (x(:,1),x(:,2),y,xi(:,1),xi(:,2), "linear");
 %! assert (zz, zz2, 1e-10);
 
 %!testif HAVE_QHULL
@@ -112,8 +174,8 @@
 %! x = 2*rand (100,2) - 1;
 %! x = [x;1,1;1,-1;-1,-1;-1,1];
 %! y = sin (2*sum (x.^2,2));
-%! zz = griddatan (x,y,xi,"nearest");
-%! zz2 = griddata (x(:,1),x(:,2),y,xi(:,1),xi(:,2),"nearest");
+%! zz = griddatan (x,y,xi, "nearest");
+%! zz2 = griddata (x(:,1),x(:,2),y,xi(:,1),xi(:,2), "nearest");
 %! assert (zz, zz2, 1e-10);
 
 %!testif HAVE_QHULL <*56515>
@@ -121,3 +183,17 @@
 %! y = [ 1; 2; 3; 4 ];
 %! xi = [ .5, .5 ];
 %! yi = griddatan (x, y, xi);
+
+## Test input validation
+%!error griddatan ()
+%!error griddatan (1)
+%!error griddatan (1,2)
+%!error <number of points in X> griddatan (1,2,3)
+%!error <Y must be a column vector> griddatan ([1;2],[3,4], 1)
+%!error <Y must .* same number of points .* as X> griddatan ([1;2],[3;4;5], 1)
+%!error <dimension of .* XI .* must match X> griddatan ([1;2],[3;4], [1, 2])
+%!error <METHOD must be a string> griddatan ([1;2],[3;4], 1, 5)
+%!error <"v4" METHOD is available for 2-D> griddatan ([1;2],[3;4], 1, "v4")
+%!error <"cubic" .* not yet implemented> griddatan ([1;2],[3;4], 1, "cubic")
+%!error <"natural" .* not yet implemented> griddatan ([1;2],[3;4], 1, "natural")
+%!error <unknown .* METHOD: "foobar"> griddatan ([1;2],[3;4], 1, "foobar")
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/gui/getpixelposition.m	Tue Jul 07 19:40:20 2020 -0400
@@ -0,0 +1,127 @@
+########################################################################
+##
+## Copyright (C) 2020 The Octave Project Developers
+##
+## See the file COPYRIGHT.md in the top-level directory of this
+## distribution or <https://octave.org/copyright/>.
+##
+## This file is part of Octave.
+##
+## Octave is free software: you can 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
+## <https://www.gnu.org/licenses/>.
+##
+########################################################################
+
+## -*- texinfo -*-
+## @deftypefn  {} {@var{pos} =} getpixelposition (@var{h})
+## @deftypefnx {} {@var{pos} =} getpixelposition (@var{h}, @var{rel_to_fig})
+## Return the position of a user interface component in pixel units.
+##
+## The first argument @var{h} must be a handle to a valid graphics object of
+## type uibuttongroup, uicontrol, uipanel, uitable, axes, or figure.  For other
+## object types, the function returns zeros.
+##
+## By default, the position is returned relative to the object's parent.
+## If the second argument @var{rel_to_fig} is logically true, the position
+## is computed relative to the enclosing figure object.
+##
+## The return value @var{pos} is a 4-element vector with values
+## @code{[ lower_left_X, lower_left_Y, width, height ]}.
+##
+## @seealso{get}
+## @end deftypefn
+
+function pos = getpixelposition (h, rel_to_fig = false)
+
+  if (nargin < 1 || nargin > 2)
+    print_usage ();
+  endif
+
+  if (! isscalar (h) || ! ishghandle (h))
+    error ("getpixelposition: H must be a scalar graphics handle");
+  endif
+
+  if (! any (strcmp (get (h, "type"), {"uibuttongroup", "uicontrol", ...
+                                       "uitable", "uipanel", ...
+                                       "axes", "figure"})))
+    pos = zeros (1, 4);
+    return;
+  endif
+
+  pos = __get_position__ (h, "pixels");
+
+  if (rel_to_fig)
+    while (! isfigure (h))
+      h = get (h, "parent");
+      pos(1:2) += __get_position__ (h, "pixels")(1:2);
+    endwhile
+  endif
+
+endfunction
+
+
+%!demo
+%! clf ();
+%! hax = axes ("position", [0.25 0.25 0.5 0.5])
+%! pos = getpixelposition (hax);
+%! han = annotation ("rectangle");
+%! set (han, "units", "pixels", "position", pos, "color", "r")
+
+%!demo
+%! hf = clf ();
+%! hbg = uibuttongroup (hf, "position", [0.2 0.7 0.2 0.2]);
+%! hb1 = uicontrol (hbg, "style", "radiobutton", ...
+%!                       "string", "Choice 1", ...
+%!                       "units", "normalized", ...
+%!                       "position", [0.01 0.5 0.98 0.5]);
+%! hb2 = uicontrol (hbg, "style", "radiobutton", ...
+%!                       "string", "Choice 2", ...
+%!                       "units", "normalized", ...
+%!                       "position", [0.01 0 0.98 0.5]);
+%! pos = getpixelposition (hbg);
+%! han = annotation ("rectangle");
+%! set (han, "units", "pixels", "position", pos, "color", "r")
+
+
+%!test
+%! pos = [0 0 400 400];
+%! hf = figure ("visible", "off", "menubar", "none", "position", pos);
+%! unwind_protect
+%!   hp = uipanel (hf, "position", [0.5 0.5 0.5 0.5]);
+%!   hax = axes (hp, "position", [0.5 0.5 0.5 0.5]);
+%!   assert (getpixelposition (hax), [100 100 100 100], 2);
+%!   assert (getpixelposition (hax, true), [300 300 100 100], 2);
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+%!test
+%! ## Compatibility: return zeros for root figure
+%! assert (getpixelposition (groot), zeros (1, 4));
+
+%!test
+%! ## Compatibility: return the same for figures regardless of rel_to_fig
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   assert (getpixelposition (hf), getpixelposition (hf, true));
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+## Test input validation
+%!error getpixelposition ()
+%!error getpixelposition (1,2,3)
+%!error <H must be a scalar> getpixelposition ([1, 2])
+%!error <H must be a .* graphics handle> getpixelposition (-1)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/gui/listfonts.m	Tue Jul 07 19:40:20 2020 -0400
@@ -0,0 +1,78 @@
+########################################################################
+##
+## Copyright (C) 2020 The Octave Project Developers
+##
+## See the file COPYRIGHT.md in the top-level directory of this
+## distribution or <https://octave.org/copyright/>.
+##
+## This file is part of Octave.
+##
+## Octave is free software: you can 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
+## <https://www.gnu.org/licenses/>.
+##
+########################################################################
+
+## -*- texinfo -*-
+## @deftypefn  {} {fonts =} listfonts ()
+## @deftypefnx {} {fonts =} listfonts (@var{h})
+## List system fonts.
+##
+## If a handle to a graphics object @var{h} is provided, also include the
+## font from the object's @qcode{"FontName"} property in the list.
+##
+## Programming Note: On systems that don't use FontConfig natively (all but
+## Linux), the font cache is built when Octave is installed.  You will need to
+## run @code{system ("fc-cache -fv")} manually after installing new fonts.
+##
+## @seealso{uisetfont, text, axes, uicontrol}
+## @end deftypefn
+
+function fonts = listfonts (h)
+
+  if (nargin > 1)
+    print_usage ();
+  endif
+
+  if (nargin == 1 && (! ishghandle (h) || ! isprop (h, "fontname")))
+    error (['listfonts: H must be a handle to a graphics object ', ...
+            'with a "fontname" property']);
+  endif
+
+  persistent sysfonts = get_fonts ();
+  fonts = sysfonts;
+
+  if (nargin == 1 && ! isempty (h))
+    font = get (h, "fontname");
+    if (! strcmp (font, "*"))
+      fonts = unique ([fonts font]);
+    endif
+  endif
+
+endfunction
+
+function fonts = get_fonts ()
+
+  fontfiles = __get_system_fonts__ ();
+
+  fonts = unique ({fontfiles.family, "FreeSans"});
+
+endfunction
+
+
+## Test input validation
+%!error listfonts (0, 0)
+%!error <H must be a handle to a graphics object with a "fontname" property>
+%! s = listfonts (0);
+%!error <H must be a handle to a graphics object>
+%! s = listfonts (struct ());
--- a/scripts/gui/module.mk	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/gui/module.mk	Tue Jul 07 19:40:20 2020 -0400
@@ -17,11 +17,13 @@
   %reldir%/dialog.m \
   %reldir%/errordlg.m \
   %reldir%/getappdata.m \
+  %reldir%/getpixelposition.m \
   %reldir%/guidata.m \
   %reldir%/guihandles.m \
   %reldir%/helpdlg.m \
   %reldir%/inputdlg.m \
   %reldir%/isappdata.m \
+  %reldir%/listfonts.m \
   %reldir%/listdlg.m \
   %reldir%/movegui.m \
   %reldir%/msgbox.m \
--- a/scripts/gui/uicontrol.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/gui/uicontrol.m	Tue Jul 07 19:40:20 2020 -0400
@@ -119,6 +119,16 @@
 
   [h, args] = __uiobject_split_args__ ("uicontrol", varargin,
                                        {"figure", "uipanel", "uibuttongroup"});
+
+  ## Validate style
+  idx = find (strcmp (args, "style"), 1, "last");
+  if (! isempty (idx))
+    if (idx < numel (args) && strcmp (varargin{idx+1}, "frame"))
+      warning ("Octave:unimplemented-matlab-functionality",
+               'uicontrol: "frame" style is not implemented.  Use uipanel() or uibuttongroup() instead');
+    endif
+  endif
+
   htmp = __go_uicontrol__ (h, args{:});
 
   if (nargout > 0)
--- a/scripts/gui/uisetfont.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/gui/uisetfont.m	Tue Jul 07 19:40:20 2020 -0400
@@ -38,14 +38,18 @@
 ## @code{FontWeight}, @code{FontAngle}, @code{FontUnits}, and @code{FontSize},
 ## indicating the initially selected font.
 ##
-## The title of the dialog window can be changed using the last argument
+## The title of the dialog window can be specified by using the last argument
 ## @var{title}.
 ##
 ## If an output argument @var{fontstruct} is requested, the selected font
 ## structure is returned.  Otherwise, the font information is displayed
 ## onscreen.
 ##
-## @seealso{text, axes, uicontrol}
+## Programming Note: On systems that don't use FontConfig natively (all but
+## Linux), the font cache is built when Octave is installed.  You will need to
+## run @code{system ("fc-cache -fv")} manually after installing new fonts.
+##
+## @seealso{listfonts, text, axes, uicontrol}
 ## @end deftypefn
 
 function varargout = uisetfont (varargin)
@@ -71,7 +75,7 @@
     typ = get (h, "type");
     if (! any (strcmp (typ, {"axes", "text", "uicontrol"})))
       error ("Octave:uisetfont:bad-object",
-             'uisetfont: unhandled object type "%s"', typ);
+             "uisetfont: H must be a handle to an axes, text, or uicontrol object");
     endif
     nargin--;
     varargin(1) = [];
@@ -333,7 +337,7 @@
 
 endfunction
 
-function cb_button (h, evt, hlists, role)
+function cb_button (h, ~, hlists, role)
 
   fontstruct = [];
   if (strcmp (role, "ok"))
@@ -345,7 +349,7 @@
 
 endfunction
 
-function cb_list_value_changed (h, evt, hlists, htext, sysfonts)
+function cb_list_value_changed (h, ~, hlists, htext, sysfonts)
 
   if (h == hlists(1))
     set (hlists(2), "string", getstylestring (sysfonts(get (h, "value"))),
@@ -363,7 +367,7 @@
 %!testif HAVE_FONTCONFIG
 %! fail ("uisetfont (110, struct ())", "Invalid call");
 %!testif HAVE_FONTCONFIG
-%! fail ("uisetfont (groot ())", "unhandled object type");
+%! fail ("uisetfont (groot ())", "H must be a handle to an axes");
 %!testif HAVE_FONTCONFIG
 %! fail ("uisetfont (struct ())", "FONTSTRUCT .* must have fields FontName,.*");
 %!testif HAVE_FONTCONFIG
--- a/scripts/help/__unimplemented__.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/help/__unimplemented__.m	Tue Jul 07 19:40:20 2020 -0400
@@ -736,7 +736,6 @@
   "edges",
   "empty",
   "enableservice",
-  "endsWith",
   "enumeration",
   "eraseBetween",
   "eventlisteners",
@@ -975,7 +974,6 @@
   "libpointer",
   "libstruct",
   "linkdata",
-  "listfonts",
   "loadlibrary",
   "lsqminnorm",
   "lsqr",
@@ -990,7 +988,6 @@
   "memmapfile",
   "memoize",
   "MemoizedFunction",
-  "memory",
   "mergecats",
   "meta.abstractDetails",
   "meta.class.fromName",
@@ -1193,13 +1190,11 @@
   "ss2tf",
   "stack",
   "standardizeMissing",
-  "startsWith",
   "stats",
   "step",
   "stopasync",
   "str2mat",
   "streamparticles",
-  "streamribbon",
   "streamslice",
   "string",
   "strings",
--- a/scripts/help/warning_ids.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/help/warning_ids.m	Tue Jul 07 19:40:20 2020 -0400
@@ -384,6 +384,14 @@
 ## the warning message is printed just once per Octave session.
 ## By default, the @code{Octave:glyph-render} warning is enabled.
 ##
+## @item Octave:unimplemented-matlab-functionality
+## If the @code{Octave:unimplemented-matlab-functionality} warning is enabled,
+## a warning is printed when a @sc{matlab} code construct is used which the
+## Octave interpreter parses as valid, but for which Octave does not yet
+## implement the functionality.
+## By default, the @code{Octave:unimplemented-matlab-functionality} warning is
+## enabled.
+##
 ## @item Octave:variable-switch-label
 ## If the @code{Octave:variable-switch-label} warning is enabled, Octave
 ## will print a warning if a switch label is not a constant or constant
--- a/scripts/io/importdata.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/io/importdata.m	Tue Jul 07 19:40:20 2020 -0400
@@ -175,8 +175,8 @@
 
     ## If no delimiter determined yet, make a guess.
     if (isempty (delimiter))
-      ## This pattern can be fooled, but mostly does the job just fine.
-      delim = regexpi (row, '[-+\d.e*ij ]+([^-+\de.ij])[-+\de*.ij ]',
+      ## Look for number, DELIMITER, DELIMITER*, number
+      delim = regexpi (row, '[-+]?\d*[.]?\d+(?:[ed][-+]?\d+)?[ij]?([^-+\d.deij])\1*[-+]?\d*[.]?\d+(?:[ed][-+]?\d+)?[ij]?',
                        'tokens', 'once');
       if (! isempty (delim))
         delimiter = delim{1};
@@ -200,6 +200,14 @@
       row = -1;
       break;
     else
+      ## The number of header rows and header columns is now known.
+      header_cols = find (! isnan (row_data), 1) - 1;
+      has_rowheaders = (header_cols == 1);
+
+      ## Set colheaders output from textdata if appropriate
+      ## NOTE: Octave chooses to be Matlab incompatible and return
+      ## both 'rowheaders' and 'colheaders' when they are present.
+      ## Matlab allows only one to be present at a time.
       if (! isempty (output.textdata))
         if (delimiter == " ")
           output.colheaders = regexp (strtrim (output.textdata{end}),
@@ -207,9 +215,22 @@
         else
           output.colheaders = ostrsplit (output.textdata{end}, delimiter);
         endif
+       
+        nc_hdr = numel (output.colheaders);
+        nc_dat = numel (row_data);
+        if (! has_rowheaders)
+          if (nc_hdr != nc_dat)
+            output = rmfield (output, {"rowheaders", "colheaders"});
+          else
+            output = rmfield (output, "rowheaders");
+          endif
+        else
+          if (nc_hdr != nc_dat-1)
+            output = rmfield (output, "colheaders");
+          endif
+        endif
       endif
-      header_cols = find (! isnan (row_data), 1) - 1;
-      ## The number of header rows and header columns is now known.
+
       break;
     endif
 
@@ -243,19 +264,31 @@
   fclose (fid);
 
   if (num_header_rows >= 0)
-    header_rows = num_header_rows;
+    ## User has defined a number of header rows which disagrees with the
+    ## auto-detected number.  Print a warning.
+    if (num_header_rows < header_rows)
+      warning ("Octave:importdata:headerrows_mismatch", 
+               "importdata: detected %d header rows, but HEADER_ROWS input configured %d rows", header_rows, num_header_rows);
+    endif
+  else
+    ## use the automatically detected number of header rows
+    num_header_rows = header_rows;
   endif
 
   ## Now, let the efficient built-in routine do the bulk of the work.
   if (delimiter == " ")
-    output.data = dlmread (fname, "", header_rows, header_cols,
+    output.data = dlmread (fname, "", num_header_rows, header_cols,
                            "emptyvalue", NA);
   else
-    output.data = dlmread (fname, delimiter, header_rows, header_cols,
+    output.data = dlmread (fname, delimiter, num_header_rows, header_cols,
                            "emptyvalue", NA);
   endif
 
   ## Go back and correct any individual values that did not convert.
+  ## FIXME: This is only efficient when the number of bad conversions is small.
+  ##        Any file with 'rowheaders' will cause the for loop to execute over
+  ##        *every* line in the file.
+
   na_idx = isna (output.data);
   if (header_cols > 0)
     na_idx = [(true (rows (na_idx), header_cols)), na_idx];
@@ -265,8 +298,11 @@
     file_content = ostrsplit (fileread (fname), "\r\n", true);
 
     na_rows = find (any (na_idx, 2));
+    ## Prune text lines in header that were already collected
+    idx = (na_rows(1:min (header_rows, end)) + num_header_rows) <= header_rows;
+    na_rows(idx) = [];
     for ridx = na_rows(:)'
-      row = file_content{ridx+header_rows};
+      row = file_content{ridx+num_header_rows};
       if (delimiter == " ")
         fields = regexp (strtrim (row), ' +', 'split');
       else
@@ -277,28 +313,45 @@
       if (! size_equal (missing_idx, fields))
         ## Fields completely missing at end of line.  Replace with NA.
         col = columns (fields);
-        output.data(ridx, (col+1):end) = NA;
+        ## FIXME: This code should be redundant because dlmread was called
+        ##        with "emptyval", NA.  Delete if there are no problems
+        ##        detected after some time.  Commented out: 5/23/2020.
+        ##output.data(ridx, (col+1):end) = NA;
         missing_idx = missing_idx(1:col);
       endif
       text = fields(missing_idx);
 
       text = text(! strcmpi (text, "NA"));  #  Remove valid "NA" entries
+      text = text(! strcmpi (text, ""));    #  Remove empty entries
       if (! isempty (text))
-        output.textdata = [output.textdata; text(:)];
+        output.textdata(end+1, 1:columns (text)) = text;
       endif
 
-      if (header_cols)
-        output.rowheaders(end+1, :) = fields(1:header_cols);
+      if (has_rowheaders)
+        output.rowheaders(end+1, 1) = fields(1);
       endif
     endfor
 
   endif
 
-  ## Final cleanup to satisfy output configuration
+  ## Final cleanup to satisfy Matlab compatibility
   if (all (cellfun ("isempty", output.textdata)))
     output = output.data;
-  elseif (! isempty (output.rowheaders) && ! isempty (output.colheaders))
-    output = struct ("data", {output.data}, "textdata", {output.textdata});
+  else
+    ## Text fields should be cell array of strings, rather than just cell.
+    try
+      output.textdata = cellstr (output.textdata);
+    end_try_catch
+    try
+      output.rowheaders = cellstr (output.rowheaders);
+    end_try_catch
+    try
+      output.colheaders = cellstr (output.colheaders);
+    end_try_catch
+  endif
+
+  if (num_header_rows != header_rows)
+    header_rows = num_header_rows;
   endif
 
 endfunction
@@ -377,7 +430,6 @@
 %! A.data = [3.1 -7.2 0; 0.012 6.5 128];
 %! A.textdata = {"This is a header row."; ...
 %!               "this row does not contain any data, but the next one does."};
-%! A.colheaders = A.textdata (2);
 %! fn  = tempname ();
 %! fid = fopen (fn, "w");
 %! fprintf (fid, "%s\n", A.textdata{:});
@@ -393,6 +445,7 @@
 %! ## Column headers, only last row is returned in colheaders
 %! A.data = [3.1 -7.2 0; 0.012 6.5 128];
 %! A.textdata = {"Label1\tLabel2\tLabel3";
+%!               "";
 %!               "col 1\tcol 2\tcol 3"};
 %! A.colheaders = {"col 1", "col 2", "col 3"};
 %! fn  = tempname ();
@@ -404,7 +457,7 @@
 %! unlink (fn);
 %! assert (a, A);
 %! assert (d, "\t");
-%! assert (h, 2);
+%! assert (h, 3);
 
 %!test
 %! ## Row headers
@@ -425,9 +478,11 @@
 %! ## Row/Column headers and Header Text
 %! A.data = [3.1 -7.2 0; 0.012 6.5 128];
 %! A.textdata = {"This is introductory header text"
-%!               "      col1 col2 col3"
+%!               "col1\tcol2\tcol3"
 %!               "row1"
 %!               "row2"};
+%! A.rowheaders = A.textdata(3:4);
+%! A.colheaders = {"col1", "col2", "col3"};
 %! fn  = tempname ();
 %! fid = fopen (fn, "w");
 %! fprintf (fid, "%s\n", A.textdata{1:2});
@@ -511,8 +566,7 @@
 %!test
 %! ## Missing values and Text Values
 %! A.data = [3.1 NA 0; 0.012 NA 128];
-%! A.textdata = {char(zeros(1,0))
-%!               "NO DATA"};
+%! A.textdata = {"NO DATA"};
 %! fn  = tempname ();
 %! fid = fopen (fn, "w");
 %! fputs (fid, "3.1\t\t0\n0.012\tNO DATA\t128");
@@ -585,6 +639,35 @@
 %! assert (d, "");
 %! assert (h, 3);
 
+%!test <*58294>
+%! ## Varying values of header lines field
+%! fn  = tempname ();
+%! fid = fopen (fn, "w");
+%! fputs (fid, "header1\nheader2\n3.1\n4.2");
+%! fclose (fid);
+%! warning ("off", "Octave:importdata:headerrows_mismatch", "local");
+%! ## Base import
+%! [a, d, h] = importdata (fn, "");
+%! assert (a.data, [3.1; 4.2]);
+%! assert (a.textdata, {"header1"; "header2"});
+%! assert (h, 2);
+%! ## Import with 0 header lines
+%! [a, d, h] = importdata (fn, "", 0);
+%! assert (a.data, [NA; NA; 3.1; 4.2]);
+%! assert (a.textdata, {"header1"; "header2"});
+%! assert (h, 0);
+%! ## Import with 1 header lines
+%! [a, d, h] = importdata (fn, "", 1);
+%! assert (a.data, [NA; 3.1; 4.2]);
+%! assert (a.textdata, {"header1"; "header2"});
+%! assert (h, 1);
+%! ## Import with 3 header lines
+%! [a, d, h] = importdata (fn, "", 3);
+%! assert (a.data, [4.2]);
+%! assert (a.textdata, {"header1"; "header2"; "3.1"});
+%! assert (h, 3);
+%! unlink (fn);
+
 %!error importdata ()
 %!error importdata (1,2,3,4)
 %!error <FNAME must be a string> importdata (1)
@@ -594,3 +677,10 @@
 %!error <HEADER_ROWS must be an integer> importdata ("foo", " ", "1")
 %!error <HEADER_ROWS must be an integer> importdata ("foo", " ", 1.5)
 %!error <not implemented for file format .avi> importdata ("foo.avi")
+%!warning <detected 2 header rows, but HEADER_ROWS input configured 1 rows>
+%! fn  = tempname ();
+%! fid = fopen (fn, "w");
+%! fputs (fid, "header1\nheader2\n3.1");
+%! fclose (fid);
+%! a = importdata (fn, "", 1);
+%! unlink (fn);
--- a/scripts/legacy/textread.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/legacy/textread.m	Tue Jul 07 19:40:20 2020 -0400
@@ -346,7 +346,7 @@
 ## Read multiple lines using empty format string
 %!test
 %! f = tempname ();
-%! unlink (f);
+%! sts = unlink (f);
 %! fid = fopen (f, "w");
 %! d = rand (1, 4);
 %! fprintf (fid, "  %f %f   %f  %f ", d);
@@ -358,7 +358,7 @@
 ## Empty format, corner case = one line w/o EOL
 %!test
 %! f = tempname ();
-%! unlink (f);
+%! sts = unlink (f);
 %! fid = fopen (f, "w");
 %! d = rand (1, 4);
 %! fprintf (fid, "  %f %f   %f  %f ", d);
--- a/scripts/linear-algebra/condest.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/linear-algebra/condest.m	Tue Jul 07 19:40:20 2020 -0400
@@ -26,8 +26,12 @@
 ## -*- texinfo -*-
 ## @deftypefn  {} {@var{cest} =} condest (@var{A})
 ## @deftypefnx {} {@var{cest} =} condest (@var{A}, @var{t})
-## @deftypefnx {} {@var{cest} =} condest (@var{A}, @var{solvefun}, @var{t}, @var{p1}, @var{p2}, @dots{})
-## @deftypefnx {} {@var{cest} =} condest (@var{Afcn}, @var{solvefun}, @var{t}, @var{p1}, @var{p2}, @dots{})
+## @deftypefnx {} {@var{cest} =} condest (@var{A}, @var{Ainvfcn})
+## @deftypefnx {} {@var{cest} =} condest (@var{A}, @var{Ainvfcn}, @var{t})
+## @deftypefnx {} {@var{cest} =} condest (@var{A}, @var{Ainvfcn}, @var{t}, @var{p1}, @var{p2}, @dots{})
+## @deftypefnx {} {@var{cest} =} condest (@var{Afcn}, @var{Ainvfcn})
+## @deftypefnx {} {@var{cest} =} condest (@var{Afcn}, @var{Ainvfcn}, @var{t})
+## @deftypefnx {} {@var{cest} =} condest (@var{Afcn}, @var{Ainvfcn}, @var{t}, @var{p1}, @var{p2}, @dots{})
 ## @deftypefnx {} {[@var{cest}, @var{v}] =} condest (@dots{})
 ##
 ## Estimate the 1-norm condition number of a square matrix @var{A} using
@@ -35,54 +39,56 @@
 ##
 ## The optional input @var{t} specifies the number of test vectors (default 5).
 ##
-## If the matrix is not explicit, e.g., when estimating the condition number of
-## @var{A} given an LU@tie{}factorization, @code{condest} uses the following
-## functions:
+## The input may be a matrix @var{A} (the algorithm is particularly
+## appropriate for large, sparse matrices).  Alternatively, the behavior of
+## the matrix can be defined implicitly by functions.  When using an implicit
+## definition, @code{condest} requires the following functions:
 ##
 ## @itemize @minus
-## @item @var{Afcn} which must return
+## @item @code{@var{Afcn} (@var{flag}, @var{x})} which must return
 ##
 ## @itemize @bullet
 ## @item
-## the dimension @var{n} of @var{a}, if @var{flag} is @qcode{"dim"}
+## the dimension @var{n} of @var{A}, if @var{flag} is @qcode{"dim"}
 ##
 ## @item
-## true if @var{a} is a real operator, if @var{flag} is @qcode{"real"}
+## true if @var{A} is a real operator, if @var{flag} is @qcode{"real"}
 ##
 ## @item
-## the result @code{@var{a} * @var{x}}, if @var{flag} is "notransp"
+## the result @code{@var{A} * @var{x}}, if @var{flag} is "notransp"
 ##
 ## @item
-## the result @code{@var{a}' * @var{x}}, if @var{flag} is "transp"
+## the result @code{@var{A}' * @var{x}}, if @var{flag} is "transp"
 ## @end itemize
 ##
-## @item @var{solvefun} which must return
+## @item @code{@var{Ainvfcn} (@var{flag}, @var{x})} which must return
 ##
 ## @itemize @bullet
 ## @item
-## the dimension @var{n} of @var{a}, if @var{flag} is @qcode{"dim"}
+## the dimension @var{n} of @code{inv (@var{A})}, if @var{flag} is
+## @qcode{"dim"}
 ##
 ## @item
-## true if @var{a} is a real operator, if @var{flag} is @qcode{"real"}
+## true if @code{inv (@var{A})} is a real operator, if @var{flag} is
+## @qcode{"real"}
 ##
 ## @item
-## the result @code{@var{a} \ @var{x}}, if @var{flag} is "notransp"
+## the result @code{inv (@var{A}) * @var{x}}, if @var{flag} is "notransp"
 ##
 ## @item
-## the result @code{@var{a}' \ @var{x}}, if @var{flag} is "transp"
+## the result @code{inv (@var{A})' * @var{x}}, if @var{flag} is "transp"
 ## @end itemize
 ## @end itemize
 ##
-## The parameters @var{p1}, @var{p2}, @dots{} are arguments of
+## Any parameters @var{p1}, @var{p2}, @dots{} are additional arguments of
 ## @code{@var{Afcn} (@var{flag}, @var{x}, @var{p1}, @var{p2}, @dots{})}
-## and @code{@var{solvefcn} (@var{flag}, @var{x}, @var{p1}, @var{p2},
-## @dots{})}.
+## and @code{@var{Ainvfcn} (@var{flag}, @var{x}, @var{p1}, @var{p2}, @dots{})}.
 ##
 ## The principal output is the 1-norm condition number estimate @var{cest}.
 ##
-## The optional second output is an approximate null vector when @var{cest} is
-## large; it satisfies the equation
-## @code{norm (A*v, 1) == norm (A, 1) * norm (@var{v}, 1) / @var{est}}.
+## The optional second output @var{v} is an approximate null vector; it
+## satisfies the equation @code{norm (@var{A}*@var{v}, 1) ==
+## norm (@var{A}, 1) * norm (@var{v}, 1) / @var{cest}}.
 ##
 ## Algorithm Note: @code{condest} uses a randomized algorithm to approximate
 ## the 1-norms.  Therefore, if consistent results are required, the
@@ -104,7 +110,7 @@
 ## Pseudospectra}.  @url{https://citeseer.ist.psu.edu/223007.html}
 ## @end itemize
 ##
-## @seealso{cond, norm, normest1, normest}
+## @seealso{cond, rcond, norm, normest1, normest}
 ## @end deftypefn
 
 ## Code originally licensed under:
@@ -142,10 +148,6 @@
 ## OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 ## SUCH DAMAGE.
 
-## Author: Jason Riedy <ejr@cs.berkeley.edu>
-## Keywords: linear-algebra norm estimation
-## Version: 0.2
-
 function [cest, v] = condest (varargin)
 
   if (nargin < 1 || nargin > 6)
@@ -154,8 +156,8 @@
 
   have_A = false;
   have_t = false;
-  have_apply_normest1 = false;
-  have_solve_normest1 = false;
+  have_Afcn = false;
+  have_Ainvfcn = false;
 
   if (isnumeric (varargin{1}))
     A = varargin{1};
@@ -166,8 +168,8 @@
     n = rows (A);
     if (nargin > 1)
       if (is_function_handle (varargin{2}))
-        solve = varargin{2};
-        have_solve_normest1 = true;
+        Ainvfcn = varargin{2};
+        have_Ainvfcn = true;
         if (nargin > 2)
           t = varargin{3};
           have_t = true;
@@ -175,23 +177,20 @@
       else
         t = varargin{2};
         have_t = true;
-        real_op = isreal (A);
       endif
-    else
-      real_op = isreal (A);
     endif
   elseif (is_function_handle (varargin{1}))
     if (nargin == 1)
-      error("condest: must provide SOLVEFCN when using AFCN");
+      error("condest: must provide AINVFCN when using AFCN");
     endif
-    apply = varargin{1};
-    have_apply_normest1 = true;
+    Afcn = varargin{1};
+    have_Afcn = true;
     if (! is_function_handle (varargin{2}))
-      error("condest: SOLVEFCN must be a function handle");
+      error("condest: AINVFCN must be a function handle");
     endif
-    solve = varargin{2};
-    have_solve_normest1 = true;
-    n = apply ("dim", [], varargin{4:end});
+    Ainvfcn = varargin{2};
+    have_Ainvfcn = true;
+    n = Afcn ("dim", [], varargin{4:end});
     if (nargin > 2)
       t = varargin{3};
       have_t = true;
@@ -207,99 +206,131 @@
   ## Disable warnings which may be emitted during calculation process.
   warning ("off", "Octave:nearly-singular-matrix", "local");
 
-  if (! have_solve_normest1)
-    ## prepare solve in normest1 form
+  if (! have_Ainvfcn)
+    ## Prepare Ainvfcn in normest1 form
     if (issparse (A))
-      [L, U, P, Pc] = lu (A);
-      solve = @(flag, x) solve_sparse (flag, x, n, real_op, L, U, P, Pc);
+      [L, U, P, Q] = lu (A);
+      Ainvfcn = @inv_sparse_fcn;
     else
       [L, U, P] = lu (A);
-      solve = @(flag, x) solve_not_sparse (flag, x, n, real_op, L, U, P);
+      Q = [];
+      Ainvfcn = @inv_full_fcn;
     endif
 
-    ## Check for singular matrices before continuing
+    ## Check for singular matrices before continuing (bug #46737)
     if (any (diag (U) == 0))
       cest = Inf;
       v = [];
       return;
     endif
+
+    ## Initialize solver
+    Ainvfcn ("init", A, L, U, P, Q);
+    clear L U P Q;
   endif
 
   if (have_A)
     Anorm = norm (A, 1);
   else
-    Anorm = normest1 (apply, t, [], varargin{4:end});
+    Anorm = normest1 (Afcn, t, [], varargin{4:end});
   endif
-  [Ainv_norm, v, w] = normest1 (solve, t, [], varargin{4:end});
+  [Ainv_norm, v, w] = normest1 (Ainvfcn, t, [], varargin{4:end});
 
   cest = Anorm * Ainv_norm;
   if (isargout (2))
     v = w / norm (w, 1);
   endif
 
+  if (! have_Ainvfcn)
+    Ainvfcn ("clear");  # clear persistent memory in subfunction
+  endif
+
 endfunction
 
-function value = solve_sparse (flag, x, n, real_op, L , U , P , Pc)
-  ## FIXME: Sparse algorithm is less accurate than full matrix version
-  ##        See BIST test for non-orthogonal matrix where relative tolerance
+function retval = inv_sparse_fcn (flag, x, varargin)
+  ## FIXME: Sparse algorithm is less accurate than full matrix version.
+  ##        See BIST test for asymmetric matrix where relative tolerance
   ##        of 1e-12 is used for sparse, but 4e-16 for full matrix.
+  ##        BUT, does it really matter for an "estimate"?
+  persistent Ainv Ainvt n isreal_op;
+
   switch (flag)
     case "dim"
-      value = n;
+      retval = n;
     case "real"
-      value = real_op;
+      retval = isreal_op;
     case "notransp"
-      value = Pc' * (U \ (L \ (P * x)));
+      retval = Ainv * x;
     case "transp"
-      value = P' * (L' \ (U' \ (Pc * x)));
+      retval = Ainvt * x;
+    case "init"
+      n = rows (x); 
+      isreal_op = isreal (x);
+      [L, U, P, Q] = deal (varargin{1:4});
+      Ainv = Q * (U \ (L \ P));
+      Ainvt = P' * (L' \ (U' \ Q'));
+    case "clear"  # called to free memory at end of condest function
+      clear Ainv Ainvt n isreal_op;
   endswitch
+
 endfunction
 
-function value = solve_not_sparse (flag, x, n, real_op, L, U, P)
+function retval = inv_full_fcn (flag, x, varargin)
+  persistent Ainv Ainvt n isreal_op;
+
   switch (flag)
     case "dim"
-      value = n;
+      retval = n;
     case "real"
-      value = real_op;
+      retval = isreal_op;
     case "notransp"
-      value = U \ (L \ (P * x));
+      retval = Ainv * x;
     case "transp"
-      value = P' * (L' \ (U' \ x));
+      retval = Ainvt \ x;
+    case "init"
+      n = rows (x); 
+      isreal_op = isreal (x);
+      [L, U, P] = deal (varargin{1:3});
+      Ainv = U \ (L \ P);
+      Ainvt = P' * (L' \ U');
+    case "clear"  # called to free memory at end of condest function
+      clear Ainv Ainvt n isreal_op;
   endswitch
+
 endfunction
 
 
 ## Note: These test bounds are very loose.  There is enough randomization to
 ## trigger odd cases with hilb().
 
-%!function value = apply_fun (flag, x, A, m)
+%!function retval = __Afcn__ (flag, x, A, m)
 %!  if (nargin == 3)
 %!    m = 1;
 %!  endif
 %!  switch (flag)
 %!    case "dim"
-%!      value = length (A);
+%!      retval = length (A);
 %!    case "real"
-%!      value = isreal (A);
+%!      retval = isreal (A);
 %!    case "notransp"
-%!      value = x; for i = 1:m, value = A * value;, endfor
+%!      retval = x; for i = 1:m, retval = A * retval;, endfor
 %!    case "transp"
-%!      value = x; for i = 1:m, value = A' * value;, endfor
+%!      retval = x; for i = 1:m, retval = A' * retval;, endfor
 %!  endswitch
 %!endfunction
-%!function value = solve_fun (flag, x, A, m)
+%!function retval = __Ainvfcn__ (flag, x, A, m)
 %!  if (nargin == 3)
 %!    m = 1;
 %!  endif
 %!  switch (flag)
 %!    case "dim"
-%!      value = length (A);
+%!      retval = length (A);
 %!    case "real"
-%!      value = isreal (A);
+%!      retval = isreal (A);
 %!    case "notransp"
-%!      value = x; for i = 1:m, value = A \ value;, endfor
+%!      retval = x; for i = 1:m, retval = A \ retval;, endfor
 %!    case "transp"
-%!      value = x; for i = 1:m, value = A' \ value;, endfor
+%!      retval = x; for i = 1:m, retval = A' \ retval;, endfor
 %!  endswitch
 %!endfunction
 
@@ -320,25 +351,25 @@
 %!test
 %! N = 6;
 %! A = hilb (N);
-%! solve = @(flag, x) solve_fun (flag, x, A);
-%! cA = condest (A, solve);
+%! Ainvfcn = @(flag, x) __Ainvfcn__ (flag, x, A);
+%! cA = condest (A, Ainvfcn);
 %! cA_test = norm (inv (A), 1) * norm (A, 1);
 %! assert (cA, cA_test, -2^-6);
 
 %!test
 %! N = 6;
 %! A = hilb (N);
-%! apply = @(flag, x) apply_fun (flag, x, A);
-%! solve = @(flag, x) solve_fun (flag, x, A);
-%! cA = condest (apply, solve);
+%! Afcn = @(flag, x) __Afcn__ (flag, x, A);
+%! Ainvfcn = @(flag, x) __Ainvfcn__ (flag, x, A);
+%! cA = condest (Afcn, Ainvfcn);
 %! cA_test = norm (inv (A), 1) * norm (A, 1);
 %! assert (cA, cA_test, -2^-6);
 
-%!test # parameters for apply and solve functions
+%!test # parameters for apply and Ainvfcn functions
 %! N = 6;
 %! A = hilb (N);
 %! m = 2;
-%! cA = condest (@apply_fun, @solve_fun, [], A, m);
+%! cA = condest (@__Afcn__, @__Ainvfcn__, [], A, m);
 %! cA_test = norm (inv (A^2), 1) * norm (A^2, 1);
 %! assert (cA, cA_test, -2^-6);
 
@@ -351,7 +382,7 @@
 %! assert (cest, Inf);
 %! assert (v, []);
 
-## Test non-orthogonal matrices
+## Test asymmetric matrices
 %!test <*57968>
 %! A = reshape (sqrt (0:15), 4, 4);
 %! cexp = norm (A, 1) * norm (inv (A), 1);
@@ -365,9 +396,9 @@
 %! assert (cest, cexp, -1e-12);
 
 ## Test input validation
-%!error condest ()
-%!error condest (1,2,3,4,5,6,7)
-%!error <A must be square> condest ([1 2])
-%!error <must provide SOLVEFCN when using AFCN> condest (@sin)
-%!error <SOLVEFCN must be a function handle> condest (@sin, 1)
+%!error <Invalid call> condest ()
+%!error <Invalid call> condest (1,2,3,4,5,6,7)
+%!error <A must be square> condest ([1, 2])
+%!error <must provide AINVFCN when using AFCN> condest (@sin)
+%!error <AINVFCN must be a function handle> condest (@sin, 1)
 %!error <argument must be a square matrix or function handle> condest ({1})
--- a/scripts/miscellaneous/computer.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/miscellaneous/computer.m	Tue Jul 07 19:40:20 2020 -0400
@@ -25,9 +25,9 @@
 
 ## -*- texinfo -*-
 ## @deftypefn  {} {} computer ()
-## @deftypefnx {} {@var{c} =} computer ()
-## @deftypefnx {} {[@var{c}, @var{maxsize}] =} computer ()
-## @deftypefnx {} {[@var{c}, @var{maxsize}, @var{endian}] =} computer ()
+## @deftypefnx {} {@var{comp} =} computer ()
+## @deftypefnx {} {[@var{comp}, @var{maxsize}] =} computer ()
+## @deftypefnx {} {[@var{comp}, @var{maxsize}, @var{endian}] =} computer ()
 ## @deftypefnx {} {@var{arch} =} computer ("arch")
 ## Print or return a string of the form @var{cpu}-@var{vendor}-@var{os} that
 ## identifies the type of computer that Octave is running on.
@@ -55,10 +55,13 @@
 ##
 ## If the argument @qcode{"arch"} is specified, return a string indicating the
 ## architecture of the computer on which Octave is running.
+##
+## Results may be different if Octave was invoked with the --traditional
+## option.
 ## @seealso{isunix, ismac, ispc}
 ## @end deftypefn
 
-function [c, maxsize, endian] = computer (a)
+function [comp, maxsize, endian] = computer (a)
 
   if (nargin > 1)
     print_usage ();
@@ -66,25 +69,45 @@
     error ('computer: "arch" is only valid argument');
   endif
 
+  canonical_host_type = __octave_config_info__ ("canonical_host_type");
+  traditional = __traditional__ ();
+  enable_64 = __octave_config_info__ ("ENABLE_64");
+  host_parts = ostrsplit (canonical_host_type, "-");
+
   if (nargin == 0)
-    msg = __octave_config_info__ ("canonical_host_type");
 
-    if (strcmp (msg, "unknown"))
-      msg = "Hi Dave, I'm a HAL-9000";
+    host = "";
+    if (traditional && enable_64)
+      if (ismac ())
+        host = "MACI64";
+      elseif (ispc ())
+        host = "PCWIN64";
+      elseif (strcmp ([host_parts{3} "-" host_parts{1}], "linux-x86_64"))
+        host = "GLNXA64";
+      endif
+    endif
+    if (isempty (host))
+      host = canonical_host_type;
+    elseif (strcmp (host, "unknown"))
+      host = "Hi Dave, I'm a HAL-9000";
     endif
 
     if (nargout == 0)
-      disp (msg);
+      disp (host);
     else
-      c = msg;
-      if (isargout (2))
-        if (__octave_config_info__ ("ENABLE_64"))
-          maxsize = 2^63-1;
+      comp = host;
+      if (nargout > 1)
+        if (enable_64)
+          if (traditional)
+            maxsize = 2^48-1;
+          else
+            maxsize = 2^63-1;
+          endif
         else
           maxsize = 2^31-1;
         endif
       endif
-      if (isargout (3))
+      if (nargout > 2)
         if (__octave_config_info__ ("words_big_endian"))
           endian = "B";
         elseif (__octave_config_info__ ("words_little_endian"))
@@ -94,13 +117,25 @@
         endif
       endif
     endif
+
   else
-    ## "arch" argument asked for
-    tmp = ostrsplit (__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});
+
+    ## "arch" case.
+    comp = "";
+    if (traditional && enable_64)
+      if (ismac ())
+        comp = "maci64";
+      elseif (ispc ())
+        comp = "win64";
+      elseif (strcmp ([host_parts{3} "-" host_parts{1}], "linux-x86_64"))
+        comp = "glnxa64";
+      endif
+    endif
+    if (isempty (comp))
+      comp = [host_parts{3} "-" host_parts{1}];
+      if (numel (host_parts) == 4)
+        comp = [host_parts{4} "-" comp];
+      endif
     endif
 
   endif
--- a/scripts/miscellaneous/copyfile.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/miscellaneous/copyfile.m	Tue Jul 07 19:40:20 2020 -0400
@@ -53,7 +53,7 @@
   endif
 
   max_cmd_line = 1024;
-  status = true;
+  sts = 1;
   msg = "";
   msgid = "";
 
@@ -87,13 +87,27 @@
   ## If f1 has more than 1 element then f2 must be a directory
   isdir = isfolder (f2);
   if (numel (f1) > 1 && ! isdir)
-    error ("copyfile: when copying multiple files, F2 must be a directory");
+    if (nargout == 0)
+      error ("copyfile: when copying multiple files, F2 must be a directory");
+    else
+      status = 0;
+      msg = "when copying multiple files, F2 must be a directory";
+      msgid = "copyfile";
+      return;
+    endif
   endif
 
   ## Protect the filename(s).
   f1 = glob (f1);
   if (isempty (f1))
-    error ("copyfile: no files to move");
+    if (nargout == 0)
+      error ("copyfile: no files to move");
+    else
+      status = 0;
+      msg = "no files to move";
+      msgid = "copyfile";
+      return;
+    endif
   endif
   p1 = sprintf ('"%s" ', f1{:});
   p2 = tilde_expand (f2);
@@ -118,7 +132,7 @@
       ## Copy the files.
       [err, msg] = system (sprintf ('%s %s"%s"', cmd, p1, p2));
       if (err != 0)
-        status = false;
+        sts = 0;
         msgid = "copyfile";
         break;
       endif
@@ -133,11 +147,19 @@
     ## Copy the files.
     [err, msg] = system (sprintf ('%s %s"%s"', cmd, p1, p2));
     if (err != 0)
-      status = false;
+      sts = 0;
       msgid = "copyfile";
     endif
   endif
 
+  if (nargout == 0)
+    if (sts == 0)
+      error ("copyfile: operation failed: %s", msg);
+    endif
+  else
+    status = sts;
+  endif
+
 endfunction
 
 
@@ -172,3 +194,4 @@
 %!error <F1 must be a string> copyfile (1, "foobar")
 %!error <F2 must be a string> copyfile ("foobar", 1)
 %!error <F2 must be a directory> copyfile ({"a", "b"}, "%_NOT_A_DIR_%")
+%!error <no files to move> copyfile ("%_NOT_A_FILENAME1_%", "%_NOT_A_FILENAME2_%")
--- a/scripts/miscellaneous/delete.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/miscellaneous/delete.m	Tue Jul 07 19:40:20 2020 -0400
@@ -80,7 +80,7 @@
 %!   delete (file);
 %!   assert (! exist (file, "file"));
 %! unwind_protect_cleanup
-%!   unlink (file);
+%!   sts = unlink (file);
 %! end_unwind_protect
 
 %!test
--- a/scripts/miscellaneous/dir.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/miscellaneous/dir.m	Tue Jul 07 19:40:20 2020 -0400
@@ -224,7 +224,7 @@
 %!   chdir (orig_dir);
 %!   confirm_recursive_rmdir (false, "local");
 %!   if (exist (tmp_dir))
-%!     rmdir (tmp_dir, "s");
+%!     sts = rmdir (tmp_dir, "s");
 %!   endif
 %! end_unwind_protect
 
@@ -238,7 +238,7 @@
 %!   assert (list(1).folder, canonicalize_file_name (tmp_dir));
 %! unwind_protect_cleanup
 %!   if (exist (tmp_dir))
-%!     rmdir (tmp_dir);
+%!     sts = rmdir (tmp_dir);
 %!   endif
 %! end_unwind_protect
 
--- a/scripts/miscellaneous/fieldnames.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/miscellaneous/fieldnames.m	Tue Jul 07 19:40:20 2020 -0400
@@ -28,19 +28,19 @@
 ## @deftypefnx {} {@var{names} =} fieldnames (@var{obj})
 ## @deftypefnx {} {@var{names} =} fieldnames (@var{javaobj})
 ## @deftypefnx {} {@var{names} =} fieldnames ("@var{javaclassname}")
-## Return a cell array of strings with the names of the fields in the
-## specified input.
+## Return a cell array of strings with the names of the fields in the specified
+## input.
 ##
-## When the input is a structure @var{struct}, the names are the elements of
-## the structure.
+## When the input is a structure @var{struct}, the @var{names} are the elements
+## of the structure.
 ##
-## When the input is an Octave object @var{obj}, the names are the public
+## When the input is an Octave object @var{obj}, the @var{names} are the public
 ## properties of the object.
 ##
 ## When the input is a Java object @var{javaobj} or a string containing the
-## name of a Java class @var{javaclassname}, the names are the public fields
-## (data members) of the object or class.
-## @seealso{numfields, isfield, orderfields, struct, methods}
+## name of a Java class @var{javaclassname}, the @var{names} are the public
+## fields (data members) of the object or class.
+## @seealso{numfields, isfield, orderfields, struct, properties}
 ## @end deftypefn
 
 function names = fieldnames (obj)
@@ -49,9 +49,14 @@
     print_usage ();
   endif
 
-  if (isstruct (obj) || isobject (obj))
-    ## Call internal C++ function for structs or Octave objects
+  if (isstruct (obj))
     names = __fieldnames__ (obj);
+  elseif (isobject (obj))
+    try
+      names = properties (obj);      ## classdef object
+    catch
+      names = __fieldnames__ (obj);  ## @class object
+    end_try_catch
   elseif (isjava (obj) || ischar (obj))
     ## FIXME: Function prototype that accepts java obj exists, but doesn't
     ##        work if obj is java.lang.String.  Convert obj to classname.
@@ -70,22 +75,34 @@
 endfunction
 
 
-## test preservation of fieldname order
+## Test preservation of fieldname order
 %!test
 %! x(3).d=1;  x(2).a=2;  x(1).b=3;  x(2).c=3;
 %! assert (fieldnames (x), {"d"; "a"; "b"; "c"});
 
-## test empty structure
+## Test empty structure
 %!test
 %! s = struct ();
 %! assert (fieldnames (s), cell (0, 1));
 
-## test Java classname by passing classname
+## Test classdef object
+%!test
+%! m = containers.Map (); 
+%! f = fieldnames (m);
+%! assert (f, {"Count"; "KeyType"; "ValueType"; "map"; "numeric_keys"});
+
+## Test old-style @class object
+%!test
+%! obj = ftp ();
+%! f = fieldnames (obj);
+%! assert (f, {"host"; "username"; "password"; "curlhandle"});
+
+## Test Java classname by passing classname
 %!testif HAVE_JAVA; usejava ("jvm")
 %! names = fieldnames ("java.lang.Double");
 %! assert (any (strcmp (names, "MAX_VALUE")));
 
-## test Java classname by passing java object
+## Test Java classname by passing java object
 %!testif HAVE_JAVA; usejava ("jvm")
 %! names = fieldnames (javaObject ("java.lang.Double", 10));
 %! assert (any (strcmp (names, "MAX_VALUE")));
--- a/scripts/miscellaneous/fileattrib.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/miscellaneous/fileattrib.m	Tue Jul 07 19:40:20 2020 -0400
@@ -24,13 +24,16 @@
 ########################################################################
 
 ## -*- texinfo -*-
-## @deftypefn  {} {} fileattrib (@var{file})
-## @deftypefnx {} {} fileattrib ()
+## @deftypefn  {} {} fileattrib ()
+## @deftypefnx {} {} fileattrib (@var{file})
+## @deftypefnx {} {[@var{status}, @var{attrib}] =} fileattrib (@dots{})
 ## @deftypefnx {} {[@var{status}, @var{msg}, @var{msgid}] =} fileattrib (@dots{})
-## Return information about @var{file}.
+## Report attribute information about @var{file}.
 ##
-## If successful, @var{status} is 1 and @var{msg} is a structure with the
-## following fields:
+## If no file or directory is specified, report information about the present
+## working directory.
+##
+## If successful, the output is a structure with the following fields:
 ##
 ## @table @code
 ## @item Name
@@ -64,17 +67,20 @@
 ## True if the user (group; other users) has execute permission for @var{file}.
 ## @end table
 ##
-## If an attribute does not apply (i.e., archive on a Unix system) then the
+## If an attribute does not apply (e.g., archive on a Unix system) then the
 ## field is set to NaN.
 ##
-## If @code{attrib} fails, @var{msg} is a non-empty string containing an
-## error message and @var{msg_id} is the non-empty string @qcode{"fileattrib"}.
+## If @var{file} contains globbing characters, information about all matching
+## files is returned in a structure array.
 ##
-## With no input arguments, return information about the current directory.
-##
-## If @var{file} contains globbing characters, return information about all
-## the matching files.
-## @seealso{glob}
+## If outputs are requested, the first is @var{status} which takes the value 1
+## when the operation was successful, and 0 otherwise.  The second output
+## contains the structure described above (@var{attrib}) if the operation was
+## successful; otherwise, the second output is a system-dependent error message
+## (@var{msg}).  The third output is an empty string ("") when the operation
+## was successful, or a unique message identifier (@var{msgid}) in the case of
+## failure.
+## @seealso{stat, glob}
 ## @end deftypefn
 
 function [status, msg, msgid] = fileattrib (file = ".")
@@ -87,7 +93,7 @@
     error ("fileattrib: FILE must be a string");
   endif
 
-  status = true;
+  sts = 1;
   msg = "";
   msgid = "";
 
@@ -108,10 +114,9 @@
         r(i).hidden = NaN;
       else
         [~, attrib] = dos (sprintf ('attrib "%s"', r(i).Name));
-        ## dos never returns error status so have to check it indirectly
+        ## DOS never returns error status so have to check it indirectly
         if (! isempty (strfind (attrib, " -")))
-          status = false;
-          msgid = "fileattrib";
+          sts = 0;
           break;
         endif
         attrib = regexprep (attrib, '\S+:.*', "");
@@ -142,15 +147,23 @@
         r(i).OtherExecute = NaN;
       endif
     else
-      status = false;
-      msgid = "fileattrib";
+      sts = 0;
       break;
     endif
   endfor
 
-  if (status)
-    if (nargout == 0)
-      status = r;
+  if (nargout == 0)
+    if (! sts)
+      error ("fileattrib: operation failed");
+    endif
+    status = r;
+  else
+    status = sts;
+    if (! sts)
+      if (isempty (msg))
+        msg = "operation failed";
+      endif
+      msgid = "fileattrib";
     else
       msg = r;
     endif
--- a/scripts/miscellaneous/fullfile.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/miscellaneous/fullfile.m	Tue Jul 07 19:40:20 2020 -0400
@@ -25,16 +25,17 @@
 
 ## -*- texinfo -*-
 ## @deftypefn  {} {@var{filename} =} fullfile (@var{dir1}, @var{dir2}, @dots{}, @var{file})
-## @deftypefnx {} {@var{filenames} =} fullfile (@dots{}, @var{files})
 ## Build complete filename from separate parts.
 ##
-## Joins any number of path components intelligently.  The return value is
-## the concatenation of each component with exactly one file separator
-## between each non empty part and at most one leading and/or trailing file
+## The function joins any number of path components intelligently.  The return
+## value is the concatenation of each component with exactly one file separator
+## between each part of the path and at most one leading and/or trailing file
 ## separator.
 ##
-## If the last component part is a cell array, returns a cell array of
-## filepaths, one for each element in the last component, e.g.:
+## The input arguments might be strings or cell strings.  Any input arguments
+## that are cell strings must contain one single string or must be equal in
+## size.  In that case, the function returns a cell string of filepaths of the
+## same dimensions as the input cell strings, e.g.:
 ##
 ## @example
 ## @group
@@ -49,7 +50,7 @@
 ## @end example
 ##
 ## On Windows systems, while forward slash file separators do work, they are
-## replaced by backslashes; in addition drive letters are stripped of leading
+## replaced by backslashes.  In addition, drive letters are stripped of leading
 ## file separators to obtain a valid file path.
 ##
 ## Note: @code{fullfile} does not perform any validation of the resulting full
@@ -59,19 +60,58 @@
 
 function filename = fullfile (varargin)
 
-  if (nargin && iscell (varargin{end}))
-    filename = cellfun (@(x) fullfile (varargin{1:end-1}, x), varargin{end},
-                                       "UniformOutput", false);
-  else
-    non_empty = cellfun ("isempty", varargin);
-    unc = 0;
-    if (ispc && ! isempty (varargin))
-      varargin = strrep (varargin, '/', filesep);
-      unc = strncmp (varargin{1}, '\\', 2);
-      varargin(1) = regexprep (varargin{1}, '[\\/]*([a-zA-Z]:[\\/]*)', "$1");
-    endif
-    filename = strjoin (varargin(! non_empty), filesep);
-    filename(unc + strfind (filename(1+unc : end), [filesep filesep])) = "";
+  ## remove empty arguments
+  varargin(cellfun (@isempty, varargin)) = [];
+
+  if (isempty (varargin))
+    ## return early for all empty or no input
+    filename = "";
+    return;
+  endif
+
+  ## check input type
+  is_cellstr = cellfun (@iscellstr, varargin);
+  if (! all (is_cellstr | cellfun (@ischar, varargin)))
+    error ("fullfile: input must either be strings or cell strings");
+  endif
+
+  ## convert regular strings to cell strings
+  varargin(! is_cellstr) = num2cell (varargin(! is_cellstr));
+
+  ## check if input size matches
+  if (numel (varargin) > 1 && common_size (varargin{:}) != 0)
+    error ("fullfile: cell string input must be scalar or of the same size");
+  endif
+
+  fs = filesep ();
+
+  if (ispc ())
+    ## replace forward slashes with backslashes
+    varargin = cellfun (@(x) strrep (x, "/", fs), varargin,
+                        "UniformOutput", false);
+
+    ## Strip fileseps preceeding drive letters
+    varargin{1} = regexprep (varargin{1}, '\\*([a-zA-Z]:\\*)', "$1");
+
+    unc = strncmp (varargin{1}, '\\', 2);
+  endif
+
+  ## insert file separator between elements
+  varargin(2,:) = {fs};
+  varargin{end} = "";
+
+  filename = strcat (varargin{:});
+
+  ## remove multiplicate file separators
+  filename = regexprep (filename, [undo_string_escapes(fs), "*"], fs);
+
+  if (ispc ())
+    ## prepend removed file separator for UNC paths
+    filename(unc) = strcat (fs, filename(unc));
+  endif
+
+  if (! any (is_cellstr))
+    filename = filename{1};
   endif
 
 endfunction
@@ -79,13 +119,14 @@
 
 %!shared fs, fsx, xfs, fsxfs, xfsy, xfsyfs
 %! fs = filesep ();
-%! fsx = [fs "x"];
-%! xfs = ["x" fs];
-%! fsxfs = [fs "x" fs];
-%! xfsy = ["x" fs "y"];
-%! xfsyfs = ["x" fs "y" fs];
+%! fsx = [fs, "x"];
+%! xfs = ["x", fs];
+%! fsxfs = [fs, "x", fs];
+%! xfsy = ["x", fs, "y"];
+%! xfsyfs = ["x", fs, "y", fs];
 
 %!assert (fullfile (""), "")
+%!assert (fullfile ("", ""), "")
 %!assert (fullfile (fs), fs)
 %!assert (fullfile ("", fs), fs)
 %!assert (fullfile (fs, ""), fs)
@@ -105,32 +146,39 @@
 %!assert (fullfile (fs, "x", fs), fsxfs)
 
 %!assert (fullfile ("x/", "/", "/", "y", "/", "/"), xfsyfs)
-%!assert (fullfile ("/", "x/", "/", "/", "y", "/", "/"), [fs xfsyfs])
-%!assert (fullfile ("/x/", "/", "/", "y", "/", "/"), [fs xfsyfs])
+%!assert (fullfile ("/", "x/", "/", "/", "y", "/", "/"), [fs, xfsyfs])
+%!assert (fullfile ("/x/", "/", "/", "y", "/", "/"), [fs, xfsyfs])
 
 ## different on purpose so that "fullfile (c{:})" works for empty c
 %!assert (fullfile (), "")
 
-%!assert (fullfile ("x", "y", {"c", "d"}), {[xfsyfs "c"], [xfsyfs "d"]})
+%!assert (fullfile ("x", "y", {"c", "d"}), {[xfsyfs, "c"], [xfsyfs, "d"]})
+%!assert (fullfile ({"folder1", "folder2"}, "sub", {"f1.m", "f2.m"}), ...
+%!        {["folder1", fs, "sub", fs, "f1.m"], ...
+%!         ["folder2", fs, "sub", fs, "f2.m"]});
 
 ## Windows specific - drive letters and file sep type
-%!test
-%! if (ispc)
-%!   assert (fullfile ('\/\/\//A:/\/\', "x/", "/", "/", "y", "/", "/"), ...
-%!           ['A:\' xfsyfs]);
-%! endif
+%!testif ; ispc ()
+%! assert (fullfile ('\/\/\//A:/\/\', "x/", "/", "/", "y", "/", "/"), ...
+%!         ['A:\' xfsyfs]);
 
 ## *nix specific - double backslash
-%!test
-%! if (isunix || ismac)
-%!   assert (fullfile (fs, fs), fs);
-%! endif
+%!testif ; ! ispc ()
+%! assert (fullfile (fs, fs), fs);
+
+## Windows specific - UNC path
+%!testif ; ispc ()
+%! assert (fullfile ({'\/\//server1', 'C:', '\\server2\/'}, ...
+%!                   "x/", "/", "/", "y", "/", "/"), ...
+%!         {['\\server1\', xfsyfs], ['C:\', xfsyfs], ['\\server2\', xfsyfs]});
 
 ## Windows specific - drive letters and file sep type, cell array
-%!test
-%! if (ispc)
-%!  tmp = fullfile ({"\\\/B:\//", "A://c", "\\\C:/g/h/i/j\/"});
-%!  assert (tmp{1}, 'B:\');
-%!  assert (tmp{2}, 'A:\c');
-%!  assert (tmp{3}, 'C:\g\h\i\j\');
-%! endif
+%!testif ; ispc ()
+%! tmp = fullfile ({'\\\/B:\//', 'A://c', '\\\C:/g/h/i/j\/'});
+%! assert (tmp{1}, 'B:\');
+%! assert (tmp{2}, 'A:\c');
+%! assert (tmp{3}, 'C:\g\h\i\j\');
+
+%!error <strings or cell strings> fullfile (1)
+%!error <strings or cell strings> fullfile ({1})
+%!error <same size> fullfile ({"a", "b"}, {"a", "b", "c"})
--- a/scripts/miscellaneous/isfolder.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/miscellaneous/isfolder.m	Tue Jul 07 19:40:20 2020 -0400
@@ -70,8 +70,8 @@
 %!   addpath (d);
 %!   assert (! isfolder (n));
 %! unwind_protect_cleanup
-%!   try, rmdir (tmp); end_try_catch
-%!   try, rmpath (d); end_try_catch
+%!   sts = rmdir (tmp);
+%!   rmpath (d);
 %! end_unwind_protect
 
 ## Test input validation
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/miscellaneous/memory.m	Tue Jul 07 19:40:20 2020 -0400
@@ -0,0 +1,265 @@
+########################################################################
+##
+## Copyright (C) 2020 The Octave Project Developers
+##
+## See the file COPYRIGHT.md in the top-level directory of this
+## distribution or <https://octave.org/copyright/>.
+##
+## This file is part of Octave.
+##
+## Octave is free software: you can 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
+## <https://www.gnu.org/licenses/>.
+##
+########################################################################
+
+## -*- texinfo -*-
+## @deftypefn  {} {} memory ()
+## @deftypefnx {} {[@var{userdata}, @var{systemdata}] =} memory ()
+## Display or return information about memory usage by Octave.
+##
+## If the function is called without output arguments, a table with an overview
+## of the current memory consumption is displayed.
+##
+## The output argument @var{userdata} is a structure with the following fields
+## containing data for the Octave process:
+## @table @code
+## @item @var{MaxPossibleArrayBytes}
+## Maximum size for an array to be allocated.  Be aware that this includes
+## @emph{all} physical memory and swap space.  Allocating that amount of memory
+## might result in system instability, data corruption and/or file system
+## curruption.  Note that dependend on the platform (32bit systems), the largest
+## contiguous memory block might further limit the maximum possible allocatable
+## array.  This check is currently not implemented.
+##
+## @item @var{MemAvailableAllArrays}
+## The total size of available memory in bytes.
+##
+## @item @var{ram_available_all_arrays}
+## The maximum size for an array that can be allocated in physical memory
+## (excluding swap space).  Note that dependend on the platform (32bit systems),
+## the largest contiguous memory block might further limit the maximum possible
+## allocatable array.  This check is currently not implemented.
+##
+## @item @var{MemUsedMATLAB}
+## @itemx @var{mem_used_octave}
+## The memory (including swap space) currently used by Octave in bytes.
+##
+## @item @var{ram_used_octave}
+## The physical memory (excluding swap space) currently used by Octave in bytes.
+##
+## @end table
+##
+## The output argument @var{systemdata} is a nested structure with the following
+## fields containing information about the system's memory:
+## @table @code
+## @item @var{PhysicalMemory.Available}
+## The currently available pyhsical memory in bytes.
+##
+## @item @var{PhysicalMemory.Total}
+## The total pyhsical memory in bytes.
+##
+## @item @var{SystemMemory.Available}
+## The currently available memory (including swap space) in bytes.
+##
+## @item @var{SystemMemory.Total}
+## The total memory (including swap space) in bytes.
+##
+## @item @var{VirtualAddressSpace.Available}
+## The currently available virtual address space in bytes.
+##
+## @item @var{VirtualAddressSpace.Total}
+## The total virtual address space in bytes.
+##
+## @end table
+##
+## @example
+## @group
+## memory ()
+##    @result{} System    RAM: 3934008 KiB,  swap: 4087804 KiB
+##       Octave    RAM:  170596 KiB,  virt: 1347944 KiB
+##       Free      RAM: 1954940 KiB,  swap: 4087804 KiB
+##       Available RAM: 2451948 KiB, total: 6042744 KiB
+## @end group
+##
+## @group
+## [userdata, systemdata] = memory ()
+##    @result{} userdata =
+##      scalar structure containing the fields:
+##      MaxPossibleArrayBytes = 6.1622e+09
+##      MemAvailableAllArrays = 6.1622e+09
+##      ram_available_all_arrays = 2.4883e+09
+##      MemUsedMATLAB = 1.3825e+09
+##      mem_used_octave = 1.3825e+09
+##      ram_used_octave = 1.7824e+08
+##
+##    systemdata =
+##      scalar structure containing the fields:
+##      PhysicalMemory =
+##        scalar structure containing the fields:
+##          Available = 2.4954e+09
+##          Total = 4.0284e+09
+##      SystemMemory =
+##        scalar structure containing the fields:
+##          Available = 6.6813e+09
+##          Total = 8.2143e+09
+##      VirtualAddressSpace =
+##        scalar structure containing the fields:
+##          Available = 2.8147e+14
+##          Total = 2.8147e+14
+## @end group
+## @end example
+##
+## This function is implemented for Linux and Windows only.
+##
+## @seealso{computer, getpid, getrusage, nproc, uname}
+## @end deftypefn
+
+function [userdata, systemdata] = memory ()
+
+  if (! isunix () && ! ispc ())
+    if (nargout > 0)
+      error ('memory: function not yet implemented for this architecture');
+    else
+      warning ('memory: function not yet implemented for this architecture');
+    endif
+    return;
+  endif
+
+  kiB = 1024;
+  [architecture, bits] = computer ();
+
+  if (isunix ())
+    ## Read values from pseudofiles
+    [status, meminfo] = lmemory ();
+
+    ## FIXME: Query the actual size of the user address space,
+    ## e.g. with getrlimit (RLIMIT_AS, rlp)
+    if (log2 (bits) > 32)
+      ## 64bit platform
+      address_space = 2^48;  # 256 TiB
+    else
+      ## 32bit platform
+      address_space =  3 * 2^30;  # 3 GiB
+    endif
+
+    total_ram = meminfo.MemTotal * kiB;
+    total_swap = meminfo.SwapTotal * kiB;
+    free_ram = meminfo.MemFree * kiB;
+    if isfield (meminfo, "MemAvailable")
+      available_ram = meminfo.MemAvailable * kiB;
+    else
+      ## On kernels from before 2014 MemAvailable is not present.
+      ## This is a rough estimate that can be used instead.
+      available_ram = (meminfo.MemFree + meminfo.Cached) * kiB;
+    endif
+    free_swap = meminfo.SwapFree * kiB;
+    used_ram = status.VmRSS * kiB;
+    used_virtual = status.VmSize * kiB;
+    avail_virtual = address_space - used_virtual;
+
+  elseif (ispc ())
+    [proc, sys] = __wmemory__ ();
+
+    total_ram = sys.TotalPhys;
+    total_swap = sys.TotalPageFile;
+    available_ram = sys.AvailPhys;
+    free_swap = sys.AvailPageFile;
+    used_ram = proc.WorkingSetSize;
+    used_virtual = proc.WorkingSetSize + proc.PagefileUsage;
+    avail_virtual = sys.AvailVirtual;
+    address_space = sys.TotalVirtual;
+
+  endif
+
+  available = min (available_ram + free_swap, avail_virtual);
+  ram_available = min (available_ram, avail_virtual);
+
+  ## FIXME: On 32bit systems, the largest possible array is limited by the
+  ## largest contiguous block in memory.
+  user.MaxPossibleArrayBytes = available;
+  user.MemAvailableAllArrays = available;
+  user.ram_available_all_arrays = ram_available;
+  user.MemUsedMATLAB = used_virtual;  # For Compatibility
+  user.mem_used_octave = used_virtual;
+  user.ram_used_octave = used_ram;
+
+  syst.PhysicalMemory.Available = available_ram;
+  syst.PhysicalMemory.Total = total_ram;
+  syst.SystemMemory.Available = available_ram + free_swap;
+  syst.SystemMemory.Total = total_ram + total_swap;
+  syst.VirtualAddressSpace.Available = avail_virtual;
+  syst.VirtualAddressSpace.Total = address_space;
+
+
+  if (nargout)
+    userdata = user;
+    systemdata = syst;
+  else
+    unitsize = kiB;
+    unitname = 'kiB';
+    disp (sprintf ('Octave is running on %s', architecture))
+    disp (sprintf ('System    RAM: %9.0f %s,  swap: %9.0f %s',
+                   round (syst.PhysicalMemory.Total / unitsize), unitname,
+                   round (total_swap / unitsize), unitname ))
+    disp (sprintf ('Octave    RAM: %9.0f %s,  virt: %9.0f %s',
+                   round (user.ram_used_octave / unitsize), unitname,
+                   round (user.mem_used_octave / unitsize), unitname))
+    if (isunix ())
+      ## The concept of free vs. available RAM doesn't seem to exist on Windows
+      disp (sprintf ('Free      RAM: %9.0f %s,  swap: %9.0f %s',
+                     round (free_ram / unitsize), unitname,
+                     round (free_swap / unitsize), unitname))
+    endif
+    disp (sprintf ('Available RAM: %9.0f %s, total: %9.0f %s',
+                   round (user.ram_available_all_arrays / unitsize), unitname,
+                   round (user.MemAvailableAllArrays / unitsize), unitname))
+  endif
+
+endfunction
+
+function [status, meminfo] = lmemory ()
+  ## Read pseudo files to gather memory information on Linux
+
+  ## Read the proc/self/status pseudofile
+  ## see https://linuxwiki.de/proc/pid#A.2Fproc.2Fpid.2Fstatus
+  ## It contains a variable number of lines with name-value pairs.
+
+  f = fopen ('/proc/self/status');
+  buffer = textscan (f, '%s %s', 'delimiter', ':\n');
+  fclose (f);
+  for i = 1:size (buffer{1}, 1)
+    status.(buffer{1}{i}) = textscan (buffer{2}{i}){1};
+  endfor
+
+  ## Read the /proc/meminfo pseudofile
+  ## see https://linuxwiki.de/proc/meminfo
+  ## It contains a variable number of lines with name-value pairs.
+
+  f = fopen ('/proc/meminfo');
+  buffer = textscan (f, '%s %s', 'delimiter', ':\n');
+  fclose (f);
+  for i = 1:size (buffer{1}, 1)
+    meminfo.(buffer{1}{i}) = textscan (buffer{2}{i}){1};
+  endfor
+
+endfunction
+
+
+%!testif ; isunix () || ispc ()
+%! [user, syst] = memory ();
+%! assert (user.mem_used_octave > 0);
+%! assert (user.ram_used_octave <= user.mem_used_octave);
+%! assert (user.mem_used_octave < syst.SystemMemory.Total);
+%! assert (user.MemAvailableAllArrays <= syst.SystemMemory.Available);
+
--- a/scripts/miscellaneous/mkdir.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/miscellaneous/mkdir.m	Tue Jul 07 19:40:20 2020 -0400
@@ -112,7 +112,7 @@
 %!   assert (isfolder (dir));
 %! unwind_protect_cleanup
 %!   confirm_recursive_rmdir (false, "local");
-%!   rmdir (dir1, "s");
+%!   sts = rmdir (dir1, "s");
 %! end_unwind_protect
 
 %!test <*53031>
@@ -125,8 +125,8 @@
 %!   assert (status);
 %!   assert (isfolder (fullfile (tmp_dir, "subdir")));
 %! unwind_protect_cleanup
-%!   rmdir (fullfile (tmp_dir, "subdir"));
-%!   rmdir (tmp_dir);
+%!   sts = rmdir (fullfile (tmp_dir, "subdir"));
+%!   sts = rmdir (tmp_dir);
 %!   if (isempty (HOME))
 %!     unsetenv ("HOME");
 %!   else
--- a/scripts/miscellaneous/module.mk	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/miscellaneous/module.mk	Tue Jul 07 19:40:20 2020 -0400
@@ -45,6 +45,7 @@
   %reldir%/loadobj.m \
   %reldir%/ls.m \
   %reldir%/ls_command.m \
+  %reldir%/memory.m \
   %reldir%/menu.m \
   %reldir%/methods.m \
   %reldir%/mex.m \
--- a/scripts/miscellaneous/movefile.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/miscellaneous/movefile.m	Tue Jul 07 19:40:20 2020 -0400
@@ -59,7 +59,7 @@
   endif
 
   max_cmd_line = 1024;
-  status = true;
+  sts = 1;
   msg = "";
   msgid = "";
 
@@ -96,13 +96,27 @@
   ## If f1 has more than 1 element f2 must be a directory
   isdir = isfolder (f2);
   if (numel (f1) > 1 && ! isdir)
-    error ("movefile: when moving multiple files, F2 must be a directory");
+    if (nargout == 0)
+      error ("movefile: when copying multiple files, F2 must be a directory");
+    else
+      status = 0;
+      msg = "when copying multiple files, F2 must be a directory";
+      msgid = "movefile";
+      return;
+    endif
   endif
 
   ## Protect the filename(s).
   f1 = glob (f1);
   if (isempty (f1))
-    error ("movefile: no files to move");
+    if (nargout == 0)
+      error ("movefile: no files to move");
+    else
+      status = 0;
+      msg = "no files to move";
+      msgid = "movefile";
+      return;
+    endif
   endif
   p1 = sprintf ('"%s" ', f1{:});
   p2 = tilde_expand (f2);
@@ -129,11 +143,11 @@
       ## Move the file(s).
       [err, msg] = system (sprintf ('%s %s "%s"', cmd, p1, p2));
       if (err != 0)
-        status = false;
+        sts = 0;
         msgid = "movefile";
       endif
       ## Load new file(s) in editor
-      __event_manager_file_renamed__ (status);
+      __event_manager_file_renamed__ (sts);
     endwhile
   else
     if (ispc () && ! isunix ()
@@ -147,11 +161,19 @@
     ## Move the file(s).
     [err, msg] = system (sprintf ('%s %s "%s"', cmd, p1, p2));
     if (err != 0)
-      status = false;
+      sts = 0;
       msgid = "movefile";
     endif
     ## Load new file(s) in editor
-    __event_manager_file_renamed__ (status);
+    __event_manager_file_renamed__ (sts);
+  endif
+
+  if (nargout == 0)
+    if (sts == 0)
+      error ("movefile: operation failed: %s", msg);
+    endif
+  else
+    status = sts;
   endif
 
 endfunction
@@ -187,3 +209,4 @@
 %!error <F1 must be a string> movefile (1, "foobar")
 %!error <F2 must be a string> movefile ("foobar", 1)
 %!error <F2 must be a directory> movefile ({"a", "b"}, "%_NOT_A_DIR_%")
+%!error <no files to move> movefile ("%_NOT_A_FILENAME1_%", "%_NOT_A_FILENAME2_%")
--- a/scripts/miscellaneous/run.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/miscellaneous/run.m	Tue Jul 07 19:40:20 2020 -0400
@@ -114,7 +114,7 @@
 %!   assert (_5yVNhWVJWJn47RKnzxPsyb_, 1337);
 %! unwind_protect_cleanup
 %!   unlink (test_script);
-%!   rmdir (tmp_dir);
+%!   sts = rmdir (tmp_dir);
 %! end_unwind_protect
 
 ## Test function file execution
@@ -140,7 +140,7 @@
 %!   assert (tstval2, true);
 %! unwind_protect_cleanup
 %!   unlink (test_function);
-%!   rmdir (tmp_dir);
+%!   sts = rmdir (tmp_dir);
 %!   path (path_orig);
 %! end_unwind_protect
 
--- a/scripts/miscellaneous/tar.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/miscellaneous/tar.m	Tue Jul 07 19:40:20 2020 -0400
@@ -149,12 +149,8 @@
 %!   chdir (orig_dir);
 %!   unlink (tarname);
 %!   confirm_recursive_rmdir (false, "local");
-%!   if (exist (dirname))
-%!     rmdir (dirname, "s");
-%!   endif
-%!   if (exist (outdir))
-%!     rmdir (outdir, "s");
-%!   endif
+%!   sts = rmdir (dirname, "s");
+%!   sts = rmdir (outdir, "s");
 %! end_unwind_protect
 
 ## Test input validation
--- a/scripts/miscellaneous/unpack.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/miscellaneous/unpack.m	Tue Jul 07 19:40:20 2020 -0400
@@ -372,7 +372,7 @@
 %!     unlink (filename);
 %!     unlink ([filename ".orig"]);
 %!     confirm_recursive_rmdir (false, "local");
-%!     rmdir (dirname, "s");
+%!     sts = rmdir (dirname, "s");
 %!   end_unwind_protect
 %! unwind_protect_cleanup
 %!   ## Restore environment variables TMPDIR, TMP
--- a/scripts/miscellaneous/zip.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/miscellaneous/zip.m	Tue Jul 07 19:40:20 2020 -0400
@@ -126,11 +126,11 @@
 %!     error ("unzipped file not equal to original file!");
 %!   endif
 %! unwind_protect_cleanup
-%!   unlink (filename);
-%!   unlink ([dirname, filesep, basename, ext]);
-%!   unlink (zipfile);
-%!   unlink ([zipfile ".zip"]);
-%!   rmdir (dirname);
+%!   sts = unlink (filename);
+%!   sts = unlink ([dirname, filesep, basename, ext]);
+%!   sts = unlink (zipfile);
+%!   sts = unlink ([zipfile ".zip"]);
+%!   sts = rmdir (dirname);
 %! end_unwind_protect
 
 ## Test input validation
--- a/scripts/path/pathdef.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/path/pathdef.m	Tue Jul 07 19:40:20 2020 -0400
@@ -112,7 +112,7 @@
 %!   assert (! isempty (strfind (p1, tmp_dir)))
 %!   assert (isempty (strfind (p2, tmp_dir)))
 %! unwind_protect_cleanup
-%!   rmdir (tmp_dir);
+%!   sts = rmdir (tmp_dir);
 %!   path (path_orig);
 %! end_unwind_protect
 
@@ -128,7 +128,7 @@
 %!   path_2 = path ();
 %!   assert (path_1, path_2)
 %! unwind_protect_cleanup
-%!   rmdir (tmp_dir);
+%!   sts = rmdir (tmp_dir);
 %!   path (path_orig);
 %! end_unwind_protect
 
--- a/scripts/path/savepath.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/path/savepath.m	Tue Jul 07 19:40:20 2020 -0400
@@ -230,6 +230,6 @@
 %!   end_unwind_protect
 %! unwind_protect_cleanup
 %!   confirm_recursive_rmdir (false, "local");
-%!   rmdir (test_dir, "s");
+%!   sts = rmdir (test_dir, "s");
 %!   unlink (fname);
 %! end_unwind_protect
--- a/scripts/pkg/pkg.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/pkg/pkg.m	Tue Jul 07 19:40:20 2020 -0400
@@ -567,7 +567,7 @@
                  global_list, global_install);
 
       unwind_protect_cleanup
-        cellfun ("unlink", local_files);
+        [~] = cellfun ("unlink", local_files);
         if (exist (tmp_dir, "file"))
           rmdir (tmp_dir, "s");
         endif
--- a/scripts/pkg/private/build.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/pkg/private/build.m	Tue Jul 07 19:40:20 2020 -0400
@@ -95,7 +95,7 @@
 
     ## Currently does nothing because gzip() removes the original tar
     ## file but that should change in the future (bug #43431).
-    unlink (tar_path);
+    [~] = unlink (tar_path);
   endfor
 
 endfunction
--- a/scripts/pkg/private/configure_make.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/pkg/private/configure_make.m	Tue Jul 07 19:40:20 2020 -0400
@@ -88,7 +88,7 @@
       cmd = ["cd '" src "'; " scenv " ./configure " flags];
       [status, output] = shell (cmd, verbose);
       if (status != 0)
-        rmdir (desc.dir, "s");
+        sts = rmdir (desc.dir, "s");
         disp (output);
         error ("pkg: error running the configure script for %s.", desc.name);
       endif
@@ -105,7 +105,7 @@
       [status, output] = shell (sprintf ("%s make --jobs %i --directory '%s'",
                                          scenv, jobs, src), verbose);
       if (status != 0)
-        rmdir (desc.dir, "s");
+        sts = rmdir (desc.dir, "s");
         disp (output);
         error ("pkg: error running 'make' for the %s package.", desc.name);
       endif
--- a/scripts/pkg/private/install.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/pkg/private/install.m	Tue Jul 07 19:40:20 2020 -0400
@@ -145,7 +145,7 @@
   catch
     ## Something went wrong, delete tmpdirs.
     for i = 1:length (tmpdirs)
-      rmdir (tmpdirs{i}, "s");
+      sts = rmdir (tmpdirs{i}, "s");
     endfor
     rethrow (lasterror ());
   end_try_catch
@@ -199,7 +199,7 @@
   catch
     ## Something went wrong, delete tmpdirs.
     for i = 1:length (tmpdirs)
-      rmdir (tmpdirs{i}, "s");
+      sts = rmdir (tmpdirs{i}, "s");
     endfor
     rethrow (lasterror ());
   end_try_catch
@@ -218,7 +218,7 @@
   catch
     ## Something went wrong, delete tmpdirs.
     for i = 1:length (tmpdirs)
-      rmdir (tmpdirs{i}, "s");
+      sts = rmdir (tmpdirs{i}, "s");
     endfor
     rethrow (lasterror ());
   end_try_catch
@@ -237,11 +237,11 @@
   catch
     ## Something went wrong, delete tmpdirs.
     for i = 1:length (tmpdirs)
-      rmdir (tmpdirs{i}, "s");
+      sts = rmdir (tmpdirs{i}, "s");
     endfor
     for i = 1:length (descriptions)
-      rmdir (descriptions{i}.dir, "s");
-      rmdir (getarchdir (descriptions{i}), "s");
+      sts = rmdir (descriptions{i}.dir, "s");
+      sts = rmdir (getarchdir (descriptions{i}), "s");
     endfor
     rethrow (lasterror ());
   end_try_catch
@@ -252,8 +252,8 @@
     if (dirempty (descriptions{i}.dir, {"packinfo", "doc"})
         && dirempty (getarchdir (descriptions{i})))
       warning ("package %s is empty\n", descriptions{i}.name);
-      rmdir (descriptions{i}.dir, "s");
-      rmdir (getarchdir (descriptions{i}), "s");
+      sts = rmdir (descriptions{i}.dir, "s");
+      sts = rmdir (getarchdir (descriptions{i}), "s");
       descriptions(i) = [];
     endif
   endfor
@@ -282,10 +282,10 @@
   catch
     ## Something went wrong, delete tmpdirs.
     for i = 1:length (tmpdirs)
-      rmdir (tmpdirs{i}, "s");
+      sts = rmdir (tmpdirs{i}, "s");
     endfor
     for i = 1:length (descriptions)
-      rmdir (descriptions{i}.dir, "s");
+      sts = rmdir (descriptions{i}.dir, "s");
     endfor
     if (global_install)
       printf ("error: couldn't append to %s\n", global_list);
@@ -376,7 +376,7 @@
   if (! isfolder (inst_dir))
     [status, msg] = mkdir (inst_dir);
     if (status != 1)
-      rmdir (desc.dir, "s");
+      sts = rmdir (desc.dir, "s");
       error ("the 'inst' directory did not exist and could not be created: %s",
              msg);
     endif
@@ -450,7 +450,7 @@
         endif
         [status, output] = copyfile (archindependent, instdir);
         if (status != 1)
-          rmdir (desc.dir, "s");
+          sts = rmdir (desc.dir, "s");
           error ("Couldn't copy files from 'src' to 'inst': %s", output);
         endif
       endif
@@ -465,7 +465,7 @@
         endif
         [status, output] = copyfile (archdependent, archdir);
         if (status != 1)
-          rmdir (desc.dir, "s");
+          sts = rmdir (desc.dir, "s");
           error ("Couldn't copy files from 'src' to 'inst': %s", output);
         endif
       endif
@@ -517,7 +517,7 @@
   if (! dirempty (instdir))
     [status, output] = copyfile (fullfile (instdir, "*"), desc.dir);
     if (status != 1)
-      rmdir (desc.dir, "s");
+      sts = rmdir (desc.dir, "s");
       error ("couldn't copy files to the installation directory");
     endif
     if (isfolder (fullfile (desc.dir, getarch ()))
@@ -532,39 +532,39 @@
             if (! isfolder (octm3))
               [status, output] = mkdir (octm3);
               if (status != 1)
-                rmdir (desc.dir, "s");
+                sts = rmdir (desc.dir, "s");
                 error ("couldn't create installation directory %s : %s",
                        octm3, output);
               endif
             endif
             [status, output] = mkdir (octm2);
             if (status != 1)
-              rmdir (desc.dir, "s");
+              sts = rmdir (desc.dir, "s");
               error ("couldn't create installation directory %s : %s",
                      octm2, output);
             endif
           endif
           [status, output] = mkdir (octm1);
           if (status != 1)
-            rmdir (desc.dir, "s");
+            sts = rmdir (desc.dir, "s");
             error ("couldn't create installation directory %s : %s",
                    octm1, output);
           endif
         endif
         [status, output] = mkdir (octfiledir);
         if (status != 1)
-          rmdir (desc.dir, "s");
+          sts = rmdir (desc.dir, "s");
           error ("couldn't create installation directory %s : %s",
           octfiledir, output);
         endif
       endif
       [status, output] = movefile (fullfile (desc.dir, getarch (), "*"),
                                    octfiledir);
-      rmdir (fullfile (desc.dir, getarch ()), "s");
+      sts = rmdir (fullfile (desc.dir, getarch ()), "s");
 
       if (status != 1)
-        rmdir (desc.dir, "s");
-        rmdir (octfiledir, "s");
+        sts = rmdir (desc.dir, "s");
+        sts = rmdir (octfiledir, "s");
         error ("couldn't copy files to the installation directory");
       endif
     endif
@@ -575,8 +575,8 @@
   packinfo = fullfile (desc.dir, "packinfo");
   [status, msg] = mkdir (packinfo);
   if (status != 1)
-    rmdir (desc.dir, "s");
-    rmdir (octfiledir, "s");
+    sts = rmdir (desc.dir, "s");
+    sts = rmdir (octfiledir, "s");
     error ("couldn't create packinfo directory: %s", msg);
   endif
 
@@ -596,8 +596,8 @@
       write_index (desc, fullfile (packdir, "inst"),
                    fullfile (packinfo, "INDEX"), global_install);
     catch
-      rmdir (desc.dir, "s");
-      rmdir (octfiledir, "s");
+      sts = rmdir (desc.dir, "s");
+      sts = rmdir (octfiledir, "s");
       rethrow (lasterror ());
     end_try_catch
   endif
@@ -629,8 +629,8 @@
   else
     [status, output] = copyfile (filepath, packinfo);
     if (status != 1)
-      rmdir (desc.dir, "s");
-      rmdir (octfiledir, "s");
+      sts = rmdir (desc.dir, "s");
+      sts = rmdir (octfiledir, "s");
       error ("Couldn't copy %s file: %s", filename, output);
     endif
   endif
@@ -801,8 +801,8 @@
       cd (wd);
     catch
       cd (wd);
-      rmdir (desc.dir, "s");
-      rmdir (getarchdir (desc), "s");
+      sts = rmdir (desc.dir, "s");
+      sts = rmdir (getarchdir (desc), "s");
       rethrow (lasterror ());
     end_try_catch
   endif
--- a/scripts/pkg/private/uninstall.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/pkg/private/uninstall.m	Tue Jul 07 19:40:20 2020 -0400
@@ -32,8 +32,8 @@
                     global_list, global_install)
 
   ## Get the list of installed packages.
-  [local_packages, global_packages] = installed_packages(local_list,
-                                                         global_list);
+  [local_packages, global_packages] = installed_packages (local_list,
+                                                          global_list);
   if (global_install)
     installed_pkgs_lst = {local_packages{:}, global_packages{:}};
   else
@@ -122,6 +122,11 @@
         endif
       endif
       if (isfolder (desc.dir))
+        ## FIXME: If first call to rmdir fails, then error() will 
+        ##        stop further processing of getarchdir & archprefix.
+        ##        If this is, in fact, correct, then calls should
+        ##        just be shortened to rmdir (...) and let rmdir()
+        ##        report failure and reason for failure.
         [status, msg] = rmdir (desc.dir, "s");
         if (status != 1 && isfolder (desc.dir))
           error ("couldn't delete directory %s: %s", desc.dir, msg);
@@ -131,7 +136,7 @@
           error ("couldn't delete directory %s: %s", getarchdir (desc), msg);
         endif
         if (dirempty (desc.archprefix))
-          rmdir (desc.archprefix, "s");
+          sts = rmdir (desc.archprefix, "s");
         endif
       else
         warning ("directory %s previously lost", desc.dir);
@@ -140,8 +145,8 @@
 
     ## Write a new ~/.octave_packages.
     if (global_install)
-      if (length (remaining_packages) == 0)
-        unlink (global_list);
+      if (numel (remaining_packages) == 0)
+        [~] = unlink (global_list);
       else
         global_packages = save_order (remaining_packages);
         if (ispc)
@@ -152,8 +157,8 @@
         save (global_list, "global_packages");
       endif
     else
-      if (length (remaining_packages) == 0)
-        unlink (local_list);
+      if (numel (remaining_packages) == 0)
+        [~] = unlink (local_list);
       else
         local_packages = save_order (remaining_packages);
         if (ispc)
--- a/scripts/plot/appearance/axis.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/plot/appearance/axis.m	Tue Jul 07 19:40:20 2020 -0400
@@ -54,14 +54,20 @@
 ## The following options control the aspect ratio of the axes.
 ##
 ## @table @asis
+## @item @qcode{"equal"}
+## Force x-axis unit distance to equal y-axis (and z-axis) unit distance.
+##
 ## @item @qcode{"square"}
 ## Force a square axis aspect ratio.
 ##
-## @item @qcode{"equal"}
-## Force x-axis unit distance to equal y-axis (and z-axis) unit distance.
+## @item @nospell{@qcode{"vis3d"}}
+## Set aspect ratio modes (@qcode{"DataAspectRatio"},
+## @qcode{"PlotBoxAspectRatio"}) to @qcode{"manual"} for rotation without
+## stretching.
 ##
-## @item @qcode{"normal"}
-## Restore default aspect ratio.
+## @item  @qcode{"normal"}
+## @itemx @qcode{"fill"}
+## Restore default automatically computed aspect ratios.
 ## @end table
 ##
 ## @noindent
@@ -83,8 +89,6 @@
 ## @item @qcode{"image"}
 ## Equivalent to @qcode{"tight"} and @qcode{"equal"}.
 ##
-## @item @nospell{@qcode{"vis3d"}}
-## Set aspect ratio modes to @qcode{"manual"} for rotation without stretching.
 ## @end table
 ##
 ## @noindent
@@ -250,7 +254,7 @@
         ## Fix aspect ratio modes for rotation without stretching.
         set (ca, "dataaspectratiomode", "manual",
                  "plotboxaspectratiomode", "manual");
-      elseif (strcmpi (opt, "normal"))
+      elseif (strcmpi (opt, "normal") || strcmpi (opt, "fill"))
         ## Set plotboxaspectratio to something obtuse so that switching
         ## back to "auto" will force a re-calculation.
         set (ca, "plotboxaspectratio", [3 2 1]);
--- a/scripts/plot/appearance/daspect.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/plot/appearance/daspect.m	Tue Jul 07 19:40:20 2020 -0400
@@ -130,7 +130,7 @@
 %! x = 0:0.01:4;
 %! plot (x,cos(x), x, sin(x));
 %! axis square;
-%! set (gca, "activepositionproperty", "position");
+%! set (gca, "positionconstraint", "innerposition");
 %! daspect ([1 1 1]);
 %! title ("square plot box with axis limits [0, 4, -2, 2]");
 
@@ -139,7 +139,7 @@
 %! x = 0:0.01:4;
 %! plot (x,cos(x), x,sin(x));
 %! axis ([0 4 -1 1]);
-%! set (gca, "activepositionproperty", "position");
+%! set (gca, "positionconstraint", "innerposition");
 %! daspect ([2 1 1]);
 %! title ("square plot box with axis limits [0, 4, -1, 1]");
 
--- a/scripts/plot/appearance/legend.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/plot/appearance/legend.m	Tue Jul 07 19:40:20 2020 -0400
@@ -131,7 +131,11 @@
 
   ## Use the old legend code to handle gnuplot toolkit
   if (strcmp (graphics_toolkit (), "gnuplot"))
-    [hleg, hleg_obj, hplot, labels] = __gnuplot_legend__ (varargin{:});
+    if (nargout > 0)
+      [hleg, hleg_obj, hplot, labels] = __gnuplot_legend__ (varargin{:});
+    else
+      __gnuplot_legend__ (varargin{:});
+    endif
     return;
   endif
 
--- a/scripts/plot/appearance/private/__gnuplot_legend__.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/plot/appearance/private/__gnuplot_legend__.m	Tue Jul 07 19:40:20 2020 -0400
@@ -622,7 +622,7 @@
                           "box", box,
                           "xtick", [], "ytick", [],
                           "xlim", [0, 1], "ylim", [0, 1],
-                          "activepositionproperty", "position");
+                          "positionconstraint", "innerposition");
           setappdata (hlegend, "__axes_handle__", ud);
           try
             addproperty ("__legend_handle__", ud(1), "handle", hlegend);
@@ -1062,7 +1062,7 @@
                 ## This violates strict Matlab compatibility, but reliably
                 ## renders an aesthetic result.
                 set (ca(i), "position",  unmodified_axes_position,
-                            "activepositionproperty", "outerposition");
+                            "positionconstraint", "outerposition");
               else
                 ## numel (ca) > 1 for axes overlays (like plotyy)
                 set (ca(i), "position", new_pos);
@@ -1181,8 +1181,8 @@
       outerposition = get (hleg, "unmodified_axes_outerposition");
       units = get (hax, "units");
       set (hax, "units", "points");
-      switch (get (hax, "activepositionproperty"))
-        case "position"
+      switch (get (hax, "positionconstraint"))
+        case "innerposition"
           set (hax, "outerposition", outerposition, "position", position);
         case "outerposition"
           set (hax, "position", position, "outerposition", outerposition);
--- a/scripts/plot/draw/colorbar.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/plot/draw/colorbar.m	Tue Jul 07 19:40:20 2020 -0400
@@ -219,7 +219,7 @@
     set (hax, "units", orig_props.units,
               "position", orig_props.position,
               "outerposition", orig_props.outerposition,
-              "activepositionproperty", orig_props.activepositionproperty);
+              "positionconstraint", orig_props.positionconstraint);
     set (hax, "units", units);
   endif
 
@@ -251,7 +251,7 @@
     ## FIXME: Matlab does not require the "position" property to be active.
     ##        Is there a way to determine the plotbox position for the
     ##        gnuplot graphics toolkit when the outerposition is active?
-    set (hax, "activepositionproperty", "position");
+    set (hax, "positionconstraint", "innerposition");
     props = get (hax);
     props.__axes_handle__ = hax;
     position = props.position;
@@ -276,7 +276,7 @@
     ## Create colorbar axes if necessary
     if (new_colorbar)
       hcb = axes ("parent", hpar, "tag", "colorbar",
-                  "activepositionproperty", "position", "position", cbpos,
+                  "positionconstraint", "innerposition", "position", cbpos,
                   "colormap", cmap,
                   "box", "on", "xdir", "normal", "ydir", "normal");
 
@@ -438,7 +438,7 @@
     set (hax, "units", orig_props.units,
               "position", orig_props.position,
               "outerposition", orig_props.outerposition,
-              "activepositionproperty", orig_props.activepositionproperty);
+              "positionconstraint", orig_props.positionconstraint);
     set (hax, "units", units);
 
     ## Nullify colorbar link (can't delete properties yet)
@@ -534,7 +534,7 @@
       scale = [scale, 1];
     endif
     if (strcmp (get (cf, "__graphics_toolkit__"), "gnuplot")
-        && strcmp (props.activepositionproperty, "outerposition"))
+        && strcmp (props.positionconstraint, "outerposition"))
       props.outerposition = props.outerposition .* [1, 1, scale];
       off = 0.5 * (props.outerposition (3:4) - __actual_axis_position__ (props)(3:4));
     else
@@ -884,7 +884,7 @@
 %! shading interp;
 %! axis ("tight", "square");
 %! colorbar ();
-#%! axes ("color","none","box","on","activepositionproperty","position");
+#%! axes ("color", "none", "box", "on", "positionconstraint", "innerposition");
 
 %!demo
 %! clf;
--- a/scripts/plot/draw/hist.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/plot/draw/hist.m	Tue Jul 07 19:40:20 2020 -0400
@@ -115,10 +115,11 @@
   ## Process possible second argument
   if (nargin == 1 || ischar (varargin{iarg}))
     n = 10;
-    ## Use range type to preserve accuracy
+    ## Use integer range values and perform division last to preserve
+    ## accuracy.
     if (min_val != max_val)
-      x = (0.5:n) * (1/n);
-      x = (max_val - min_val) * x + min_val;
+      x = 1:2:2*n;
+      x = ((max_val - min_val) * x + 2*n*min_val) / (2*n);
     else
       x = (-floor ((n-1)/2):ceil ((n-1)/2)) + min_val;
     endif
@@ -140,10 +141,11 @@
       if (n <= 0)
         error ("hist: number of bins NBINS must be positive");
       endif
-      ## Use range type to preserve accuracy
+      ## Use integer range values and perform division last to preserve
+      ## accuracy.
       if (min_val != max_val)
-        x = (0.5:n) * (1/n);
-        x = (max_val - min_val) * x + min_val;
+        x = 1:2:2*n;
+        x = ((max_val - min_val) * x + 2*n*min_val) / (2*n);
       else
         x = (-floor ((n-1)/2):ceil ((n-1)/2)) + min_val;
       endif
--- a/scripts/plot/draw/lightangle.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/plot/draw/lightangle.m	Tue Jul 07 19:40:20 2020 -0400
@@ -122,7 +122,7 @@
     pos -= get (hax, "CameraTarget");
   endif
 
-  pos = sph2cart (az, el, norm (pos));
+  [pos(1), pos(2), pos(3)] = sph2cart (az, el, norm (pos));
 
   if (strcmp (get (hl, "Style"), "local"))
     pos += get (hax, "CameraTarget");
--- a/scripts/plot/draw/module.mk	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/plot/draw/module.mk	Tue Jul 07 19:40:20 2020 -0400
@@ -9,6 +9,7 @@
   %reldir%/private/__contour__.m \
   %reldir%/private/__errplot__.m \
   %reldir%/private/__ezplot__.m \
+  %reldir%/private/__gnuplot_scatter__.m \
   %reldir%/private/__interp_cube__.m \
   %reldir%/private/__line__.m \
   %reldir%/private/__marching_cube__.m \
@@ -98,6 +99,7 @@
   %reldir%/stream2.m \
   %reldir%/stream3.m \
   %reldir%/streamline.m \
+  %reldir%/streamribbon.m \
   %reldir%/streamtube.m \
   %reldir%/surf.m \
   %reldir%/surface.m \
--- a/scripts/plot/draw/ostreamtube.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/plot/draw/ostreamtube.m	Tue Jul 07 19:40:20 2020 -0400
@@ -71,7 +71,7 @@
 ## @end group
 ## @end example
 ##
-## @seealso{stream3, streamline, streamtube}
+## @seealso{stream3, streamline, streamribbon, streamtube}
 ## @end deftypefn
 
 ## References:
@@ -161,7 +161,7 @@
   for i = 1 : length (xyz)
     sl = xyz{i};
     if (! isempty (sl))
-      slx = sl(:, 1); sly = sl(:, 2); slz = sl(:, 3);
+      slx = sl(:,1); sly = sl(:,2); slz = sl(:,3);
       mxx(j) = max (slx); mnx(j) = min (slx);
       mxy(j) = max (sly); mny(j) = min (sly);
       mxz(j) = max (slz); mnz(j) = min (slz);
@@ -179,12 +179,12 @@
     num_vertices = rows (sl);
     if (! isempty (sl) && num_vertices > 2)
 
-      usl = interp3 (x, y, z, u, sl(:, 1), sl(:, 2), sl(:, 3));
-      vsl = interp3 (x, y, z, v, sl(:, 1), sl(:, 2), sl(:, 3));
-      wsl = interp3 (x, y, z, w, sl(:, 1), sl(:, 2), sl(:, 3));
+      usl = interp3 (x, y, z, u, sl(:,1), sl(:,2), sl(:,3));
+      vsl = interp3 (x, y, z, v, sl(:,1), sl(:,2), sl(:,3));
+      wsl = interp3 (x, y, z, w, sl(:,1), sl(:,2), sl(:,3));
       vv = sqrt (usl.*usl + vsl.*vsl + wsl.*wsl);
 
-      div_sl = interp3 (x, y, z, div, sl(:, 1), sl(:, 2), sl(:, 3));
+      div_sl = interp3 (x, y, z, div, sl(:,1), sl(:,2), sl(:,3));
       is_singular_div = find (isnan (div_sl), 1, "first");
 
       if (! isempty (is_singular_div))
@@ -211,61 +211,65 @@
   cp = cos (phi);
   sp = sin (phi);
 
-  X0 = sl(1, :);
-  X1 = sl(2, :);
-
-  ## 1st rotation axis
+  ## 1st streamline segment
+  X0 = sl(1,:);
+  X1 = sl(2,:);
   R = X1 - X0;
   RE = R / norm (R);
 
-  ## Initial radius
-  vold = vv(1);
-  vact = vv(2);
-  ract = rstart * exp (0.5 * div_sl(2) * norm (R) / vact) * sqrt (vold / vact);
-  vold = vact;
+  ## Guide point and its rotation to create a segment
+  KE = get_normal1 (RE);
+  K = rstart * KE;
+  XS0 = rotation (K, RE, cp, sp) + repmat (X0.', 1, num_circum);
+
+  ## End of first segment
+  ract = rstart * exp (0.5 * div_sl(2) * norm (R) / vv(2)) * ...
+                  sqrt (vv(1) / vv(2));
   rold = ract;
-
-  ## Guide point and its rotation to create a segment
-  N = get_normal1 (R);
-  K = ract * N;
+  K = ract * KE;
   XS = rotation (K, RE, cp, sp) + repmat (X1.', 1, num_circum);
 
-  px = zeros (num_circum, max_vertices - 1);
-  py = zeros (num_circum, max_vertices - 1);
-  pz = zeros (num_circum, max_vertices - 1);
-  pc = zeros (num_circum, max_vertices - 1);
+  px = zeros (num_circum, max_vertices);
+  py = zeros (num_circum, max_vertices);
+  pz = zeros (num_circum, max_vertices);
+  pc = zeros (num_circum, max_vertices);
 
-  px(:, 1) = XS(1, :).';
-  py(:, 1) = XS(2, :).';
-  pz(:, 1) = XS(3, :).';
-  pc(:, 1) = vact * ones (num_circum, 1);
+  px(:,1) = XS0(1,:).';
+  py(:,1) = XS0(2,:).';
+  pz(:,1) = XS0(3,:).';
+  pc(:,1) = vv(1) * ones (num_circum, 1);
+
+  px(:,2) = XS(1,:).';
+  py(:,2) = XS(2,:).';
+  pz(:,2) = XS(3,:).';
+  pc(:,2) = vv(2) * ones (num_circum, 1);
 
   for i = 3 : max_vertices
 
-    KK = K;
+    ## Next streamline segment
     X0 = X1;
-    X1 = sl(i, :);
+    X1 = sl(i,:);
     R = X1 - X0;
     RE = R / norm (R);
 
     ## Tube radius
-    vact = vv(i);
-    ract = rold * exp (0.5 * div_sl(i) * norm (R) / vact) * sqrt (vold / vact);
-    vold = vact;
+    ract = rold * exp (0.5 * div_sl(i) * norm (R) / vv(i)) * ...
+                  sqrt (vv(i-1) / vv(i));
     rold = ract;
 
-    ## Project KK onto RE and get the difference in order to calculate the next
-    ## guiding point
-    Kp = KK - RE * dot (KK, RE);
-    K = ract * Kp / norm (Kp);
+    ## Project KE onto RE and get the difference in order to transport
+    ## the normal vector KE along the vertex array
+    Kp = KE - RE * dot (KE, RE);
+    KE = Kp / norm (Kp);
+    K = ract * KE;
 
     ## Rotate around RE and collect surface patches
     XS = rotation (K, RE, cp, sp) + repmat (X1.', 1, num_circum);
 
-    px(:, i - 1) = XS(1, :).';
-    py(:, i - 1) = XS(2, :).';
-    pz(:, i - 1) = XS(3, :).';
-    pc(:, i - 1) = vact * ones (num_circum, 1);
+    px(:,i) = XS(1,:).';
+    py(:,i) = XS(2,:).';
+    pz(:,i) = XS(3,:).';
+    pc(:,i) = vv(i) * ones (num_circum, 1);
 
   endfor
 
@@ -277,9 +281,9 @@
 function N = get_normal1 (X)
 
   if ((X(3) == 0) && (X(1) == -X(2)))
-    N = [- X(2) - X(3), X(1), X(1)];
+    N = [(- X(2) - X(3)), X(1), X(1)];
   else
-    N = [X(3), X(3), - X(1) - X(2)];
+    N = [X(3), X(3), (- X(1) - X(2))];
   endif
 
   N /= norm (N);
@@ -294,17 +298,17 @@
   uy = U(2);
   uz = U(3);
 
-  Y(1, :) = X(1) * (cp + ux * ux * (1 - cp)) + ...
-            X(2) * (ux * uy * (1 - cp) - uz * sp) + ...
-            X(3) * (ux * uz * (1 - cp) + uy * sp);
+  Y(1,:) = X(1) * (cp + ux * ux * (1 - cp)) + ...
+           X(2) * (ux * uy * (1 - cp) - uz * sp) + ...
+           X(3) * (ux * uz * (1 - cp) + uy * sp);
 
-  Y(2, :) = X(1) * (uy * ux * (1 - cp) + uz * sp) + ...
-            X(2) * (cp + uy * uy * (1 - cp)) + ...
-            X(3) * (uy * uz * (1 - cp) - ux * sp);
+  Y(2,:) = X(1) * (uy * ux * (1 - cp) + uz * sp) + ...
+           X(2) * (cp + uy * uy * (1 - cp)) + ...
+           X(3) * (uy * uz * (1 - cp) - ux * sp);
 
-  Y(3, :) = X(1) * (uz * ux * (1 - cp) - uy * sp) + ...
-            X(2) * (uz * uy * (1 - cp) + ux * sp) + ...
-            X(3) * (cp + uz * uz * (1 - cp));
+  Y(3,:) = X(1) * (uz * ux * (1 - cp) - uy * sp) + ...
+           X(2) * (uz * uy * (1 - cp) + ux * sp) + ...
+           X(3) * (cp + uz * uz * (1 - cp));
 
 endfunction
 
@@ -359,8 +363,8 @@
 %!error <invalid number of inputs> ostreamtube (1,2,3)
 %!error <invalid number of inputs> ostreamtube (1,2,3,4)
 %!error <invalid number of inputs> ostreamtube (1,2,3,4,5)
-%!error <invalid number of OPTIONS> ostreamtube (1,2,3,4,5,6, [1,2,3])
-%!error <SCALE must be a real scalar . 0> ostreamtube (1,2,3,4,5,6, [1i])
-%!error <SCALE must be a real scalar . 0> ostreamtube (1,2,3,4,5,6, [0])
-%!error <N must be greater than 2> ostreamtube (1,2,3,4,5,6, [1, 1i])
-%!error <N must be greater than 2> ostreamtube (1,2,3,4,5,6, [1, 2])
+%!error <invalid number of OPTIONS> ostreamtube (1,2,3,4,5,6,[1,2,3])
+%!error <SCALE must be a real scalar . 0> ostreamtube (1,2,3,4,5,6,[1i])
+%!error <SCALE must be a real scalar . 0> ostreamtube (1,2,3,4,5,6,[0])
+%!error <N must be greater than 2> ostreamtube (1,2,3,4,5,6,[1,1i])
+%!error <N must be greater than 2> ostreamtube (1,2,3,4,5,6,[1,2])
--- a/scripts/plot/draw/patch.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/plot/draw/patch.m	Tue Jul 07 19:40:20 2020 -0400
@@ -94,16 +94,6 @@
     print_usage ();
   endif
 
-  ## FIXME: ishold called this way is very slow.
-  if (! ishold (hax))
-    ## FIXME: This is a hack to get 'layer' command to work for 2D patches
-    ##        Alternative is much more complicated surgery in graphics.cc.
-    ##        of get_children_limits() for 'z' axis and 'patch' object type.
-    if (isempty (get (htmp, "zdata")))
-      set (hax, "zlim", [-1 1]);
-    endif
-  endif
-
   if (nargout > 0)
     h = htmp;
   endif
@@ -259,21 +249,21 @@
 
 %!demo
 %! clf;
-%! vertices = [0 0 0; 0.5 -0.5 0; 1 0 0; 1 1 0; 0 1 1; 1 0 1; 0 -1 0;]+3;
+%! vertices = [0 0 0; 0.5 -0.5 0; 1 0 0; 1 1 0; 0 1 1; 1 0 1; 0 -1 0] + 3;
 %! faces = [1 2 3 4 5 6 7];
 %! ha = axes ();
-%! hp = patch ('Vertices', vertices, 'Faces', faces, 'FaceColor', 'g');
-%! xlabel('x'), ylabel('y'), zlabel('z')
-%! view(3)
-%! set (ha, "XTick", [], "YTick", [], "ZTick", [])
-%! text (vertices(1,1), vertices(1,2), vertices(1,3), "1")
-%! text (vertices(2,1), vertices(2,2), vertices(2,3), "2")
-%! text (vertices(3,1), vertices(3,2), vertices(3,3), "3")
-%! text (vertices(4,1), vertices(4,2), vertices(4,3), "4")
-%! text (vertices(5,1), vertices(5,2), vertices(5,3), "5")
-%! text (vertices(6,1), vertices(6,2), vertices(6,3), "6")
-%! text (vertices(7,1), vertices(7,2), vertices(7,3), "7")
-%! title ("Non-coplanar patch")
+%! hp = patch ("Vertices", vertices, "Faces", faces, "FaceColor", "g");
+%! xlabel ("x"), ylabel ("y"), zlabel ("z");
+%! view(3);
+%! set (ha, "XTick", [], "YTick", [], "ZTick", []);
+%! text (vertices(1,1), vertices(1,2), vertices(1,3), "1");
+%! text (vertices(2,1), vertices(2,2), vertices(2,3), "2");
+%! text (vertices(3,1), vertices(3,2), vertices(3,3), "3");
+%! text (vertices(4,1), vertices(4,2), vertices(4,3), "4");
+%! text (vertices(5,1), vertices(5,2), vertices(5,3), "5");
+%! text (vertices(6,1), vertices(6,2), vertices(6,3), "6");
+%! text (vertices(7,1), vertices(7,2), vertices(7,3), "7");
+%! title ("Non-coplanar patch");
 
 
 %!test
--- a/scripts/plot/draw/plotyy.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/plot/draw/plotyy.m	Tue Jul 07 19:40:20 2020 -0400
@@ -136,9 +136,9 @@
   if (strcmp (get (ax(1), "__autopos_tag__"), "subplot"))
     set (ax(2), "__autopos_tag__", "subplot");
   elseif (strcmp (graphics_toolkit (), "gnuplot"))
-    set (ax, "activepositionproperty", "position");
+    set (ax, "positionconstraint", "innerposition");
   else
-    set (ax, "activepositionproperty", "outerposition");
+    set (ax, "positionconstraint", "outerposition");
   endif
 
   ## Don't replace axis which has colororder property already modified
@@ -154,7 +154,7 @@
     set (ax(2), "ycolor", getcolor (h2));
   endif
 
-  if (strcmp (get(ax(1), "activepositionproperty"), "position"))
+  if (strcmp (get(ax(1), "positionconstraint"), "innerposition"))
     set (ax(2), "position", get (ax(1), "position"));
   else
     set (ax(2), {"outerposition", "looseinset"},
@@ -234,8 +234,8 @@
       val = get (h, prop);
       if (strcmpi (prop, "position") || strcmpi (prop, "outerposition"))
         ## Save/restore "positionconstraint"
-        constraint = get (ax2, "activepositionproperty");
-        set (ax2, prop, get (h, prop), "activepositionproperty", constraint);
+        constraint = get (ax2, "positionconstraint");
+        set (ax2, prop, get (h, prop), "positionconstraint", constraint);
       else
         set (ax2, prop, get (h, prop));
       endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/draw/private/__gnuplot_scatter__.m	Tue Jul 07 19:40:20 2020 -0400
@@ -0,0 +1,345 @@
+########################################################################
+##
+## Copyright (C) 2020 The Octave Project Developers
+##
+## See the file COPYRIGHT.md in the top-level directory of this
+## distribution or <https://octave.org/copyright/>.
+##
+## This file is part of Octave.
+##
+## Octave is free software: you can 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
+## <https://www.gnu.org/licenses/>.
+##
+########################################################################
+
+## -*- texinfo -*-
+## @deftypefn {} {@var{hg} =} __gnuplot_scatter__ (@dots{})
+## Undocumented internal function.
+## @end deftypefn
+
+function hg = __gnuplot_scatter__ (hax, fcn, x, y, z, c, s, marker, filled, newargs)
+
+if (isempty (c))
+  c = __next_line_color__ ();
+endif
+
+## Must occur after __next_line_color__ in order to work correctly.
+hg = hggroup (hax, "__appdata__", struct ("__creator__", "__scatter__"));
+newargs = __add_datasource__ (fcn, hg, {"x", "y", "z", "c", "size"},
+                              newargs{:});
+
+addproperty ("xdata", hg, "data", x);
+addproperty ("ydata", hg, "data", y);
+addproperty ("zdata", hg, "data", z);
+if (ischar (c))
+  ## For single explicit color, cdata is unused
+  addproperty ("cdata", hg, "data", []);
+else
+  addproperty ("cdata", hg, "data", c);
+endif
+addproperty ("sizedata", hg, "data", s);
+addlistener (hg, "xdata", @update_data);
+addlistener (hg, "ydata", @update_data);
+addlistener (hg, "zdata", @update_data);
+addlistener (hg, "cdata", @update_data);
+addlistener (hg, "sizedata", @update_data);
+
+one_explicit_color = ischar (c) || isequal (size (c), [1, 3]);
+s = sqrt (s);  # size adjustment for visual compatibility w/Matlab
+
+if (numel (x) <= 100)
+
+  ## For small number of points, we'll construct an object for each point.
+
+  if (numel (s) == 1)
+    s = repmat (s, numel (x), 1);
+  endif
+
+  if (one_explicit_color)
+    for i = 1 : numel (x)
+      if (filled)
+        __go_patch__ (hg, "facecolor", "none", "edgecolor", "none",
+                      "xdata", x(i), "ydata", y(i), "zdata", z(i,:),
+                      "faces", 1, "vertices", [x(i), y(i), z(i,:)],
+                      "marker", marker,  "markersize", s(i),
+                      "markeredgecolor", c, "markerfacecolor", c,
+                      "linestyle", "none");
+      else
+        __go_patch__ (hg, "facecolor", "none", "edgecolor", "none",
+                      "xdata", x(i), "ydata", y(i), "zdata", z(i,:),
+                      "faces", 1, "vertices", [x(i), y(i), z(i,:)],
+                      "marker", marker,  "markersize", s(i),
+                      "markeredgecolor", c, "markerfacecolor", "none",
+                      "linestyle", "none");
+      endif
+    endfor
+  else
+    if (rows (c) == 1)
+      c = repmat (c, rows (x), 1);
+    endif
+    for i = 1 : numel (x)
+      if (filled)
+        __go_patch__ (hg, "facecolor", "none", "edgecolor", "none",
+                      "xdata", x(i), "ydata", y(i), "zdata", z(i,:),
+                      "faces", 1, "vertices", [x(i), y(i), z(i,:)],
+                      "marker", marker, "markersize", s(i),
+                      "markeredgecolor", "none",
+                      "markerfacecolor", "flat",
+                      "cdata", c(i,:), "facevertexcdata", c(i,:),
+                      "linestyle", "none");
+      else
+        __go_patch__ (hg, "facecolor", "none", "edgecolor", "none",
+                      "xdata", x(i), "ydata", y(i), "zdata", z(i,:),
+                      "faces", 1, "vertices", [x(i), y(i), z(i,:)],
+                      "marker", marker, "markersize", s(i),
+                      "markeredgecolor", "flat",
+                      "markerfacecolor", "none",
+                      "cdata", c(i,:), "facevertexcdata", c(i,:),
+                      "linestyle", "none");
+      endif
+    endfor
+  endif
+
+else
+
+  ## For larger numbers of points, we use one single object.
+  vert = [x, y, z];
+  render_size_color (hg, vert, s, c, marker, filled, true);
+
+endif
+
+if (! ischar (c) && rows (c) > 1)
+  ax = get (hg, "parent");
+  clim = get (ax, "clim");
+  if (min (c(:)) < clim(1))
+    clim(1) = min (c(:));
+    set (ax, "clim", clim);
+  endif
+  if (max (c(:)) > clim(2))
+    set (ax, "clim", [clim(1), max(c(:))]);
+  endif
+endif
+
+addproperty ("linewidth", hg, "patchlinewidth", 0.5);
+addproperty ("marker", hg, "patchmarker", marker);
+if (filled)
+  addproperty ("markeredgecolor", hg, "patchmarkeredgecolor", "none");
+  if (one_explicit_color)
+    addproperty ("markerfacecolor", hg, "patchmarkerfacecolor", c);
+  else
+    addproperty ("markerfacecolor", hg, "patchmarkerfacecolor", "flat");
+  endif
+else
+  addproperty ("markerfacecolor", hg, "patchmarkerfacecolor", "none");
+  if (one_explicit_color)
+    addproperty ("markeredgecolor", hg, "patchmarkeredgecolor", c);
+  else
+    addproperty ("markeredgecolor", hg, "patchmarkeredgecolor", "flat");
+  endif
+endif
+addlistener (hg, "linewidth", @update_props);
+addlistener (hg, "marker", @update_props);
+addlistener (hg, "markerfacecolor", @update_props);
+addlistener (hg, "markeredgecolor", @update_props);
+
+## Matlab property, although Octave does not implement it.
+addproperty ("hittestarea", hg, "radio", "on|{off}", "off");
+
+if (! isempty (newargs))
+  set (hg, newargs{:});
+endif
+
+endfunction
+
+function render_size_color (hg, vert, s, c, marker, filled, isflat)
+
+  if (isempty (c))
+    c = __next_line_color__ ();
+  endif
+
+  if (isscalar (s))
+    x = vert(:,1);
+    y = vert(:,2);
+    z = vert(:,3:end);
+    toolkit = get (ancestor (hg, "figure"), "__graphics_toolkit__");
+    ## Does gnuplot only support triangles with different vertex colors ?
+    ## FIXME: Verify gnuplot can only support one color.  If RGB triplets
+    ##        can be assigned to each vertex, then fix __gnuplot_draw_axes__.m
+    gnuplot_hack = (numel (x) > 1 && columns (c) == 3
+                    && strcmp (toolkit, "gnuplot"));
+    if (ischar (c) || ! isflat || gnuplot_hack)
+      if (filled)
+        ## "facecolor" and "edgecolor" must be set before any other properties
+        ## to skip co-planarity check (see bug #55751).
+        __go_patch__ (hg, "facecolor", "none", "edgecolor", "none",
+                          "xdata", x, "ydata", y, "zdata", z,
+                          "faces", 1:numel (x), "vertices", vert,
+                          "marker", marker,
+                          "markeredgecolor", "none",
+                          "markerfacecolor", c(1,:),
+                          "markersize", s, "linestyle", "none");
+      else
+        __go_patch__ (hg, "facecolor", "none", "edgecolor", "none",
+                          "xdata", x, "ydata", y, "zdata", z,
+                          "faces", 1:numel (x), "vertices", vert,
+                          "marker", marker,
+                          "markeredgecolor", c(1,:),
+                          "markerfacecolor", "none",
+                          "markersize", s, "linestyle", "none");
+      endif
+    else
+      if (filled)
+        __go_patch__ (hg, "facecolor", "none", "edgecolor", "none",
+                          "xdata", x, "ydata", y, "zdata", z,
+                          "faces", 1:numel (x), "vertices", vert,
+                          "marker", marker, "markersize", s,
+                          "markeredgecolor", "none",
+                          "markerfacecolor", "flat",
+                          "cdata", c, "facevertexcdata", c,
+                          "linestyle", "none");
+      else
+        __go_patch__ (hg, "facecolor", "none", "edgecolor", "none",
+                          "xdata", x, "ydata", y, "zdata", z,
+                          "faces", 1:numel (x), "vertices", vert,
+                          "marker", marker, "markersize", s,
+                          "markeredgecolor", "flat",
+                          "markerfacecolor", "none",
+                          "cdata", c, "facevertexcdata", c,
+                          "linestyle", "none");
+      endif
+    endif
+  else
+    ## Round size to one decimal place.
+    [ss, ~, s_to_ss] = unique (ceil (s*10) / 10);
+    for i = 1:rows (ss)
+      idx = (i == s_to_ss);
+      render_size_color (hg, vert(idx,:), ss(i), c,
+                             marker, filled, isflat);
+    endfor
+  endif
+
+endfunction
+
+function update_props (h, d)
+
+  lw = get (h, "linewidth");
+  m  = get (h, "marker");
+  fc = get (h, "markerfacecolor");
+  ec = get (h, "markeredgecolor");
+  kids = get (h, "children");
+
+  set (kids, "linewidth", lw, "marker", m,
+             "markerfacecolor", fc, "markeredgecolor", ec);
+
+endfunction
+
+## FIXME: This callback routine doesn't handle the case where N > 100.
+function update_data (h, d)
+
+  x = get (h, "xdata");
+  y = get (h, "ydata");
+  z = get (h, "zdata");
+  if (numel (x) > 100)
+    error ("scatter: cannot update data with more than 100 points.  Call scatter (x, y, ...) with new data instead.");
+  endif
+  c = get (h, "cdata");
+  one_explicit_color = ischar (c) || isequal (size (c), [1, 3]);
+  if (! one_explicit_color)
+    if (rows (c) == 1)
+      c = repmat (c, numel (x), 1);
+    endif
+  endif
+  filled = ! strcmp (get (h, "markerfacecolor"), "none");
+  s = get (h, "sizedata");
+  ## Size adjustment for visual compatibility with Matlab.
+  s = sqrt (s);
+  if (numel (s) == 1)
+    s = repmat (s, numel (x), 1);
+  endif
+  hlist = get (h, "children");
+
+  if (one_explicit_color)
+    if (filled)
+      if (isempty (z))
+        for i = 1 : length (hlist)
+          set (hlist(i), "vertices", [x(i), y(i)],
+                         "markersize", s(i),
+                         "markeredgecolor", c, "markerfacecolor", c);
+
+        endfor
+      else
+        for i = 1 : length (hlist)
+          set (hlist(i), "vertices", [x(i), y(i), z(i)],
+                         "markersize", s(i),
+                         "markeredgecolor", c, "markerfacecolor", c);
+        endfor
+      endif
+    else
+      if (isempty (z))
+        for i = 1 : length (hlist)
+          set (hlist(i), "vertices", [x(i), y(i)],
+                         "markersize", s(i),
+                         "markeredgecolor", c, "markerfacecolor", "none");
+
+        endfor
+      else
+        for i = 1 : length (hlist)
+          set (hlist(i), "vertices", [x(i), y(i), z(i)],
+                         "markersize", s(i),
+                         "markeredgecolor", c, "markerfacecolor", "none");
+        endfor
+      endif
+    endif
+  else
+    if (filled)
+      if (isempty (z))
+        for i = 1 : length (hlist)
+          set (hlist(i), "vertices", [x(i), y(i)],
+                         "markersize", s(i),
+                         "markeredgecolor", "none", "markerfacecolor", "flat",
+                         "cdata", reshape (c(i,:),[1, size(c)(2:end)]),
+                         "facevertexcdata", c(i,:));
+        endfor
+      else
+        for i = 1 : length (hlist)
+          set (hlist(i), "vertices", [x(i), y(i), z(i)],
+                         "markersize", s(i),
+                         "markeredgecolor", "none", "markerfacecolor", "flat",
+                         "cdata", reshape (c(i,:),[1, size(c)(2:end)]),
+                         "facevertexcdata", c(i,:));
+        endfor
+      endif
+    else
+      if (isempty (z))
+        for i = 1 : length (hlist)
+          set (hlist(i), "vertices", [x(i), y(i)],
+                         "markersize", s(i),
+                         "markeredgecolor", "flat", "markerfacecolor", "none",
+                         "cdata", reshape (c(i,:),[1, size(c)(2:end)]),
+                         "facevertexcdata", c(i,:));
+        endfor
+      else
+        for i = 1 : length (hlist)
+          set (hlist(i), "vertices", [x(i), y(i), z(i)],
+                         "markersize", s(i),
+                         "markeredgecolor", "flat", "markerfacecolor", "none",
+                         "cdata", reshape (c(i,:),[1, size(c)(2:end)]),
+                         "facevertexcdata", c(i,:));
+        endfor
+      endif
+    endif
+  endif
+
+endfunction
+
--- a/scripts/plot/draw/private/__scatter__.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/plot/draw/private/__scatter__.m	Tue Jul 07 19:40:20 2020 -0400
@@ -24,13 +24,13 @@
 ########################################################################
 
 ## -*- texinfo -*-
-## @deftypefn {} {@var{hg} =} __scatter__ (@dots{})
+## @deftypefn {} {@var{hs} =} __scatter__ (@dots{})
 ## Undocumented internal function.
 ## @end deftypefn
 
-function hg = __scatter__ (varargin)
+function hs = __scatter__ (varargin)
 
-  hax = varargin{1};  # We don't do anything with this.  Could remove it.
+  hax = varargin{1};
   nd  = varargin{2};
   fcn = varargin{3};
   x   = varargin{4}(:);
@@ -108,7 +108,7 @@
   x(idx) = [];
   y(idx) = [];
   if (nd == 2)
-    z = zeros (length (x), 0);
+    z = zeros (numel (x), 0);
   endif
   if (numel (s) > 1)
     s(idx) = [];
@@ -169,311 +169,58 @@
     endif
   endwhile
 
-  if (isempty (c))
-    c = __next_line_color__ ();
-  endif
+  if (strcmp ("gnuplot", graphics_toolkit ()))
+    ## Legacy code using patch for gnuplot toolkit
+    hs = __gnuplot_scatter__ (hax, fcn, x, y, z, c, s, marker, filled, newargs);
 
-  ## Must occur after __next_line_color__ in order to work correctly.
-  hg = hggroup ("__appdata__", struct ("__creator__", "__scatter__"));
-  newargs = __add_datasource__ (fcn, hg, {"x", "y", "z", "c", "size"},
-                                newargs{:});
-
-  addproperty ("xdata", hg, "data", x);
-  addproperty ("ydata", hg, "data", y);
-  addproperty ("zdata", hg, "data", z);
-  if (ischar (c))
-    ## For single explicit color, cdata is unused
-    addproperty ("cdata", hg, "data", []);
   else
-    addproperty ("cdata", hg, "data", c);
-  endif
-  addproperty ("sizedata", hg, "data", s);
-  addlistener (hg, "xdata", @update_data);
-  addlistener (hg, "ydata", @update_data);
-  addlistener (hg, "zdata", @update_data);
-  addlistener (hg, "cdata", @update_data);
-  addlistener (hg, "sizedata", @update_data);
-
-  one_explicit_color = ischar (c) || isequal (size (c), [1, 3]);
-  s = sqrt (s);  # size adjustment for visual compatibility w/Matlab
-
-  if (numel (x) <= 100)
-
-    ## For small number of points, we'll construct an object for each point.
-
-    if (numel (s) == 1)
-      s = repmat (s, numel (x), 1);
+    ## Use OpenGL rendering for "qt" and "fltk" graphics toolkits
+    if (isempty (x))
+      c = x;
+    endif
+    if (ischar (c))
+      c = str2rgb (c);
+    endif
+    if (isempty (c))
+      cdata_args = {};
+    else
+      cdata_args = {"cdata", c};
+    endif
+    if (filled)
+      filled_args = {"markeredgecolor", "none", "markerfacecolor", "flat"};
+    else
+      filled_args = {};
     endif
 
-    if (one_explicit_color)
-      for i = 1 : numel (x)
-        if (filled)
-          __go_patch__ (hg, "facecolor", "none", "edgecolor", "none",
-                        "xdata", x(i), "ydata", y(i), "zdata", z(i,:),
-                        "faces", 1, "vertices", [x(i), y(i), z(i,:)],
-                        "marker", marker,  "markersize", s(i),
-                        "markeredgecolor", c, "markerfacecolor", c,
-                        "linestyle", "none");
-        else
-          __go_patch__ (hg, "facecolor", "none", "edgecolor", "none",
-                        "xdata", x(i), "ydata", y(i), "zdata", z(i,:),
-                        "faces", 1, "vertices", [x(i), y(i), z(i,:)],
-                        "marker", marker,  "markersize", s(i),
-                        "markeredgecolor", c, "markerfacecolor", "none",
-                        "linestyle", "none");
-        endif
-      endfor
-    else
-      if (rows (c) == 1)
-        c = repmat (c, rows (x), 1);
-      endif
-      for i = 1 : numel (x)
-        if (filled)
-          __go_patch__ (hg, "facecolor", "none", "edgecolor", "none",
-                        "xdata", x(i), "ydata", y(i), "zdata", z(i,:),
-                        "faces", 1, "vertices", [x(i), y(i), z(i,:)],
-                        "marker", marker, "markersize", s(i),
-                        "markeredgecolor", "none",
-                        "markerfacecolor", "flat",
-                        "cdata", c(i,:), "facevertexcdata", c(i,:),
-                        "linestyle", "none");
-        else
-          __go_patch__ (hg, "facecolor", "none", "edgecolor", "none",
-                        "xdata", x(i), "ydata", y(i), "zdata", z(i,:),
-                        "faces", 1, "vertices", [x(i), y(i), z(i,:)],
-                        "marker", marker, "markersize", s(i),
-                        "markeredgecolor", "flat",
-                        "markerfacecolor", "none",
-                        "cdata", c(i,:), "facevertexcdata", c(i,:),
-                        "linestyle", "none");
-        endif
-      endfor
-    endif
-
-  else
-
-    ## For larger numbers of points, we use one single object.
-    vert = [x, y, z];
-    render_size_color (hg, vert, s, c, marker, filled, true);
-
-  endif
-
-  if (! ischar (c) && rows (c) > 1)
-    ax = get (hg, "parent");
-    clim = get (ax, "clim");
-    if (min (c(:)) < clim(1))
-      clim(1) = min (c(:));
-      set (ax, "clim", clim);
-    endif
-    if (max (c(:)) > clim(2))
-      set (ax, "clim", [clim(1), max(c(:))]);
-    endif
-  endif
-
-  addproperty ("linewidth", hg, "patchlinewidth", 0.5);
-  addproperty ("marker", hg, "patchmarker", marker);
-  if (filled)
-    addproperty ("markeredgecolor", hg, "patchmarkeredgecolor", "none");
-    if (one_explicit_color)
-      addproperty ("markerfacecolor", hg, "patchmarkerfacecolor", c);
-    else
-      addproperty ("markerfacecolor", hg, "patchmarkerfacecolor", "flat");
-    endif
-  else
-    addproperty ("markerfacecolor", hg, "patchmarkerfacecolor", "none");
-    if (one_explicit_color)
-      addproperty ("markeredgecolor", hg, "patchmarkeredgecolor", c);
-    else
-      addproperty ("markeredgecolor", hg, "patchmarkeredgecolor", "flat");
-    endif
-  endif
-  addlistener (hg, "linewidth", @update_props);
-  addlistener (hg, "marker", @update_props);
-  addlistener (hg, "markerfacecolor", @update_props);
-  addlistener (hg, "markeredgecolor", @update_props);
-
-  ## Matlab property, although Octave does not implement it.
-  addproperty ("hittestarea", hg, "radio", "on|{off}", "off");
-
-  if (! isempty (newargs))
-    set (hg, newargs{:});
+    hs = __go_scatter__ (hax, "xdata", x(:), "ydata", y(:), "zdata", z(:),
+                         cdata_args{:}, "sizedata", s(:), "marker", marker,
+                         filled_args{:}, newargs{:});
   endif
 
 endfunction
 
-function render_size_color (hg, vert, s, c, marker, filled, isflat)
+
+function rgb = str2rgb (str)
+  ## Convert a color code to the corresponding RGB values
+  rgb = [];
 
-  if (isscalar (s))
-    x = vert(:,1);
-    y = vert(:,2);
-    z = vert(:,3:end);
-    toolkit = get (ancestor (hg, "figure"), "__graphics_toolkit__");
-    ## Does gnuplot only support triangles with different vertex colors ?
-    ## FIXME: Verify gnuplot can only support one color.  If RGB triplets
-    ##        can be assigned to each vertex, then fix __gnuplot_draw_axes__.m
-    gnuplot_hack = (numel (x) > 1 && columns (c) == 3
-                    && strcmp (toolkit, "gnuplot"));
-    if (ischar (c) || ! isflat || gnuplot_hack)
-      if (filled)
-        ## "facecolor" and "edgecolor" must be set before any other properties
-        ## to skip co-planarity check (see bug #55751).
-        __go_patch__ (hg, "facecolor", "none", "edgecolor", "none",
-                          "xdata", x, "ydata", y, "zdata", z,
-                          "faces", 1:numel (x), "vertices", vert,
-                          "marker", marker,
-                          "markeredgecolor", "none",
-                          "markerfacecolor", c(1,:),
-                          "markersize", s, "linestyle", "none");
-      else
-        __go_patch__ (hg, "facecolor", "none", "edgecolor", "none",
-                          "xdata", x, "ydata", y, "zdata", z,
-                          "faces", 1:numel (x), "vertices", vert,
-                          "marker", marker,
-                          "markeredgecolor", c(1,:),
-                          "markerfacecolor", "none",
-                          "markersize", s, "linestyle", "none");
-      endif
-    else
-      if (filled)
-        __go_patch__ (hg, "facecolor", "none", "edgecolor", "none",
-                          "xdata", x, "ydata", y, "zdata", z,
-                          "faces", 1:numel (x), "vertices", vert,
-                          "marker", marker, "markersize", s,
-                          "markeredgecolor", "none",
-                          "markerfacecolor", "flat",
-                          "cdata", c, "facevertexcdata", c,
-                          "linestyle", "none");
-      else
-        __go_patch__ (hg, "facecolor", "none", "edgecolor", "none",
-                          "xdata", x, "ydata", y, "zdata", z,
-                          "faces", 1:numel (x), "vertices", vert,
-                          "marker", marker, "markersize", s,
-                          "markeredgecolor", "flat",
-                          "markerfacecolor", "none",
-                          "cdata", c, "facevertexcdata", c,
-                          "linestyle", "none");
-      endif
-    endif
-  else
-    ## Round size to one decimal place.
-    [ss, ~, s_to_ss] = unique (ceil (s*10) / 10);
-    for i = 1:rows (ss)
-      idx = (i == s_to_ss);
-      render_size_color (hg, vert(idx,:), ss(i), c,
-                             marker, filled, isflat);
-    endfor
-  endif
-
-endfunction
-
-function update_props (h, d)
-
-  lw = get (h, "linewidth");
-  m  = get (h, "marker");
-  fc = get (h, "markerfacecolor");
-  ec = get (h, "markeredgecolor");
-  kids = get (h, "children");
-
-  set (kids, "linewidth", lw, "marker", m,
-             "markerfacecolor", fc, "markeredgecolor", ec);
+  switch (str)
+    case 'b'
+      rgb = [0, 0, 1];
+    case 'k'
+      rgb = [0, 0, 0];
+    case 'r'
+      rgb = [1, 0, 0];
+    case 'g'
+      rgb = [0, 1, 0];
+    case 'y'
+      rgb = [1, 1, 0];
+    case 'm'
+      rgb = [1, 0, 1];
+    case 'c'
+      rgb = [0, 1, 1];
+    case 'w'
+      rgb = [1, 1, 1];
+endswitch
 
 endfunction
-
-## FIXME: This callback routine doesn't handle the case where N > 100.
-function update_data (h, d)
-
-  x = get (h, "xdata");
-  y = get (h, "ydata");
-  z = get (h, "zdata");
-  if (numel (x) > 100)
-    error ("scatter: cannot update data with more than 100 points.  Call scatter (x, y, ...) with new data instead.");
-  endif
-  c = get (h, "cdata");
-  one_explicit_color = ischar (c) || isequal (size (c), [1, 3]);
-  if (! one_explicit_color)
-    if (rows (c) == 1)
-      c = repmat (c, numel (x), 1);
-    endif
-  endif
-  filled = ! strcmp (get (h, "markerfacecolor"), "none");
-  s = get (h, "sizedata");
-  ## Size adjustment for visual compatibility with Matlab.
-  s = sqrt (s);
-  if (numel (s) == 1)
-    s = repmat (s, numel (x), 1);
-  endif
-  hlist = get (h, "children");
-
-  if (one_explicit_color)
-    if (filled)
-      if (isempty (z))
-        for i = 1 : length (hlist)
-          set (hlist(i), "vertices", [x(i), y(i)],
-                         "markersize", s(i),
-                         "markeredgecolor", c, "markerfacecolor", c);
-
-        endfor
-      else
-        for i = 1 : length (hlist)
-          set (hlist(i), "vertices", [x(i), y(i), z(i)],
-                         "markersize", s(i),
-                         "markeredgecolor", c, "markerfacecolor", c);
-        endfor
-      endif
-    else
-      if (isempty (z))
-        for i = 1 : length (hlist)
-          set (hlist(i), "vertices", [x(i), y(i)],
-                         "markersize", s(i),
-                         "markeredgecolor", c, "markerfacecolor", "none");
-
-        endfor
-      else
-        for i = 1 : length (hlist)
-          set (hlist(i), "vertices", [x(i), y(i), z(i)],
-                         "markersize", s(i),
-                         "markeredgecolor", c, "markerfacecolor", "none");
-        endfor
-      endif
-    endif
-  else
-    if (filled)
-      if (isempty (z))
-        for i = 1 : length (hlist)
-          set (hlist(i), "vertices", [x(i), y(i)],
-                         "markersize", s(i),
-                         "markeredgecolor", "none", "markerfacecolor", "flat",
-                         "cdata", reshape (c(i,:),[1, size(c)(2:end)]),
-                         "facevertexcdata", c(i,:));
-        endfor
-      else
-        for i = 1 : length (hlist)
-          set (hlist(i), "vertices", [x(i), y(i), z(i)],
-                         "markersize", s(i),
-                         "markeredgecolor", "none", "markerfacecolor", "flat",
-                         "cdata", reshape (c(i,:),[1, size(c)(2:end)]),
-                         "facevertexcdata", c(i,:));
-        endfor
-      endif
-    else
-      if (isempty (z))
-        for i = 1 : length (hlist)
-          set (hlist(i), "vertices", [x(i), y(i)],
-                         "markersize", s(i),
-                         "markeredgecolor", "flat", "markerfacecolor", "none",
-                         "cdata", reshape (c(i,:),[1, size(c)(2:end)]),
-                         "facevertexcdata", c(i,:));
-        endfor
-      else
-        for i = 1 : length (hlist)
-          set (hlist(i), "vertices", [x(i), y(i), z(i)],
-                         "markersize", s(i),
-                         "markeredgecolor", "flat", "markerfacecolor", "none",
-                         "cdata", reshape (c(i,:),[1, size(c)(2:end)]),
-                         "facevertexcdata", c(i,:));
-        endfor
-      endif
-    endif
-  endif
-
-endfunction
--- a/scripts/plot/draw/scatter.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/plot/draw/scatter.m	Tue Jul 07 19:40:20 2020 -0400
@@ -72,6 +72,8 @@
 ## @end group
 ## @end example
 ##
+## Programming Note: The full list of properties is documented at
+## @ref{Scatter Properties}.
 ## @seealso{scatter3, patch, plot}
 ## @end deftypefn
 
@@ -219,3 +221,20 @@
 %!     title (str);
 %!   endfor
 %! endfor
+
+
+%!testif ; ! strcmp (graphics_toolkit (), "gnuplot")
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   hs = scatter ([], []);
+%!   assert (get (hs, "type"), "scatter");
+%!   assert (isempty (get (hs, "xdata")));
+%!   assert (isempty (get (hs, "ydata")));
+%!   assert (isempty (get (hs, "zdata")));
+%!   assert (get (hs, "cdata"), [0, 0.4470, 0.7410]);
+%!   assert (get (hs, "cdatamode"), "auto");
+%!   assert (get (hs, "sizedata"), 36);
+%!   assert (get (hs, "linewidth"), 0.5);
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
--- a/scripts/plot/draw/scatter3.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/plot/draw/scatter3.m	Tue Jul 07 19:40:20 2020 -0400
@@ -59,7 +59,7 @@
 ## If the first argument @var{hax} is an axes handle, then plot into this axes,
 ## rather than the current axes returned by @code{gca}.
 ##
-## The optional return value @var{h} is a graphics handle to the hggroup
+## The optional return value @var{h} is a graphics handle to the scatter
 ## object representing the points.
 ##
 ## @example
@@ -69,6 +69,8 @@
 ## @end group
 ## @end example
 ##
+## Programming Note: The full list of properties is documented at
+## @ref{Scatter Properties}.
 ## @seealso{scatter, patch, plot}
 ## @end deftypefn
 
--- a/scripts/plot/draw/semilogx.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/plot/draw/semilogx.m	Tue Jul 07 19:40:20 2020 -0400
@@ -104,12 +104,12 @@
 %!
 %! subplot (1,2,1);
 %!  semilogx (x, y);
-%!  set (gca, "xdir", "reverse", "activepositionproperty", "outerposition");
+%!  set (gca, "xdir", "reverse", "positionconstraint", "outerposition");
 %!  title ({"semilogx (x, y)", "xdir = reversed"});
 %!
 %! subplot (1,2,2);
 %!  semilogx (-x, y);
-%!  set (gca, "xdir", "reverse", "activepositionproperty", "outerposition");
+%!  set (gca, "xdir", "reverse", "positionconstraint", "outerposition");
 %!  title ({"semilogx (-x, y)", "xdir = reversed"});
 
 %!test
--- a/scripts/plot/draw/semilogy.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/plot/draw/semilogy.m	Tue Jul 07 19:40:20 2020 -0400
@@ -104,12 +104,12 @@
 %!
 %! subplot (2,1,1);
 %!  semilogy (x, y);
-%!  set (gca, "ydir", "reverse", "activepositionproperty", "outerposition");
+%!  set (gca, "ydir", "reverse", "positionconstraint", "outerposition");
 %!  title ({"semilogy (x, y)", "ydir = reversed"});
 %!
 %! subplot (2,1,2);
 %!  semilogy (x, -y);
-%!  set (gca, "ydir", "reverse", "activepositionproperty", "outerposition");
+%!  set (gca, "ydir", "reverse", "positionconstraint", "outerposition");
 %!  title ({"semilogy (x, -y)", "ydir = reversed"});
 
 %!test
--- a/scripts/plot/draw/stream3.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/plot/draw/stream3.m	Tue Jul 07 19:40:20 2020 -0400
@@ -58,7 +58,7 @@
 ## @end group
 ## @end example
 ##
-## @seealso{stream2, streamline, streamtube, ostreamtube}
+## @seealso{stream2, streamline, streamribbon, streamtube, ostreamtube}
 ## @end deftypefn
 
 ## References:
--- a/scripts/plot/draw/streamline.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/plot/draw/streamline.m	Tue Jul 07 19:40:20 2020 -0400
@@ -61,7 +61,7 @@
 ## @end group
 ## @end example
 ##
-## @seealso{stream2, stream3, streamtube, ostreamtube}
+## @seealso{stream2, stream3, streamribbon, streamtube, ostreamtube}
 ## @end deftypefn
 
 function h = streamline (varargin)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/draw/streamribbon.m	Tue Jul 07 19:40:20 2020 -0400
@@ -0,0 +1,444 @@
+########################################################################
+##
+## Copyright (C) 2020 The Octave Project Developers
+##
+## See the file COPYRIGHT.md in the top-level directory of this
+## distribution or <https://octave.org/copyright/>.
+##
+## This file is part of Octave.
+##
+## Octave is free software: you can 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
+## <https://www.gnu.org/licenses/>.
+##
+########################################################################
+
+## -*- texinfo -*-
+## @deftypefn  {} {} streamribbon (@var{x}, @var{y}, @var{z}, @var{u}, @var{v}, @var{w}, @var{sx}, @var{sy}, @var{sz})
+## @deftypefnx {} {} streamribbon (@var{u}, @var{v}, @var{w}, @var{sx}, @var{sy}, @var{sz})
+## @deftypefnx {} {} streamribbon (@var{xyz}, @var{x}, @var{y}, @var{z}, @var{anlr_spd}, @var{lin_spd})
+## @deftypefnx {} {} streamribbon (@var{xyz}, @var{anlr_spd}, @var{lin_spd})
+## @deftypefnx {} {} streamribbon (@var{xyz}, @var{anlr_rot})
+## @deftypefnx {} {} streamribbon (@dots{}, @var{width})
+## @deftypefnx {} {} streamribbon (@var{hax}, @dots{})
+## @deftypefnx {} {@var{h} =} streamribbon (@dots{})
+## Calculate and display streamribbons.
+##
+## The streamribbon is constructed by rotating a normal vector around a
+## streamline according to the angular rotation of the vector field.
+##
+## The vector field is given by @code{[@var{u}, @var{v}, @var{w}]} and is
+## defined over a rectangular grid given by @code{[@var{x}, @var{y}, @var{z}]}.
+## The streamribbons start at the seed points
+## @code{[@var{sx}, @var{sy}, @var{sz}]}.
+##
+## @code{streamribbon} can be called with a cell array that contains
+## pre-computed streamline data.  To do this, @var{xyz} must be created with
+## the @code{stream3} function.  @var{lin_spd} is the linear speed of the
+## vector field and can be calculated from @code{[@var{u}, @var{v}, @var{w}]}
+## by the square root of the sum of the squares.  The angular speed
+## @var{anlr_spd} is the projection of the angular velocity onto the velocity
+## of the normalized vector field and can be calculated with the @code{curl}
+## command.  This option is useful if you need to alter the integrator step
+## size or the maximum number of streamline vertices.
+##
+## Alternatively, ribbons can be created from an array of vertices @var{xyz} of
+## a path curve.  @var{anlr_rot} contains the angles of rotation around the
+## edges between adjacent vertices of the path curve.
+##
+## The input parameter @var{width} sets the width of the streamribbons.
+##
+## Streamribbons are colored according to the total angle of rotation along the
+## ribbon.
+##
+## If the first argument @var{hax} is an axes handle, then plot into this axes,
+## rather than the current axes returned by @code{gca}.
+##
+## The optional return value @var{h} is a graphics handle to the plot objects
+## created for each streamribbon.
+##
+## Example:
+##
+## @example
+## @group
+## [x, y, z] = meshgrid (0:0.2:4, -1:0.2:1, -1:0.2:1);
+## u = - x + 10;
+## v = 10 * z.*x;
+## w = - 10 * y.*x;
+## streamribbon (x, y, z, u, v, w, [0, 0], [0, 0.6], [0, 0]);
+## view (3);
+## @end group
+## @end example
+##
+## @seealso{streamline, stream3, streamtube, ostreamtube}
+##
+## @end deftypefn
+
+## References:
+##
+## @inproceedings{
+##    title = {Feature Detection from Vector Quantities in a Numerically Simulated Hypersonic Flow Field in Combination with Experimental Flow Visualization},
+##    author = {Pagendarm, Hans-Georg and Walter, Birgit},
+##    year = {1994},
+##    publisher = {IEEE Computer Society Press},
+##    booktitle = {Proceedings of the Conference on Visualization ’94},
+##    pages = {117–123},
+## }
+##
+## @article{
+##    title = {Efficient streamline, streamribbon, and streamtube constructions on unstructured grids},
+##    author = {Ueng, Shyh-Kuang and Sikorski, C. and Ma, Kwan-Liu},
+##    year = {1996},
+##    month = {June},
+##    publisher = {IEEE Transactions on Visualization and Computer Graphics},
+## }
+##
+## @inproceedings{
+##    title = {Visualization of 3-D vector fields - Variations on a stream},
+##    author = {Dave Darmofal and Robert Haimes},
+##    year = {1992}
+## }
+##
+## @techreport{
+##    title = {Parallel Transport Approach to Curve Framing},
+##    author = {Andrew J. Hanson and Hui Ma},
+##    year = {1995}
+## }
+##
+## @article{
+##    title = {There is More than One Way to Frame a Curve},
+##    author = {Bishop, Richard},
+##    year = {1975},
+##    month = {03},
+##    volume = {82},
+##    publisher = {The American Mathematical Monthly}
+## }
+
+function h = streamribbon (varargin)
+
+  [hax, varargin, nargin] = __plt_get_axis_arg__ ("streamribbon", varargin{:});
+
+  width = [];
+  xyz = [];
+  anlr_spd = [];
+  lin_spd = [];
+  anlr_rot = [];
+  switch (nargin)
+    case 0
+      print_usage ();
+    case 2
+      [xyz, anlr_rot] = varargin{:};
+    case 3
+      if (numel (varargin{3}) == 1)
+        [xyz, anlr_rot, width] = varargin{:};
+      else
+        [xyz, anlr_spd, lin_spd] = varargin{:};
+        [m, n, p] = size (anlr_spd);
+        [x, y, z] = meshgrid (1:n, 1:m, 1:p);
+      endif
+    case 4
+      [xyz, anlr_spd, lin_spd, width] = varargin{:};
+      [m, n, p] = size (anlr_spd);
+      [x, y, z] = meshgrid (1:n, 1:m, 1:p);
+    case 6
+      if (iscell (varargin{1}))
+        [xyz, x, y, z, anlr_spd, lin_spd] = varargin{:};
+      else
+        [u, v, w, spx, spy, spz] = varargin{:};
+        [m, n, p] = size (u);
+        [x, y, z] = meshgrid (1:n, 1:m, 1:p);
+      endif
+    case 7
+      if (iscell (varargin{1}))
+        [xyz, x, y, z, anlr_spd, lin_spd, width] = varargin{:};
+      else
+        [u, v, w, spx, spy, spz, width] = varargin{:};
+        [m, n, p] = size (u);
+        [x, y, z] = meshgrid (1:n, 1:m, 1:p);
+      endif
+    case 9
+      [x, y, z, u, v, w, spx, spy, spz] = varargin{:};
+    case 10
+      [x, y, z, u, v, w, spx, spy, spz, width] = varargin{:};
+    otherwise
+      error ("streamribbon: invalid number of inputs");
+  endswitch
+
+  if (isempty (xyz))
+    xyz = stream3 (x, y, z, u, v, w, spx, spy, spz);
+    anlr_spd = curl (x, y, z, u, v, w);
+    lin_spd = sqrt (u.*u + v.*v + w.*w);
+  endif
+
+  ## Derive scale factor from the bounding box diagonal
+  if (isempty (width))
+    mxx = mnx = mxy = mny = mxz = mnz = [];
+    j = 1;
+    for i = 1 : length (xyz)
+      sl = xyz{i};
+      if (! isempty (sl))
+        slx = sl(:,1); sly = sl(:,2); slz = sl(:,3);
+        mxx(j) = max (slx); mnx(j) = min (slx);
+        mxy(j) = max (sly); mny(j) = min (sly);
+        mxz(j) = max (slz); mnz(j) = min (slz);
+        j += 1;
+      end
+    endfor
+    dx = max (mxx) - min (mnx);
+    dy = max (mxy) - min (mny);
+    dz = max (mxz) - min (mnz);
+    width = sqrt (dx*dx + dy*dy + dz*dz) / 25;
+  elseif (! isreal (width) || width <= 0)
+    error ("streamribbon: WIDTH must be a real scalar > 0");
+  endif
+
+  if (! isempty (anlr_rot))
+    for i = 1 : length (xyz)
+      if (rows (anlr_rot{i}) != rows (xyz{i}))
+        error ("streamribbon: ANLR_ROT must have same length as XYZ");
+      endif
+    endfor
+  endif
+
+  if (isempty (hax))
+    hax = gca ();
+  else
+    hax = hax(1);
+  endif
+
+  ## Angular speed of a paddle wheel spinning around a streamline in a fluid
+  ## flow "V":
+  ## dtheta/dt = 0.5 * <curl(V), V/norm(V)>
+  ##
+  ## Integration along a streamline segment with the length "h" yields the
+  ## rotation angle:
+  ## theta = 0.25 * h * <curl(V), V(0)/norm(V(0))^2) + V(h)/norm(V(h))^2)>
+  ##
+  ## Alternative approach using the curl angular speed "c = curl()":
+  ## theta = 0.5 * h * (c(0)/norm(V(0)) + c(h)/norm(V(h)))
+  ##
+  ## Hints:
+  ## i. ) For integration use trapezoidal rule
+  ## ii.) "V" can be assumend to be piecewise linear and curl(V) to be
+  ##      piecewise constant because of the used linear interpolation
+
+  h = [];
+  for i = 1 : length (xyz)
+    sl = xyz{i};
+    num_vertices = rows (sl);
+    if (! isempty (sl) && num_vertices > 1)
+      if isempty (anlr_rot)
+        ## Plot from vector field
+        ## Interpolate onto streamline vertices
+        [lin_spd_sl, anlr_spd_sl, max_vertices] = ...
+                                  interp_sl (x, y, z, lin_spd, anlr_spd, sl);
+        if (max_vertices > 1)
+          ## Euclidean distance between two adjacent vertices
+          stepsize = vecnorm (diff (sl(1:max_vertices, :)), 2, 2);
+          ## Angular rotation around edges between two adjacent sl-vertices
+          ## Note: Potential "division by zero" is checked in interp_sl()
+          anlr_rot_sl = 0.5 * stepsize.*(anlr_spd_sl(1:max_vertices - 1)./ ...
+                                         lin_spd_sl(1:max_vertices - 1) + ...
+                                         anlr_spd_sl(2:max_vertices)./ ...
+                                         lin_spd_sl(2:max_vertices));
+
+          htmp = plotribbon (hax, sl, anlr_rot_sl, max_vertices, 0.5 * width);
+          h = [h; htmp];
+        endif
+      else
+          ## Plot from vertice array
+          anlr_rot_sl = anlr_rot{i};
+
+          htmp = plotribbon (hax, sl, anlr_rot_sl, num_vertices, 0.5 * width);
+          h = [h; htmp];
+      endif
+    endif
+  endfor
+
+endfunction
+
+function h = plotribbon (hax, sl, anlr_rot_sl, max_vertices, width2)
+
+  total_angle = cumsum (anlr_rot_sl);
+  total_angle = [0; total_angle];
+
+  ## 1st streamline segment
+  X0 = sl(1,:);
+  X1 = sl(2,:);
+  R = X1 - X0;
+  RE = R / norm (R);
+
+  ## Initial vector KE which is to be transported along the vertice array
+  KE = get_normal2 (RE);
+  XS10 = - width2 * KE + X0;
+  XS20 = width2 * KE + X0;
+
+  ## Apply angular rotation
+  cp = cos (anlr_rot_sl(1));
+  sp = sin (anlr_rot_sl(1));
+  KE = rotation (KE, RE, cp, sp).';
+
+  XS1 = - width2 * KE + X1;
+  XS2 = width2 * KE + X1;
+
+  px = zeros (2, max_vertices);
+  py = zeros (2, max_vertices);
+  pz = zeros (2, max_vertices);
+  pc = zeros (2, max_vertices);
+
+  px(:,1) = [XS10(1); XS20(1)];
+  py(:,1) = [XS10(2); XS20(2)];
+  pz(:,1) = [XS10(3); XS20(3)];
+  pc(:,1) = total_angle(1) * [1; 1];
+
+  px(:,2) = [XS1(1); XS2(1)];
+  py(:,2) = [XS1(2); XS2(2)];
+  pz(:,2) = [XS1(3); XS2(3)];
+  pc(:,2) = total_angle(2) * [1; 1];
+
+  for i = 3 : max_vertices
+
+    ## Next streamline segment
+    X0 = X1;
+    X1 = sl(i,:);
+    R = X1 - X0;
+    RE = R / norm (R);
+
+    ## Project KE onto RE and get the difference in order to transport
+    ## the normal vector KE along the vertex array
+    Kp = KE - RE * dot (KE, RE);
+    KE = Kp / norm (Kp);
+
+    ## Apply angular rotation to KE
+    cp = cos (anlr_rot_sl(i - 1));
+    sp = sin (anlr_rot_sl(i - 1));
+    KE = rotation (KE, RE, cp, sp).';
+
+    XS1 = - width2 * KE + X1;
+    XS2 = width2 * KE + X1;
+
+    px(:,i) = [XS1(1); XS2(1)];
+    py(:,i) = [XS1(2); XS2(2)];
+    pz(:,i) = [XS1(3); XS2(3)];
+    pc(:,i) = total_angle(i) * [1; 1];
+
+  endfor
+
+  h = surface (hax, px, py, pz, pc);
+
+endfunction
+
+## Interpolate speed and divergence onto the streamline vertices and
+## return the first chunck of valid samples until a singularity /
+## zero is hit or the streamline vertex array "sl" ends
+function [lin_spd_sl, anlr_spd_sl, max_vertices] = ...
+                               interp_sl (x, y, z, lin_spd, anlr_spd, sl)
+
+  anlr_spd_sl = interp3 (x, y, z, anlr_spd, sl(:,1), sl(:,2), sl(:,3));
+  lin_spd_sl = interp3 (x, y, z, lin_spd, sl(:,1), sl(:,2), sl(:,3));
+
+  is_singular_anlr_spd = find (isnan (anlr_spd_sl), 1, "first");
+  is_zero_lin_spd = find (lin_spd_sl == 0, 1, "first");
+
+  max_vertices = rows (sl);
+  if (! isempty (is_singular_anlr_spd))
+    max_vertices = min (max_vertices, is_singular_anlr_spd - 1);
+  endif
+  if (! isempty (is_zero_lin_spd))
+    max_vertices = min (max_vertices, is_zero_lin_spd - 1);
+  endif
+
+endfunction
+
+## N normal to X, so that N is in span ([0 0 1], X)
+## If not possible then span ([1 0 0], X)
+function N = get_normal2 (X)
+
+  if ((X(1) == 0) && (X(2) == 0))
+    A = [1, 0, 0];
+  else
+    A = [0, 0, 1];
+  endif
+
+  ## Project A onto X and get the difference
+  N = A - X * dot (A, X) / (norm (X)^2);
+  N /= norm (N);
+
+endfunction
+
+## Rotate X around U where |U| = 1
+## cp = cos (angle), sp = sin (angle)
+function Y = rotation (X, U, cp, sp)
+
+  ux = U(1);
+  uy = U(2);
+  uz = U(3);
+
+  Y(1,:) = X(1) * (cp + ux * ux * (1 - cp)) + ...
+           X(2) * (ux * uy * (1 - cp) - uz * sp) + ...
+           X(3) * (ux * uz * (1 - cp) + uy * sp);
+
+  Y(2,:) = X(1) * (uy * ux * (1 - cp) + uz * sp) + ...
+           X(2) * (cp + uy * uy * (1 - cp)) + ...
+           X(3) * (uy * uz * (1 - cp) - ux * sp);
+
+  Y(3,:) = X(1) * (uz * ux * (1 - cp) - uy * sp) + ...
+           X(2) * (uz * uy * (1 - cp) + ux * sp) + ...
+           X(3) * (cp + uz * uz * (1 - cp));
+
+endfunction
+
+%!demo
+%! clf;
+%! [x, y, z] = meshgrid (0:0.2:4, -1:0.2:1, -1:0.2:1);
+%! u = - x + 10;
+%! v = 10 * z.*x;
+%! w = - 10 * y.*x;
+%! sx = [0, 0];
+%! sy = [0, 0.6];
+%! sz = [0, 0];
+%! streamribbon (x, y, z, u, v, w, sx, sy, sz);
+%! hold on;
+%! quiver3 (x, y, z, u, v, w);
+%! colormap (jet);
+%! shading interp;
+%! camlight ("headlight");
+%! view (3);
+%! axis tight equal off;
+%! set (gca, "cameraviewanglemode", "manual");
+%! hcb = colorbar;
+%! title (hcb, "Angle");
+%! title ("Streamribbon");
+
+%!demo
+%! clf;
+%! t = (0:pi/50:2*pi).';
+%! xyz{1} = [cos(t), sin(t), 0*t];
+%! twist{1} = ones (numel (t), 1) * pi / (numel (t) - 1);
+%! streamribbon (xyz, twist, 0.5);
+%! colormap (jet);
+%! view (3);
+%! camlight ("headlight");
+%! axis tight equal off;
+%! title ("Moebius Strip");
+
+## Test input validation
+%!error streamribbon ()
+%!error <invalid number of inputs> streamribbon (1)
+%!error <invalid number of inputs> streamribbon (1,2,3,4,5)
+%!error <invalid number of inputs> streamribbon (1,2,3,4,5,6,7,8)
+%!error <invalid number of inputs> streamribbon (1,2,3,4,5,6,7,8,9,10,11)
+%!error <WIDTH must be a real scalar . 0> streamribbon (1,2,3,1i)
+%!error <WIDTH must be a real scalar . 0> streamribbon (1,2,3,0)
+%!error <WIDTH must be a real scalar . 0> streamribbon (1,2,3,-1)
+%!error <ANLR_ROT must have same length as XYZ> streamribbon ({[1,1,1;2,2,2]},{[1,1,1]})
--- a/scripts/plot/draw/streamtube.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/plot/draw/streamtube.m	Tue Jul 07 19:40:20 2020 -0400
@@ -66,7 +66,7 @@
 ## The optional return value @var{h} is a graphics handle to the plot objects
 ## created for each tube.
 ##
-## @seealso{stream3, streamline, ostreamtube}
+## @seealso{stream3, streamline, streamribbon, ostreamtube}
 ## @end deftypefn
 
 function h = streamtube (varargin)
@@ -169,7 +169,7 @@
   for i = 1 : length (xyz)
     sl = xyz{i};
     if (! isempty (sl))
-      slx = sl(:, 1); sly = sl(:, 2); slz = sl(:, 3);
+      slx = sl(:,1); sly = sl(:,2); slz = sl(:,3);
       mxx(j) = max (slx); mnx(j) = min (slx);
       mxy(j) = max (sly); mny(j) = min (sly);
       mxz(j) = max (slz); mnz(j) = min (slz);
@@ -226,10 +226,9 @@
   cp = cos (phi);
   sp = sin (phi);
 
-  X0 = sl(1, :);
-  X1 = sl(2, :);
-
-  ## 1st rotation axis
+  ## 1st streamline segment
+  X0 = sl(1,:);
+  X1 = sl(2,:);
   R = X1 - X0;
   RE = R / norm (R);
 
@@ -244,35 +243,34 @@
   py = zeros (num_circum, max_vertices);
   pz = zeros (num_circum, max_vertices);
 
-  px(:, 1) = XS0(1, :).';
-  py(:, 1) = XS0(2, :).';
-  pz(:, 1) = XS0(3, :).';
+  px(:,1) = XS0(1,:).';
+  py(:,1) = XS0(2,:).';
+  pz(:,1) = XS0(3,:).';
 
-  px(:, 2) = XS(1, :).';
-  py(:, 2) = XS(2, :).';
-  pz(:, 2) = XS(3, :).';
+  px(:,2) = XS(1,:).';
+  py(:,2) = XS(2,:).';
+  pz(:,2) = XS(3,:).';
 
   for i = 3 : max_vertices
 
-    KEold = KE;
+    ## Next streamline segment
     X0 = X1;
-
-    X1 = sl(i, :);
+    X1 = sl(i,:);
     R = X1 - X0;
     RE = R / norm (R);
 
-    ## Project KE onto RE and get the difference in order to calculate the next
-    ## guiding point
-    Kp = KEold - RE * dot (KEold, RE);
+    ## Project KE onto RE and get the difference in order to transport
+    ## the normal vector KE along the vertex array
+    Kp = KE - RE * dot (KE, RE);
     KE = Kp / norm (Kp);
     K = radius_sl(i) * KE;
 
     ## Rotate around RE and collect surface patches
     XS = rotation (K, RE, cp, sp) + repmat (X1.', 1, num_circum);
 
-    px(:, i) = XS(1, :).';
-    py(:, i) = XS(2, :).';
-    pz(:, i) = XS(3, :).';
+    px(:,i) = XS(1,:).';
+    py(:,i) = XS(2,:).';
+    pz(:,i) = XS(3,:).';
 
   endfor
 
@@ -285,7 +283,7 @@
 ## the streamline vertex array "sl" ends
 function [div_sl_crop, max_vertices] = interp_sl (x, y, z, div, sl)
 
-  div_sl = interp3 (x, y, z, div, sl(:, 1), sl(:, 2), sl(:, 3));
+  div_sl = interp3 (x, y, z, div, sl(:,1), sl(:,2), sl(:,3));
   is_nan = find (isnan (div_sl), 1, "first");
   is_inf = find (isinf (div_sl), 1, "first");
 
@@ -305,9 +303,9 @@
 function N = get_normal1 (X)
 
   if ((X(3) == 0) && (X(1) == -X(2)))
-    N = [- X(2) - X(3), X(1), X(1)];
+    N = [(- X(2) - X(3)), X(1), X(1)];
   else
-    N = [X(3), X(3), - X(1) - X(2)];
+    N = [X(3), X(3), (- X(1) - X(2))];
   endif
 
   N /= norm (N);
@@ -322,17 +320,17 @@
   uy = U(2);
   uz = U(3);
 
-  Y(1, :) = X(1) * (cp + ux * ux * (1 - cp)) + ...
-            X(2) * (ux * uy * (1 - cp) - uz * sp) + ...
-            X(3) * (ux * uz * (1 - cp) + uy * sp);
+  Y(1,:) = X(1) * (cp + ux * ux * (1 - cp)) + ...
+           X(2) * (ux * uy * (1 - cp) - uz * sp) + ...
+           X(3) * (ux * uz * (1 - cp) + uy * sp);
 
-  Y(2, :) = X(1) * (uy * ux * (1 - cp) + uz * sp) + ...
-            X(2) * (cp + uy * uy * (1 - cp)) + ...
-            X(3) * (uy * uz * (1 - cp) - ux * sp);
+  Y(2,:) = X(1) * (uy * ux * (1 - cp) + uz * sp) + ...
+           X(2) * (cp + uy * uy * (1 - cp)) + ...
+           X(3) * (uy * uz * (1 - cp) - ux * sp);
 
-  Y(3, :) = X(1) * (uz * ux * (1 - cp) - uy * sp) + ...
-            X(2) * (uz * uy * (1 - cp) + ux * sp) + ...
-            X(3) * (cp + uz * uz * (1 - cp));
+  Y(3,:) = X(1) * (uz * ux * (1 - cp) - uy * sp) + ...
+           X(2) * (uz * uy * (1 - cp) + ux * sp) + ...
+           X(3) * (cp + uz * uz * (1 - cp));
 
 endfunction
 
@@ -356,7 +354,7 @@
 %!demo
 %! clf;
 %! t = 0:.15:15;
-%! xyz{1} = [cos(t)' sin(t)' (t/3)'];
+%! xyz{1} = [cos(t)', sin(t)', (t/3)'];
 %! dia{1} = cos(t)';
 %! streamtube (xyz, dia);
 %! grid on;
--- a/scripts/plot/draw/surfl.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/plot/draw/surfl.m	Tue Jul 07 19:40:20 2020 -0400
@@ -156,7 +156,7 @@
 
     ## Get view vector (vv).
     [az, el] = view ();
-    vv = sph2cart ((az - 90) * pi/180.0, el * pi/180.0, 1.0);
+    [vv(1), vv(2), vv(3)] = sph2cart ((az - 90) * pi/180.0, el * pi/180.0, 1.0);
 
     if (! have_lv)
       ## Calculate light vector (lv) from view vector.
--- a/scripts/plot/util/__actual_axis_position__.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/plot/util/__actual_axis_position__.m	Tue Jul 07 19:40:20 2020 -0400
@@ -50,7 +50,7 @@
   end_unwind_protect
   ## Get axes size in pixels
   if (strcmp (get (axis_obj.parent, "__graphics_toolkit__"), "gnuplot")
-      && strcmp (axis_obj.activepositionproperty, "outerposition"))
+      && strcmp (axis_obj.positionconstraint, "outerposition"))
     pos_in_pixels = axis_obj.outerposition .* fig_position([3, 4, 3, 4]);
   else
     pos_in_pixels = axis_obj.position .* fig_position([3, 4, 3, 4]);
@@ -82,7 +82,7 @@
     endif
     pos = pos_in_pixels ./ fig_position([3, 4, 3, 4]);
   elseif (strcmp (get (axis_obj.parent, "__graphics_toolkit__"), "gnuplot")
-          && strcmp (axis_obj.activepositionproperty, "outerposition"))
+          && strcmp (axis_obj.positionconstraint, "outerposition"))
     pos = axis_obj.outerposition;
   else
     pos = axis_obj.position;
--- a/scripts/plot/util/hdl2struct.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/plot/util/hdl2struct.m	Tue Jul 07 19:40:20 2020 -0400
@@ -139,12 +139,13 @@
   persistent excluded;
 
   if (isempty (excluded))
-    excluded = cell2struct (repmat ({[]}, 1, 15),
+    excluded = cell2struct (repmat ({[]}, 1, 16),
                             {"beingdeleted", "busyaction", "buttondownfcn", ...
-                             "children", "clipping", "createfcn", ...
-                             "deletefcn", "handlevisibility", "hittest", ...
-                             "interruptible", "parent", "selected" , ...
-                             "selectionhighlight", "type", "uicontextmenu"}, 2);
+                             "children", "clipping", "contextmenu", ...
+                             "createfcn", "deletefcn", "handlevisibility", ...
+                             "hittest", "interruptible", "parent", ...
+                             "selected" , "selectionhighlight", "type", ...
+                             "uicontextmenu"}, 2);
   endif
 
   obj = get (h);
--- a/scripts/plot/util/isprop.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/plot/util/isprop.m	Tue Jul 07 19:40:20 2020 -0400
@@ -31,29 +31,42 @@
 ## logical array indicating whether each handle has the property @var{prop}.
 ##
 ## For plotting, @var{obj} is a handle to a graphics object.  Otherwise,
-## @var{obj} should be an instance of a class.
-## @seealso{get, set, ismethod, isobject}
+## @var{obj} should be an instance of a class.  @code{isprop} reports whether
+## the class defines a property, but @code{Access} permissions or visibility
+## restrictions (@code{Hidden = true}) may prevent use by the programmer.
+## @seealso{get, set, properties, ismethod, isobject}
 ## @end deftypefn
 
 function res = isprop (obj, prop)
 
   if (nargin != 2)
     print_usage ();
-  elseif (! ischar (prop))
+  endif
+
+  if (! ischar (prop))
     error ("isprop: PROP name must be a string");
   endif
 
-  warning ("error", "Octave:abbreviated-property-match", "local");
+  if (isobject (obj))
+    ## Separate code for classdef objects because Octave doesn't handle arrays
+    ## of objects and so can't use the generic code.
+    warning ("off", "Octave:classdef-to-struct", "local");
+
+    all_props = __fieldnames__ (obj);
+    res = any (strcmp (prop, all_props));
+  else
+    warning ("error", "Octave:abbreviated-property-match", "local");
 
-  res = false (size (obj));
-  for i = 1:numel (res)
-    if (ishghandle (obj(i)))
-      try
-        v = get (obj(i), prop);
-        res(i) = true;
-      end_try_catch
-    endif
-  endfor
+    res = false (size (obj));
+    for i = 1:numel (res)
+      if (ishghandle (obj(i)))
+        try
+          get (obj(i), prop);
+          res(i) = true;
+        end_try_catch
+      endif
+    endfor
+  endif
 
 endfunction
 
@@ -63,6 +76,11 @@
 %!assert (isprop (zeros (2, 3), "visible"), true (2, 3))
 %!assert (isprop ([-2, -1, 0], "visible"), [false, false, true])
 
+%!test
+%! m = containers.Map ();
+%! assert (isprop (m, "KeyType"));
+%! assert (! isprop (m, "FooBar"));
+
 %!error isprop ()
 %!error isprop (1)
 %!error isprop (1,2,3)
--- a/scripts/plot/util/print.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/plot/util/print.m	Tue Jul 07 19:40:20 2020 -0400
@@ -1006,13 +1006,10 @@
   switch (opts.devopt)
     case {"pdflatexstandalone"}
       packages = "\\usepackage{graphicx,color}";
-      graphicsfile = [opts.name "-inc.pdf"];
     case {"pslatexstandalone"}
       packages = "\\usepackage{epsfig,color}";
-      graphicsfile = [opts.name "-inc.ps"];
     otherwise
       packages = "\\usepackage{epsfig,color}";
-      graphicsfile = [opts.name "-inc.eps"];
   endswitch
 
   packages = {packages "\\usepackage[utf8]{inputenc}"};
@@ -1035,9 +1032,6 @@
     error ("Octave:print:errorclosingfile",
            "print: error closing file '%s'", latexfile);
   endif
-  ## FIXME: should this be fixed in GL2PS?
-  latex = strrep (latex, "\\includegraphics{}",
-                  sprintf ("\\includegraphics{%s}", graphicsfile));
 
   fid = fopen (latexfile, "w");
   if (fid >= 0)
--- a/scripts/plot/util/private/__add_default_menu__.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/plot/util/private/__add_default_menu__.m	Tue Jul 07 19:40:20 2020 -0400
@@ -28,7 +28,6 @@
 ## @deftypefnx {} {} __add_default_menu__ (@var{hfig}, @var{hmenu})
 ## Add default menu and listeners to figure.
 ##
-##
 ## All uimenu handles have their @qcode{"HandleVisibility"} property set to
 ## @qcode{"off"}.
 ## @end deftypefn
@@ -37,7 +36,7 @@
 
   ## Gnuplot doesn't handle uimenu and uitoolbar objects
   if (strcmp (graphics_toolkit (), "gnuplot"))
-    return
+    return;
   endif
 
   ## Create
@@ -45,11 +44,11 @@
     ## File menu
     hui = uimenu (hf, "label", "&File", "tag", "__default_menu__File", ...
                       "handlevisibility", "off");
-    uimenu (hui, "label", "&Open", "callback", @open_cb, ...
+    uimenu (hui, "label", "&Open...", "callback", @open_cb, ...
             "accelerator", "o");
     uimenu (hui, "label", "&Save", "callback", {@save_cb, "save"}, ...
             "accelerator", "s");
-    uimenu (hui, "label", "Save &As", "callback", {@save_cb, "saveas"}, ...
+    uimenu (hui, "label", "Save &As...", "callback", {@save_cb, "saveas"}, ...
             "accelerator", "S");
     uimenu (hui, "label", "&Close", "callback", @close_cb, ...
             "accelerator", "w", "separator", "on");
@@ -173,17 +172,16 @@
   set (htb, "visible", toolbar_state);
 endfunction
 
-function open_cb (h, e)
-  [filename, filedir] = uigetfile ({"*.ofig", "Octave Figure File"}, ...
+function open_cb ()
+  [filename, filedir] = uigetfile ({"*.ofig;*.fig", "Figure Files"}, ...
                                    "Open Figure");
   if (filename != 0)
     fname = fullfile (filedir, filename);
-    tmphf = hgload (fname);
-    set (tmphf, "filename", fname);
+    openfig (fname);
   endif
 endfunction
 
-function save_cb (h, e, action)
+function save_cb (h, ~, action)
   hfig = gcbf ();
   fname = get (hfig, "filename");
 
@@ -198,34 +196,53 @@
   endif
 endfunction
 
+function __save_as__ (hf, fname = "")
+  if (! isempty (fname))
+    def = fname;
+  else
+    def = fullfile (pwd (), "untitled.ofig");
+  endif
+  filter = {"*.ofig", "Octave Figure";
+            "*.eps",  "Encapsulated PostScript";
+            "*.pdf",  "Portable Document Format";
+            "*.ps",   "PostScript";
+            "*.svg",  "Scalable Vector Graphics";
+            "*.gif",  "GIF Image";
+            "*.jpg",  "JPEG Image";
+            "*.png",  "Portable Network Graphics Image";
+            "*.tiff", "TIFF Image"};
+  ## Reorder filters to have current first
+  [~, ~, ext] = fileparts (def);
+  idx = strcmp (filter(:,1), ["*" tolower(ext)]);
+  filter = [filter(idx,:); filter(! idx,:)];
 
-function __save_as__ (hf, fname = "")
-  filter = ifelse (! isempty (fname), fname, ...
-                   {"*.ofig", "Octave Figure File";
-                    "*.eps;*.pdf;*.svg;*.ps", "Vector Image Formats";
-                    "*.gif;*.jpg;*.png;*.tiff", "Bitmap Image Formats"});
-  def = ifelse (! isempty (fname), fname, fullfile (pwd, "untitled.ofig"));
-
-  [filename, filedir] = uiputfile (filter, "Save Figure", def);
+  [filename, filedir, filteridx] = uiputfile (filter, "Save Figure", def);
 
   if (filename != 0)
     fname = fullfile (filedir, filename);
-    set (gcbf, "filename", fname);
-    flen = numel (fname);
-    if (flen > 5 && strcmp (fname(flen-4:end), ".ofig"))
-      hgsave (hf, fname);
+    [~, ~, ext] = fileparts (fname);
+    if (filteridx > rows (filter))
+      ## "All Files" option
+      if (isempty (ext))
+        fmt = "";
+      else
+        fmt = ext(2:end);
+      endif
     else
-      saveas (hf, fname);
+      fmt = filter{filteridx,1}(3:end);
+      if (isempty (ext))
+        fname = [fname "." fmt];
+      endif
     endif
+    set (hf, "filename", fname);
+    saveas (hf, fname, fmt);
   endif
 endfunction
 
-
-function close_cb (h, e)
-  close (gcbf);
+function close_cb ()
+  close (gcbf ());
 endfunction
 
-
 function [hax, fig] = __get_axes__ (h)
   ## Get parent figure
   fig = ancestor (h, "figure");
@@ -234,7 +251,7 @@
   hax = findobj (fig, "type", "axes", "-not", "tag", "legend");
 endfunction
 
-function autoscale_cb (h, e)
+function autoscale_cb (h)
   hax = __get_axes__ (h);
   arrayfun (@(h) axis (h, "auto"), hax);
   drawnow ();
@@ -253,7 +270,7 @@
                                     "FigureHandle", hf));
 endfunction
 
-function guimode_cb (h, e)
+function guimode_cb (h)
   [hax, fig] = __get_axes__ (h);
   id = get (h, "tag");
   switch (id)
@@ -275,7 +292,7 @@
   endswitch
 endfunction
 
-function mouse_tools_cb (h, ev, htools, typ = "")
+function mouse_tools_cb (h, ~, htools, typ = "")
 
   persistent recursion = false;
 
@@ -290,7 +307,7 @@
       mode = get (hf, "__mouse_mode__");
       state = "on";
 
-      switch mode
+      switch (mode)
         case "zoom"
           zm = get (hf, "__zoom_mode__");
           if (strcmp (zm.Direction, "in"))
@@ -318,7 +335,7 @@
       ## Update the mouse mode according to the button state
       state = get (h, "state");
 
-      switch typ
+      switch (typ)
         case {"zoomin", "zoomout"}
           prop = "__zoom_mode__";
           val = get (hf, prop);
@@ -329,7 +346,7 @@
             else
               val.Direction = "out";
             endif
-            set (hf, "__mouse_mode__" , "zoom");
+            set (hf, "__mouse_mode__", "zoom");
           endif
           val.Enable = state;
           set (hf, prop, val);
@@ -338,21 +355,21 @@
           prop = ["__", typ, "_mode__"];
           val = get (hf, prop);
           if (strcmp (state, "on"))
-            set (hf, "__mouse_mode__" , typ);
+            set (hf, "__mouse_mode__", typ);
           endif
           val.Enable = state;
           set (hf, prop, val);
 
         case {"text", "select"}
           if (strcmp (state, "on"))
-            set (hf, "__mouse_mode__" , typ);
+            set (hf, "__mouse_mode__", typ);
           endif
       endswitch
 
       if (strcmp (state, "on"))
         set (htools(htools != h), "state", "off");
       elseif (! any (strcmp (get (htools, "state"), "on")))
-        set (hf, "__mouse_mode__" , "none");
+        set (hf, "__mouse_mode__", "none");
       endif
     endif
 
--- a/scripts/plot/util/private/__gnuplot_draw_axes__.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/plot/util/private/__gnuplot_draw_axes__.m	Tue Jul 07 19:40:20 2020 -0400
@@ -56,6 +56,10 @@
   endif
 
   nd = __calc_dimensions__ (h);
+  if (nd == 2 && (any (get (h, "view") != [0, 90])))
+    ## view() only works correctly on 3-D axes in gnuplot (bug #58526).
+    nd = 3;
+  endif
 
   if (strcmp (axis_obj.dataaspectratiomode, "manual")
       && strcmp (axis_obj.xlimmode, "manual")
@@ -87,7 +91,7 @@
     dr = 1;
   endif
 
-  if (strcmp (axis_obj.activepositionproperty, "position"))
+  if (strcmp (axis_obj.positionconstraint, "innerposition"))
     if (nd == 2 || all (mod (axis_obj.view, 90) == 0))
       x = [1, 1];
     else
@@ -103,7 +107,7 @@
     fprintf (plot_stream, "set rmargin screen %.15g;\n",
              pos(1)+pos(3)/2+x(1)*pos(3)/2);
     sz_str = "";
-  else ## activepositionproperty == outerposition
+  else ## positionconstraint == outerposition
     fprintf (plot_stream, "unset tmargin;\n");
     fprintf (plot_stream, "unset bmargin;\n");
     fprintf (plot_stream, "unset lmargin;\n");
@@ -2296,7 +2300,7 @@
              tickdir, ticklength, axispos, mirror);
     labels = strrep (labels, "%", "%%");
     for i = 1:ntics
-      fprintf (plot_stream, ' "%s" %.15g', labels{k++}, tics(i));
+      fprintf (plot_stream, ' "%s" %.15f', labels{k++}, tics(i));
       if (i < ntics)
         fputs (plot_stream, ", ");
       endif
--- a/scripts/plot/util/private/__print_parse_opts__.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/plot/util/private/__print_parse_opts__.m	Tue Jul 07 19:40:20 2020 -0400
@@ -250,7 +250,11 @@
     if (opengl_ok && strcmp (graphics_toolkit (arg_st.figure), "qt"))
       ## "opengl" renderer only does text rotations of 0°, 90°, 180°, 270°, ...
       ht = findall (arg_st.figure, "type", "text");
-      angles = [get(ht, "rotation"){:}];
+      if (isempty (ht))
+        angles = [];
+      else
+        angles = [get(ht, "rotation"){:}];
+      endif
       if (any (mod (angles, 90)))
         arg_st.renderer = "painters";
       else
--- a/scripts/plot/util/saveas.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/plot/util/saveas.m	Tue Jul 07 19:40:20 2020 -0400
@@ -33,6 +33,14 @@
 ## are:
 ##
 ## @table @code
+##
+##   @item ofig
+##     Octave figure file format (default)
+##
+##   @item mfig
+##     Two files: Octave m-file @file{filename.m} containing code
+##     to open Octave figure file @file{filename.ofig}
+##
 ##   @item ps
 ##     PostScript
 ##
@@ -58,7 +66,7 @@
 ##
 ## If @var{fmt} is omitted it is extracted from the extension of
 ## @var{filename}.  The default format when there is no extension is
-## @qcode{"pdf"}.
+## @qcode{"ofig"}.
 ##
 ## @example
 ## @group
@@ -68,7 +76,7 @@
 ## @end group
 ## @end example
 ##
-## @seealso{print, hgsave, orient}
+## @seealso{print, savefig, hgsave, orient}
 ## @end deftypefn
 
 function saveas (h, filename, fmt)
@@ -90,32 +98,57 @@
     fig = ancestor (h, "figure");
   endif
 
+  default_fmt = "ofig";
+
   if (nargin == 2)
     ## Attempt to infer format from filename
     [~, ~, ext] = fileparts (filename);
-    if (! isempty (ext))
-      fmt = ext(2:end);
-    else
-      fmt = "pdf";
+    if (isempty (ext))
+      ext = ["." default_fmt];
+      filename = [filename ext];
     endif
+    fmt = ext(2:end);
   endif
 
   if (nargin == 3)
     if (! ischar (fmt))
       error ("saveas: FMT must be a string");
+    elseif (isempty (fmt))
+      fmt = default_fmt;
     endif
     [~, ~, ext] = fileparts (filename);
     if (isempty (ext))
-      filename = [filename "." fmt];
+      ext = ["." fmt];
+      filename = [filename ext];
     endif
   endif
 
-  prt_opt = ["-d" tolower(fmt)];
+  fmt = tolower (fmt);
+
+  if (any (strcmp (fmt, {"ofig", "fig"})))
+    savefig (fig, filename);
+  elseif (any (strcmp (fmt, {"m", "mfig"})))
+    [d, n] = fileparts (filename);
+    mfilename = fullfile (d, [n ".m"]);
+    figfilename = fullfile (d, [n ".ofig"]);
+
+    savefig (fig, figfilename);
 
-  print (fig, filename, prt_opt);
+    fid = fopen (mfilename, "wt");
+    if (fid < 0)
+      error ("saveas: could not open '%s' for writing", mfilename);
+    endif
+    fprintf (fid, ['h = openfig ("' figfilename '");' "\n"]);
+    fclose (fid);
+  else
+    prt_opt = ["-d" fmt];
+
+    print (fig, filename, prt_opt);
+  endif
 
 endfunction
 
+
 ## Test input validation
 %!error saveas ()
 %!error saveas (1)
--- a/scripts/plot/util/struct2hdl.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/plot/util/struct2hdl.m	Tue Jul 07 19:40:20 2020 -0400
@@ -47,7 +47,7 @@
 
   fields = {"handle", "type", "children", "properties", "special"};
   partypes = {"root", "figure", "axes", "hggroup"};
-  othertypes = {"line", "patch", "surface", "image", "text"};
+  othertypes = {"line", "patch", "scatter", "surface", "image", "text"};
   alltypes = [partypes othertypes];
 
   if (nargin > 3 || ! isstruct (s))
@@ -108,16 +108,22 @@
   ## change the mode to "manual" when the value is "auto".
   names = fieldnames (s.properties);
   n = strncmp (cellfun (@fliplr, names, "uniformoutput", false), "edom", 4);
-  n = (n | strcmp (names, "activepositionproperty"));
+  n = (n | strcmp (names, "positionconstraint"));
   names = [names(! n); names(n)];
   n_pos = find (strcmp (names, "position") | strcmp (names, "outerposition"));
   if (strcmp (s.type, "axes") && numel (n_pos) == 2)
-    if (strcmp (s.properties.activepositionproperty, "position"))
+    if (isfield (s.properties, "positionconstraint"))
+      positionconstraint = s.properties.positionconstraint;
+    else
+      ## loading old figure file before "positionconstraint" property was added
+      positionconstraint = s.properties.activepositionproperty;
+    endif
+    if (strcmp (positionconstraint, "outerposition"))
+      names{n_pos(1)} = "position";
+      names{n_pos(2)} = "outerposition";
+    else
       names{n_pos(1)} = "outerposition";
       names{n_pos(2)} = "position";
-    else
-      names{n_pos(1)} = "position";
-      names{n_pos(2)} = "outerposition";
     endif
   endif
   ## Reorder the properties with the mode properties coming last
@@ -157,14 +163,22 @@
         par = gcf;
       endif
     endif
-    if (isfield (s.properties, "tightinset"))
-      s.properties = rmfield (s.properties, {"tightinset"});
+    ## remove read only properties
+    ## FIXME: Remove "interactions", "layout", "legend", "toolbar", "xaxis",
+    ## "yaxis", and "zaxis" from this list once they are implemented.
+    ro_props = {"interactions", "layout", "legend", "nextseriesindex", ...
+                "tightinset", "toolbar", "xaxis", "yaxis", "zaxis"};
+    has_ro_props = cellfun (@(x) isfield (s.properties, x), ro_props);
+    if (any (has_ro_props))
+      s.properties = rmfield (s.properties, ro_props(has_ro_props));
     endif
     [h, s] = createaxes (s, p, par);
   elseif (strcmp (s.type, "line"))
     h = createline (s, par);
   elseif (strcmp (s.type, "patch"))
     [h, s] = createpatch (s, par);
+  elseif (strcmp (s.type, "scatter"))
+    [h, s] = createscatter (s, par);
   elseif (strcmp (s.type, "text"))
     if (isfield (s.properties, "extent"))
       s.properties = rmfield (s.properties, "extent");
@@ -180,7 +194,8 @@
     [h, s, p] = createhg (s, p, par, hilev);
   elseif (any (strcmp (s.type, {"uimenu", "uicontextmenu",...
                                 "uicontrol", "uipanel", "uibuttongroup",...
-                                "uitoolbar", "uipushtool", "uitable"})))
+                                "uitoolbar", "uipushtool", "uitoggletool"...
+                                "uitable"})))
     if (isfield (s.properties, "extent"))
       s.properties = rmfield (s.properties, "extent");
     endif
@@ -368,6 +383,24 @@
 
 endfunction
 
+function [h, sout] = createscatter (s, par)
+
+  if (isempty (s.properties.zdata))
+    ## 2D scatter
+    h = scatter (s.properties.xdata, s.properties.ydata);
+  else
+    ## 3D scatter
+    h = scatter3 (s.properties.xdata, s.properties.ydata, s.properties.zdata);
+  endif
+
+  set (h, "parent", par);
+  s.properties = rmfield (s.properties,
+                          {"xdata", "ydata", "zdata"});
+  addmissingprops (h, s.properties);
+  sout = s;
+
+endfunction
+
 function h = createtext (s, par)
   h = text ("parent", par);
   addmissingprops (h, s.properties);
--- a/scripts/plot/util/subplot.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/plot/util/subplot.m	Tue Jul 07 19:40:20 2020 -0400
@@ -211,7 +211,7 @@
     set (cf, "units", "pixels");
 
     ## FIXME: At the moment we force gnuplot to use the aligned mode
-    ##        which will set "activepositionproperty" to "position".
+    ##        which will set "positionconstraint" to "innerposition".
     ##        This can yield to text overlap between labels and titles.
     ##        See bug #31610.
     if (strcmp (get (cf, "__graphics_toolkit__"), "gnuplot"))
@@ -288,7 +288,7 @@
         set (hsubplot, varargin{:});
       endif
     else
-      pval = [{"activepositionproperty", "position", ...
+      pval = [{"positionconstraint", "innerposition", ...
                "position", pos, "looseinset", li} varargin];
       if (! make_subplot)
         hsubplot = axes (pval{:});
@@ -445,7 +445,7 @@
       endif
       for ii = 1:numel (hsubplots)
         set (hsubplots(ii), "outerposition", opos(ii,:), ...
-             "activepositionproperty", "position");
+             "positionconstraint", "innerposition");
       endfor
 
       ## Compare current positions to default and compute the new ones
--- a/scripts/polynomial/polyfit.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/polynomial/polyfit.m	Tue Jul 07 19:40:20 2020 -0400
@@ -27,25 +27,33 @@
 ## @deftypefn  {} {@var{p} =} polyfit (@var{x}, @var{y}, @var{n})
 ## @deftypefnx {} {[@var{p}, @var{s}] =} polyfit (@var{x}, @var{y}, @var{n})
 ## @deftypefnx {} {[@var{p}, @var{s}, @var{mu}] =} polyfit (@var{x}, @var{y}, @var{n})
-## Return the coefficients of a polynomial @var{p}(@var{x}) of degree
-## @var{n} that minimizes the least-squares-error of the fit to the points
-## @code{[@var{x}, @var{y}]}.
+## Return the coefficients of a polynomial @var{p}(@var{x}) of degree @var{n}
+## that minimizes the least-squares-error of the fit to the points
+## @code{[@var{x}(:), @var{y}(:)]}.
 ##
-## If @var{n} is a logical vector, it is used as a mask to selectively force
-## the corresponding polynomial coefficients to be used or ignored.
+## @var{n} is typically an integer @geq{} 0 specifying the degree of the
+## approximating polynomial.  If @var{n} is a logical vector, it is used as a
+## mask to selectively force the corresponding polynomial coefficients to be
+## used or ignored.
 ##
-## The polynomial coefficients are returned in a row vector.
+## The polynomial coefficients are returned in the row vector @var{p}.  The
+## output @var{p} may be directly used with @code{polyval} to estimate values
+## using the fitted polynomial.
 ##
 ## The optional output @var{s} is a structure containing the following fields:
 ##
 ## @table @samp
-## @item R
-## Triangular factor R from the QR@tie{}decomposition.
+##
+## @item yf
+## The values of the polynomial for each value of @var{x}.
 ##
 ## @item X
 ## The @nospell{Vandermonde} matrix used to compute the polynomial
 ## coefficients.
 ##
+## @item R
+## Triangular factor R from the QR@tie{}decomposition.
+##
 ## @item C
 ## The unscaled covariance matrix, formally equal to the inverse of
 ## @var{x'}*@var{x}, but computed in a way minimizing roundoff error
@@ -56,25 +64,37 @@
 ##
 ## @item normr
 ## The norm of the residuals.
-##
-## @item yf
-## The values of the polynomial for each value of @var{x}.
 ## @end table
 ##
-## The second output may be used by @code{polyval} to calculate the
-## statistical error limits of the predicted values.  In particular, the
-## standard deviation of @var{p} coefficients is given by
+## The second output may be used by @code{polyval} to calculate the statistical
+## error limits of the predicted values.  In particular, the standard deviation
+## of @var{p} coefficients is given by
 ##
-## @code{sqrt (diag (s.C)/s.df)*s.normr}.
+## @code{sqrt (diag (@var{s.C})/@var{s.df}) * @var{s.normr}}.
 ##
-## When the third output, @var{mu}, is present the coefficients, @var{p}, are
-## associated with a polynomial in
+## When the third output, @var{mu}, is present the original data is centered
+## and scaled which can improve the numerical stability of the fit.  The
+## coefficients @var{p} are associated with a polynomial in
 ##
 ## @code{@var{xhat} = (@var{x} - @var{mu}(1)) / @var{mu}(2)} @*
 ## where @var{mu}(1) = mean (@var{x}), and @var{mu}(2) = std (@var{x}).
 ##
-## This linear transformation of @var{x} improves the numerical stability of
-## the fit.
+## Example 1 : logical @var{n} and integer @var{n}
+##
+## @example
+## @group
+## f = @@(x) x.^2 + 5;   # data-generating function
+## x = 0:5;
+## y = f (x);
+## ## Fit data to polynomial A*x^3 + B*x^1
+## p = polyfit (x, y, logical ([1, 0, 1, 0]))
+## @result{} p = [ 0.0680, 0, 4.2444, 0 ]
+## ## Fit data to polynomial using all terms up to x^3
+## p = polyfit (x, y, 3)
+## @result{} p = [ -4.9608e-17, 1.0000e+00, -3.3813e-15, 5.0000e+00 ]
+## @end group
+## @end example
+##
 ## @seealso{polyval, polyaffine, roots, vander, zscore}
 ## @end deftypefn
 
@@ -84,93 +104,118 @@
     print_usage ();
   endif
 
+  y_is_row_vector = isrow (y);
+
+  ## Reshape x & y into column vectors.
+  x = x(:);
+  y = y(:);
+
+  nx = numel (x);
+  ny = numel (y);
+  if (nx != ny)
+    error ("polyfit: X and Y must have the same number of points");
+  endif
+
   if (nargout > 2)
-    ## Normalized the x values.
+    ## Center and scale the x values.
     mu = [mean(x), std(x)];
     x = (x - mu(1)) / mu(2);
   endif
 
-  if (! size_equal (x, y))
-    error ("polyfit: X and Y must be vectors of the same size");
-  endif
-
+  ## n is the polynomial degree (an input, or deduced from the polymask size)
+  ## m is the effective number of coefficients.
   if (islogical (n))
-    polymask = n;
-    ## n is the polynomial degree as given the polymask size; m is the
-    ## effective number of used coefficients.
-    n = length (polymask) - 1; m = sum (polymask) - 1;
+    polymask = n(:).';          # force to row vector
+    n = numel (polymask) - 1;
+    m = sum (polymask) - 1;
+    pad_output = true;
   else
     if (! (isscalar (n) && n >= 0 && ! isinf (n) && n == fix (n)))
       error ("polyfit: N must be a non-negative integer");
     endif
-    polymask = logical (ones (1, n+1)); m = n;
+    polymask = true (1, n+1);
+    m = n;
+    pad_output = false;
   endif
 
-  y_is_row_vector = (rows (y) == 1);
-
-  ## Reshape x & y into column vectors.
-  l = numel (x);
-  x = x(:);
-  y = y(:);
+  if (m >= nx)
+    warning ("polyfit: degree of polynomial N is >= number of data points; solution is not unique");
+    m = nx;
+    pad_output = true;
+    ## Keep the lowest m entries in polymask
+    idx = find (polymask);
+    idx((end-m+1):end) = [];  
+    polymask(idx) = false;
+  endif
 
   ## Construct the Vandermonde matrix.
-  v = vander (x, n+1);
+  X = vander (x, n+1);
+  v = X(:, polymask);
 
   ## Solve by QR decomposition.
-  [q, r, k] = qr (v(:, polymask), 0);
+  [q, r, k] = qr (v, 0);
   p = r \ (q' * y);
   p(k) = p;
 
-  if (n != m)
-    q = p; p = zeros (n+1, 1);
-    p(polymask) = q;
-  endif
-
-  if (nargout > 1)
+  if (isargout (2))
     yf = v*p;
-
     if (y_is_row_vector)
       s.yf = yf.';
     else
       s.yf = yf;
     endif
-    s.X = v;
+
+    s.X = X;
 
-    ## r.'*r is positive definite if X(:, polymask) is of full rank.
-    ## Invert it by cholinv to avoid taking the square root of squared
-    ## quantities.  If cholinv fails, then X(:, polymask) is rank deficient
-    ## and not invertible.
+    ## r.'*r is positive definite if matrix v is of full rank.  Invert it by
+    ## cholinv to avoid taking the square root of squared quantities.
+    ## If cholinv fails, then v is rank deficient and not invertible.
     try
       C = cholinv (r.'*r)(k, k);
     catch
-      C = NaN (m+1, m+1);
+      C = NaN (m, m);
     end_try_catch
 
-    if (n != m)
-      ## fill matrices if required
+    if (pad_output)
       s.X(:, ! polymask) = 0;
-      s.R = zeros (n+1, n+1); s.R(polymask, polymask) = r;
-      s.C = zeros (n+1, n+1); s.C(polymask, polymask) = C;
+      s.R = zeros (rows (r), n+1); s.R(:, polymask) = r;
+      s.C = zeros (rows (C), n+1); s.C(:, polymask) = C;
     else
       s.R = r;
       s.C = C;
     endif
-    s.df = l - m - 1;
+
+    s.df = max (0, nx - m - 1);
     s.normr = norm (yf - y);
   endif
 
-  ## Return a row vector.
-  p = p.';
+  if (pad_output)
+    ## Zero pad output
+    q = p;
+    p = zeros (n+1, 1);
+    p(polymask) = q;
+  endif
+  p = p.';  # Return a row vector.  
 
 endfunction
 
 
 %!shared x
 %! x = [-2, -1, 0, 1, 2];
-%!assert (polyfit (x, x.^2+x+1, 2), [1, 1, 1], sqrt (eps))
-%!assert (polyfit (x, x.^2+x+1, 3), [0, 1, 1, 1], sqrt (eps))
-%!fail ("polyfit (x, x.^2+x+1)")
-%!fail ("polyfit (x, x.^2+x+1, [])")
+
+%!assert (polyfit (x, 3*x.^2 + 2*x + 1, 2), [3, 2, 1], 10*eps)
+%!assert (polyfit (x, 3*x.^2 + 2*x + 1, logical ([1 1 1])), [3, 2, 1], 10*eps)
+%!assert (polyfit (x, x.^2 + 2*x + 3, 3), [0, 1, 2, 3], 10*eps)
+%!assert (polyfit (x, x.^2 + 2*x + 3, logical ([0 1 1 1])), [0 1 2 3], 10*eps)
+
+## Test logical input N
+%!test
+%! x = [0:5];
+%! y = 3*x.^3 + 2*x.^2 + 4;
+%! [p, s] = polyfit (x, y, logical ([1, 0, 1, 1]));
+%! assert (p(2), 0);
+%! assert (all (p([1, 3, 4])));
+%! assert (s.df, 3);
 
 ## Test difficult case where scaling is really needed.  This example
 ## demonstrates the rather poor result which occurs when the dependent
@@ -188,25 +233,29 @@
 %! assert (s2.normr < s1.normr);
 
 %!test
-%! x = 1:4;
-%! p0 = [1i, 0, 2i, 4];
-%! y0 = polyval (p0, x);
-%! p = polyfit (x, y0, numel (p0) - 1);
-%! assert (p, p0, 1000*eps);
-
-%!test
 %! warning ("off", "Octave:nearly-singular-matrix", "local");
 %! x = 1000 + (-5:5);
 %! xn = (x - mean (x)) / std (x);
 %! pn = ones (1,5);
 %! y = polyval (pn, xn);
-%! [p, s, mu] = polyfit (x, y, numel (pn) - 1);
-%! [p2, s2] = polyfit (x, y, numel (pn) - 1);
+%! n = numel (pn) - 1;
+%! [p, s, mu] = polyfit (x, y, n);
+%! [p2, s2] = polyfit (x, y, n);
 %! assert (p, pn, s.normr);
 %! assert (s.yf, y, s.normr);
 %! assert (mu, [mean(x), std(x)]);
 %! assert (s.normr/s2.normr < sqrt (eps));
 
+## Complex polynomials
+%!test
+%! x = 1:4;
+%! p0 = [1i, 0, 2i, 4];
+%! y = polyval (p0, x);
+%! n = numel (p0) - 1;
+%! p = polyfit (x, y, n);
+%! assert (p, p0, 1000*eps);
+
+## Matrix input
 %!test
 %! x = [1, 2, 3; 4, 5, 6];
 %! y = [0, 0, 1; 1, 0, 0];
@@ -214,4 +263,89 @@
 %! expected = [0, 1, -14, 65, -112, 60] / 12;
 %! assert (p, expected, sqrt (eps));
 
-%!error <vectors of the same size> polyfit ([1, 2; 3, 4], [1, 2, 3, 4], 2)
+## Orientation of output
+%!test
+%! x = 0:5;
+%! y = x.^4 + 2*x + 5;
+%! [p, s] = polyfit (x, y, 3);
+%! assert (isrow (s.yf));
+%! [p, s] = polyfit (x, y.', 3);
+%! assert (iscolumn (s.yf));
+
+## Insufficient data for fit
+%!test
+%! x = [1, 2];
+%! y = [3, 4];
+%! ## Disable warnings entirely because there is not a specific ID to disable.
+%! wstate = warning ();
+%! unwind_protect
+%!   warning ("off", "all");
+%!   p0 = polyfit (x, y, 4);
+%!   [p1, s, mu] = polyfit (x, y, 4);
+%! unwind_protect_cleanup
+%!   warning (wstate);
+%! end_unwind_protect
+%! assert (p0, [0, 0, 0, 1, 2], 10*eps);
+%! assert (p1, [0, 0, 0, sqrt(2)/2, 3.5], 10*eps);
+%! assert (size (s.X), [2, 5]);
+%! assert (s.X(:,1:3), zeros (2,3));
+%! assert (size (s.R), [2, 5]);
+%! assert (s.R(:,1:3), zeros (2,3));
+%! assert (size (s.C), [2, 5]);
+%! assert (s.C(:,1:3), zeros (2,3));
+%! assert (s.df, 0);
+%! assert (mu, [1.5, sqrt(2)/2]);
+
+%!test
+%! x = [1, 2, 3];
+%! y = 2*x + 1;
+%! ## Disable warnings entirely because there is not a specific ID to disable.
+%! wstate = warning ();
+%! unwind_protect
+%!   warning ("off", "all");
+%!   p0 = polyfit (x, y, logical ([1, 1, 1, 0 1]));
+%!   [p1, s, mu] = polyfit (x, y, logical ([1, 1, 1, 0 1]));
+%! unwind_protect_cleanup
+%!   warning (wstate);
+%! end_unwind_protect
+%! assert (p0, [0, -2/11, 12/11, 0, 23/11], 10*eps);
+%! assert (p1, [0, 2, 0, 0, 5], 10*eps);
+%! assert (size (s.X), [3, 5]);
+%! assert (s.X(:,[1,4]), zeros (3,2));
+%! assert (size (s.R), [3, 5]);
+%! assert (s.R(:,[1,4]), zeros (3,2));
+%! assert (size (s.C), [3, 5]);
+%! assert (s.C(:,[1,4]), zeros (3,2));
+%! assert (s.df, 0);
+%! assert (mu, [2, 1]);
+
+%!test <*57964>
+%! ## Disable warnings entirely because there is not a specific ID to disable.
+%! wstate = warning ();
+%! unwind_protect
+%!   warning ("off", "all");
+%!   [p, s] = polyfit ([1,2], [3,4], 2);
+%! unwind_protect_cleanup
+%!   warning (wstate);
+%! end_unwind_protect
+%! assert (size (p), [1, 3]);
+%! assert (size (s.X), [2, 3]);
+%! assert (s.X(:,1), [0; 0]);
+%! assert (size (s.R), [2, 3]);
+%! assert (s.R(:,1), [0; 0]);
+%! assert (size (s.C), [2, 3]);
+%! assert (s.C(:,1), [0; 0]);
+
+## Test input validation
+%!error polyfit ()
+%!error polyfit (1)
+%!error polyfit (1,2)
+%!error polyfit (1,2,3,4,5)
+%!error <X and Y must have the same number of points> polyfit ([1, 2], 1, 1)
+%!error <X and Y must have the same number of points> polyfit (1, [1, 2], 1)
+%!error <N must be a non-negative integer> polyfit (1, 2, [1,2])
+%!error <N must be a non-negative integer> polyfit (1, 2, -1)
+%!error <N must be a non-negative integer> polyfit (1, 2, Inf)
+%!error <N must be a non-negative integer> polyfit (1, 2, 1.5)
+%!test <*57964>
+%! fail ("p = polyfit ([1,2], [3,4], 4)", "warning", "solution is not unique");
--- a/scripts/prefs/getpref.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/prefs/getpref.m	Tue Jul 07 19:40:20 2020 -0400
@@ -151,9 +151,7 @@
 %!
 %! unwind_protect_cleanup
 %!   unlink (fullfile (tmp_home, ".octave_prefs"));
-%!   if (isfolder (tmp_home))
-%!     rmdir (tmp_home);
-%!   endif
+%!   sts = rmdir (tmp_home);
 %!   if (isempty (HOME))
 %!     unsetenv ("HOME");
 %!   else
--- a/scripts/prefs/setpref.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/prefs/setpref.m	Tue Jul 07 19:40:20 2020 -0400
@@ -96,9 +96,7 @@
 %!         "size mismatch for PREF and VAL");
 %! unwind_protect_cleanup
 %!   unlink (fullfile (tmp_home, ".octave_prefs"));
-%!   if (isfolder (tmp_home))
-%!     rmdir (tmp_home);
-%!   endif
+%!   sts = rmdir (tmp_home);
 %!   if (isempty (HOME))
 %!     unsetenv ("HOME");
 %!   else
--- a/scripts/strings/dec2bin.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/strings/dec2bin.m	Tue Jul 07 19:40:20 2020 -0400
@@ -24,45 +24,112 @@
 ########################################################################
 
 ## -*- texinfo -*-
-## @deftypefn {} {} dec2bin (@var{d}, @var{len})
-## Return a binary number corresponding to the non-negative integer @var{d},
-## as a string of ones and zeros.
+## @deftypefn  {} {} dec2bin (@var{d})
+## @deftypefnx {} {} dec2bin (@var{d}, @var{len})
+## Return a string of ones and zeros representing the conversion of the integer
+## @var{d} to a binary number.
 ##
-## For example:
+## If @var{d} is negative, return the two's complement binary value of @var{d}.
+## If @var{d} is a matrix or cell array, return a string matrix with one row
+## for each 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.
+##
+## Examples:
 ##
 ## @example
 ## @group
 ## dec2bin (14)
 ##      @result{} "1110"
+##
+## dec2bin (-14)
+##      @result{} "11110010"
 ## @end group
 ## @end example
 ##
-## 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.
+## Programming Notes: The largest negative value that can be converted in to
+## two's complement is @code{- (flintmax () / 2)}.
 ##
-## The optional second argument, @var{len}, specifies the minimum number of
-## digits in the result.
 ## @seealso{bin2dec, dec2base, dec2hex}
 ## @end deftypefn
 
 function b = dec2bin (d, len)
 
+  if (nargin == 0 || nargin > 2)
+    print_usage ();
+  endif
+
+  if (iscell (d))
+    d = cell2mat (d);
+  endif
+  ## Create column vector for algorithm (output is always col. vector anyways)
+  d = d(:);
+  
+  lt_zero_idx = (d < 0);
+  if (any (lt_zero_idx))
+    ## FIXME: Need an algorithm that works with larger values such as int64.
+    if (any (d(lt_zero_idx) < -2^52))
+      error ("dec2bin: negative inputs cannot be less than -flintmax () / 2");
+    elseif (any (d(lt_zero_idx) < intmin ("int32")))
+      d(lt_zero_idx) += flintmax ();
+    elseif (any (d < intmin ("int16")))
+      d(lt_zero_idx) += double (intmax ("uint32")) + 1;
+    elseif (any (d < intmin ("int8")))
+      d(lt_zero_idx) += double (intmax ("uint16"))+ 1;
+    else
+      d(lt_zero_idx) += double (intmax ("uint8")) + 1;
+    endif
+  endif
+
   if (nargin == 1)
     b = dec2base (d, 2);
-  elseif (nargin == 2)
+  else
     b = dec2base (d, 2, len);
-  else
-    print_usage ();
   endif
 
 endfunction
 
 
+%!assert (dec2bin (3), "11")
 %!assert (dec2bin (14), "1110")
 %!assert (dec2bin (14, 6), "001110")
+%!assert (dec2bin ([1, 2; 3, 4]), ["001"; "011"; "010"; "100"])
 %!assert (dec2bin ({1, 2; 3, 4}), ["001"; "011"; "010"; "100"])
+%!assert (dec2bin ({1, 2; 3, 4}, 4), ["0001"; "0011"; "0010"; "0100"])
+
+## Test negative inputs
+%!assert (dec2bin (-3), "11111101")
+%!assert (dec2bin (-3, 3), "11111101")
+%!assert (dec2bin (-3, 9), "011111101")
+%!assert (dec2bin (-2^7 -1), "1111111101111111")
+%!assert (dec2bin (-2^15 -1), "11111111111111110111111111111111")
+## FIXME: Matlab generates a string that is 64 characters long
+%!assert (dec2bin (-2^31 -1),
+%!        "11111111111111111111101111111111111111111111111111111")
+%!assert (dec2bin (-2^52),
+%!        "10000000000000000000000000000000000000000000000000000")
+## FIXME: Uncomment when support for int64 is added
+%!#assert (dec2bin (-2^63),
+%!        "1000000000000000000000000000000000000000000000000000000000000000")
+%!#test
+%! assert (dec2bin (int64 (-2^63)),
+%!        "1000000000000000000000000000000000000000000000000000000000000000");
+%!#test
+%! assert (dec2bin (int64 (-2^63) -1),
+%!        "1000000000000000000000000000000000000000000000000000000000000000");
+%!#test
+%! assert (dec2bin (int64 (-2^63) +1),
+%!        "1000000000000000000000000000000000000000000000000000000000000001");
+%!assert (dec2bin ([-1, -2; -3, -4]),
+%!        ["11111111"; "11111101"; "11111110"; "11111100"])
+%!assert (dec2bin ([1, 2; 3, -4]),
+%!        ["00000001"; "00000011"; "00000010"; "11111100"])
+%!assert (dec2bin ({1, 2; 3, -4}),
+%!        ["00000001"; "00000011"; "00000010"; "11111100"])
 
 ## Test input validation
 %!error dec2bin ()
 %!error dec2bin (1, 2, 3)
+%!error <negative inputs cannot be less than> dec2bin (- flintmax ())
--- a/scripts/strings/dec2hex.m	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/strings/dec2hex.m	Tue Jul 07 19:40:20 2020 -0400
@@ -24,36 +24,66 @@
 ########################################################################
 
 ## -*- texinfo -*-
-## @deftypefn {} {} dec2hex (@var{d}, @var{len})
-## Return the hexadecimal string corresponding to the non-negative integer
-## @var{d}.
+## @deftypefn  {} {} dec2hex (@var{d})
+## @deftypefnx {} {} dec2hex (@var{d}, @var{len})
+## Return a string representing the conversion of the integer @var{d} to a
+## hexadecimal (base16) number.
 ##
-## For example:
+## If @var{d} is negative, return the two's complement binary value of @var{d}.
+## If @var{d} is a matrix or cell array, return a string matrix with one row
+## for each 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.
+##
+## Examples:
 ##
 ## @example
 ## @group
 ## dec2hex (2748)
 ##      @result{} "ABC"
+##
+## dec2hex (-2)
+##      @result{} "FE"
 ## @end group
 ## @end example
 ##
-## 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.
 ## @seealso{hex2dec, dec2base, dec2bin}
 ## @end deftypefn
 
 function h = dec2hex (d, len)
 
+  if (nargin == 0 || nargin > 2)
+    print_usage ();
+  endif
+
+  if (iscell (d))
+    d = cell2mat (d);
+  endif
+  ## Create column vector for algorithm (output is always col. vector anyways)
+  d = d(:);
+  
+  lt_zero_idx = (d < 0);
+  if (any (lt_zero_idx))
+    ## FIXME: Need an algorithm that works with larger values such as int64.
+    if (any (d(lt_zero_idx) < -2^52))
+      error ("dec2hex: negative inputs cannot be less than -flintmax () / 2");
+    elseif (any (d(lt_zero_idx) < intmin ("int32")))
+      d(lt_zero_idx) += flintmax ();
+    elseif (any (d < intmin ("int16")))
+      d(lt_zero_idx) += double (intmax ("uint32")) + 1;
+    elseif (any (d < intmin ("int8")))
+      d(lt_zero_idx) += double (intmax ("uint16"))+ 1;
+    else
+      d(lt_zero_idx) += double (intmax ("uint8")) + 1;
+    endif
+  endif
+
   if (nargin == 1)
     h = dec2base (d, 16);
-  elseif (nargin == 2)
+  else
     h = dec2base (d, 16, len);
-  else
-    print_usage ();
   endif
 
 endfunction
@@ -61,8 +91,37 @@
 
 %!assert (dec2hex (2748), "ABC")
 %!assert (dec2hex (2748, 5), "00ABC")
+%!assert (dec2hex ([2748, 2746]), ["ABC"; "ABA"])
 %!assert (dec2hex ({2748, 2746}), ["ABC"; "ABA"])
+%!assert (dec2hex ({2748, 2746}, 4), ["0ABC"; "0ABA"])
+
+## Test negative inputs
+%!assert (dec2hex (-3), "FD")
+%!assert (dec2hex (-3, 1), "FD")
+%!assert (dec2hex (-3, 3), "0FD")
+%!assert (dec2hex (-2^7 -1), "FF7F")
+%!assert (dec2hex (-2^15 -1), "FFFF7FFF")
+## FIXME: Matlab returns longer string that begins with 'F'
+%!assert (dec2hex (-2^31 -1), "1FFFFF7FFFFFFF")
+## FIXME: Matlab returns longer string that begins with 'FFF'
+%!assert (dec2hex (-2^52), "10000000000000")
+## FIXME: Uncomment when support for int64 is added
+%!#assert (dec2hex (-2^63),
+%!        "1000000000000000000000000000000000000000000000000000000000000000")
+%!#test
+%! assert (dec2hex (int64 (-2^63)),
+%!        "1000000000000000000000000000000000000000000000000000000000000000");
+%!#test
+%! assert (dec2hex (int64 (-2^63) -1),
+%!        "1000000000000000000000000000000000000000000000000000000000000000");
+%!#test
+%! assert (dec2hex (int64 (-2^63) +1),
+%!        "1000000000000000000000000000000000000000000000000000000000000001");
+%!assert (dec2hex ([-1, -2; -3, -4]), ["FF"; "FD"; "FE"; "FC"])
+%!assert (dec2hex ([1, 2; 3, -4]), ["01"; "03"; "02"; "FC"])
+%!assert (dec2hex ({1, 2; 3, -4}), ["01"; "03"; "02"; "FC"])
 
 ## Test input validation
 %!error dec2hex ()
 %!error dec2hex (1, 2, 3)
+%!error <negative inputs cannot be less than> dec2hex (- flintmax ())
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/strings/endsWith.m	Tue Jul 07 19:40:20 2020 -0400
@@ -0,0 +1,173 @@
+########################################################################
+##
+## Copyright (C) 2020 The Octave Project Developers
+##
+## See the file COPYRIGHT.md in the top-level directory of this
+## distribution or <https://octave.org/copyright/>.
+##
+## This file is part of Octave.
+##
+## Octave is free software: you can 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
+## <https://www.gnu.org/licenses/>.
+##
+########################################################################
+
+## -*- texinfo -*-
+## @deftypefn  {} {@var{retval} =} endsWith (@var{str}, @var{pattern})
+## @deftypefnx {} {@var{retval} =} endsWith (@var{str}, @var{pattern}, "IgnoreCase", @var{ignore_case})
+## Check whether string(s) end with pattern(s).
+##
+## Return an array of logical values that indicates which string(s) in the
+## input @var{str} (a single string or cell array of strings) end with
+## the input @var{pattern} (a single string or cell array of strings).
+##
+## If the value of the parameter @qcode{"IgnoreCase"} is true, then the
+## function will ignore the letter case of @var{str} and @var{pattern}.  By
+## default, the comparison is case sensitive.
+##
+## Examples:
+##
+## @example
+## @group
+## ## one string and one pattern while considering case
+## endsWith ("hello", "lo")
+##       @result{}  1
+## @end group
+##
+## @group
+## ## one string and one pattern while ignoring case
+## endsWith ("hello", "LO", "IgnoreCase", true)
+##       @result{}  1
+## @end group
+##
+## @group
+## ## multiple strings and multiple patterns while considering case
+## endsWith (@{"tests.txt", "mydoc.odt", "myFunc.m", "results.pptx"@},
+##           @{".docx", ".odt", ".txt"@})
+##       @result{}  1  1  0  0
+## @end group
+##
+## @group
+## ## multiple strings and one pattern while considering case
+## endsWith (@{"TESTS.TXT", "mydoc.odt", "result.txt", "myFunc.m"@},
+##           ".txt", "IgnoreCase", false)
+##       @result{}  0  0  1  0
+## @end group
+##
+## @group
+## ## multiple strings and one pattern while ignoring case
+## endsWith (@{"TESTS.TXT", "mydoc.odt", "result.txt", "myFunc.m"@},
+##           ".txt", "IgnoreCase", true)
+##       @result{}  1  0  1  0
+## @end group
+## @end example
+##
+## @seealso{startsWith, regexp, strncmp, strncmpi}
+## @end deftypefn
+
+function retval = endsWith (str, pattern, IgnoreCase, ignore_case)
+
+  if (nargin != 2 && nargin != 4)
+    print_usage ();
+  endif
+
+  ## Validate input str and pattern
+  if (! (iscellstr (str) || ischar (str)))
+    error ("endsWith: STR must be a string or cell array of strings");
+  endif
+  if (! (iscellstr (pattern) || ischar (pattern)))
+    error ("endsWith: PATTERN must be a string or cell array of strings");
+  endif
+
+  ## reverse str and pattern
+  str = cellfun (@flip, cellstr (str), "UniformOutput", false);
+  pattern = cellfun (@flip, cellstr (pattern), "UniformOutput", false);
+
+  if (nargin == 2)
+    ignore_case = false;
+  else
+    ## For Matlab compatibility accept any abbreviation of 3rd argument
+    if (! ischar (IgnoreCase) || isempty (IgnoreCase)
+        || ! strncmpi (IgnoreCase, "IgnoreCase", length (IgnoreCase)))
+      error ('endsWith: third input must be "IgnoreCase"');
+    endif
+
+    if (! isscalar (ignore_case) || ! isreal (ignore_case))
+      error ('endsWith: "IgnoreCase" value must be a logical scalar');
+    endif
+    ignore_case = logical (ignore_case);
+  endif
+
+  retval = false (size (str));
+  if (ignore_case)
+    for j = 1:numel (pattern)
+      retval |= strncmpi (str, pattern{j}, length (pattern{j}));
+    endfor
+  else
+    for j = 1:numel (pattern)
+      retval |= strncmp (str, pattern{j}, length (pattern{j}));
+    endfor
+  endif
+
+endfunction
+
+
+## Test simple use with one string and one pattern
+%!assert (endsWith ("hello", "lo"))
+%!assert (! endsWith ("hello", "LO"))
+%!assert (endsWith ("hello", "LO", "i", 5))
+%!assert (! endsWith ("hello", "no"))
+
+## Test multiple strings with a single pattern
+%!test
+%! str = {"myFile.odt", "results.ppt", "myCode.m"; ...
+%!        "data-analysis.ppt", "foundations.txt", "data.odt"};
+%! pattern = ".odt";
+%! expected = [true, false, false; false, false, true];
+%! assert (endsWith (str, pattern), expected);
+
+## Test multiple strings with multiple patterns
+%!test
+%! str = {"tests.txt", "mydoc.odt", "myFunc.m", "results.pptx"};
+%! pattern = {".docx", ".odt", ".txt"};
+%! expected = [true, true, false, false];
+%! assert (endsWith (str, pattern), expected);
+
+## Test IgnoreCase
+%!test
+%! str = {"TESTS.TXT", "mydoc.odt", "result.txt", "myFunc.m"};
+%! pattern = ".txt";
+%! expected_ignore = [true, false, true, false];
+%! expected_wo_ignore = [false, false, true, false];
+%! assert (endsWith (str, pattern, "IgnoreCase", true), expected_ignore);
+%! assert (endsWith (str, pattern, "IgnoreCase", false), expected_wo_ignore);
+%! assert (endsWith (str, pattern, "I", 500), expected_ignore);
+%! assert (endsWith (str, pattern, "iG", 0), expected_wo_ignore);
+
+## Test input validation
+%!error endsWith ()
+%!error endsWith ("A")
+%!error endsWith ("A", "B", "C")
+%!error endsWith ("A", "B", "C", "D", "E")
+%!error <STR must be a string> endsWith (152, "hi")
+%!error <STR must be a .* cell array of strings> endsWith ({152}, "hi")
+%!error <PATTERN must be a string> endsWith ("hi", 152)
+%!error <PATTERN must be a .* cell array of strings> endsWith ("hi", {152})
+%!error <third input must be "IgnoreCase"> endsWith ("hello", "lo", 1, 1)
+%!error <third input must be "IgnoreCase"> endsWith ("hello", "lo", "", 1)
+%!error <third input must be "IgnoreCase"> endsWith ("hello", "lo", "foo", 1)
+%!error <"IgnoreCase" value must be a logical scalar>
+%! endsWith ("hello", "hi", "i", "true");
+%!error <"IgnoreCase" value must be a logical scalar>
+%! endsWith ("hello", "hi", "i", {true});
--- a/scripts/strings/module.mk	Tue Jul 07 18:34:23 2020 -0400
+++ b/scripts/strings/module.mk	Tue Jul 07 19:40:20 2020 -0400
@@ -9,6 +9,7 @@
   %reldir%/dec2base.m \
   %reldir%/dec2bin.m \
   %reldir%/dec2hex.m \
+  %reldir%/endsWith.m \
   %reldir%/erase.m \
   %reldir%/hex2dec.m \
   %reldir%/index.m \
@@ -20,6 +21,7 @@
   %reldir%/ostrsplit.m \
   %reldir%/regexptranslate.m \
   %reldir%/rindex.m \
+  %reldir%/startsWith.m \
   %reldir%/str2num.m \
   %reldir%/strcat.m \
   %reldir%/strchr.m \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/strings/startsWith.m	Tue Jul 07 19:40:20 2020 -0400
@@ -0,0 +1,172 @@
+########################################################################
+##
+## Copyright (C) 2020 The Octave Project Developers
+##
+## See the file COPYRIGHT.md in the top-level directory of this
+## distribution or <https://octave.org/copyright/>.
+##
+## This file is part of Octave.
+##
+## Octave is free software: you can 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
+## <https://www.gnu.org/licenses/>.
+##
+########################################################################
+
+## -*- texinfo -*-
+## @deftypefn  {} {@var{retval} =} startsWith (@var{str}, @var{pattern})
+## @deftypefnx {} {@var{retval} =} startsWith (@var{str}, @var{pattern}, "IgnoreCase", @var{ignore_case})
+## Check whether string(s) start with pattern(s).
+##
+## Return an array of logical values that indicates which string(s) in the
+## input @var{str} (a single string or cell array of strings) begin with
+## the input @var{pattern} (a single string or cell array of strings).
+##
+## If the value of the parameter @qcode{"IgnoreCase"} is true, then the
+## function will ignore the letter case of @var{str} and @var{pattern}.  By
+## default, the comparison is case sensitive.
+##
+## Examples:
+##
+## @example
+## @group
+## ## one string and one pattern while considering case
+## startsWith ("hello", "he")
+##       @result{}  1
+## @end group
+##
+## @group
+## ## one string and one pattern while ignoring case
+## startsWith ("hello", "HE", "IgnoreCase", true)
+##       @result{}  1
+## @end group
+##
+## @group
+## ## multiple strings and multiple patterns while considering case
+## startsWith (@{"lab work.pptx", "data.txt", "foundations.ppt"@},
+##             @{"lab", "data"@})
+##       @result{}  1  1  0
+## @end group
+##
+## @group
+## ## multiple strings and one pattern while considering case
+## startsWith (@{"DATASHEET.ods", "data.txt", "foundations.ppt"@},
+##             "data", "IgnoreCase", false)
+##       @result{}  0  1  0
+## @end group
+##
+## @group
+## ## multiple strings and one pattern while ignoring case
+## startsWith (@{"DATASHEET.ods", "data.txt", "foundations.ppt"@},
+##             "data", "IgnoreCase", true)
+##       @result{}  1  1  0
+## @end group
+## @end example
+##
+## @seealso{endsWith, regexp, strncmp, strncmpi}
+## @end deftypefn
+
+function retval = startsWith (str, pattern, IgnoreCase, ignore_case)
+
+  if (nargin != 2 && nargin != 4)
+    print_usage ();
+  endif
+
+  ## Validate input str and pattern
+  if (! (iscellstr (str) || ischar (str)))
+    error ("startsWith: STR must be a string or cell array of strings");
+  endif
+  if (! (iscellstr (pattern) || ischar (pattern)))
+    error ("startsWith: PATTERN must be a string or cell array of strings");
+  endif
+
+  str = cellstr (str);
+  pattern = cellstr (pattern);
+
+  if (nargin == 2)
+    ignore_case = false;
+  else
+    ## For Matlab compatibility accept any abbreviation of 3rd argument
+    if (! ischar (IgnoreCase) || isempty (IgnoreCase)
+        || ! strncmpi (IgnoreCase, "IgnoreCase", length (IgnoreCase)))
+      error ('startsWith: third input must be "IgnoreCase"');
+    endif
+
+    if (! isscalar (ignore_case) || ! isreal (ignore_case))
+      error ('startsWith: "IgnoreCase" value must be a logical scalar');
+    endif
+    ignore_case = logical (ignore_case);
+  endif
+
+  retval = false (size (str));
+  if (ignore_case)
+    for j = 1:numel (pattern)
+      retval |= strncmpi (str, pattern{j}, length (pattern{j}));
+    endfor
+  else
+    for j = 1:numel (pattern)
+      retval |= strncmp (str, pattern{j}, length (pattern{j}));
+    endfor
+  endif
+
+endfunction
+
+
+## Test simple use with one string and one pattern
+%!assert (startsWith ("hello", "he"))
+%!assert (! startsWith ("hello", "HE"))
+%!assert (startsWith ("hello", "HE", "i", 5))
+%!assert (! startsWith ("hello", "no"))
+
+## Test multiple strings with a single pattern
+%!test
+%! str = {"data science", "dataSheet.ods", "myFunc.m"; "foundations.ppt", ...
+%!        "results.txt", "myFile.odt"};
+%! pattern = "data";
+%! expected = [true, true, false; false, false, false];
+%! assert (startsWith (str, pattern), expected);
+
+## Test multiple strings with multiple patterns
+%!test
+%! str = {"lab work.pptx", "myFile.odt", "data.txt", "foundations.ppt"};
+%! pattern = {"lab", "data"};
+%! expected = [true, false, true, false];
+%! assert (startsWith (str, pattern), expected);
+
+## Test IgnoreCase
+%!test
+%! str = {"DATASHEET.ods", "myFile.odt", "data.txt", "foundations.ppt"};
+%! pattern = "data";
+%! expected_ignore = [true, false, true, false];
+%! expected_wo_ignore = [false, false, true, false];
+%! assert (startsWith (str, pattern, "IgnoreCase", true), expected_ignore);
+%! assert (startsWith (str, pattern, "IgnoreCase", false), expected_wo_ignore);
+%! assert (startsWith (str, pattern, "I", 500), expected_ignore);
+%! assert (startsWith (str, pattern, "iG", 0), expected_wo_ignore);
+
+## Test input validation
+%!error startsWith ()
+%!error startsWith ("A")
+%!error startsWith ("A", "B", "C")
+%!error startsWith ("A", "B", "C", "D", "E")
+%!error <STR must be a string> startsWith (152, "hi")
+%!error <STR must be a .* cell array of strings> startsWith ({152}, "hi")
+%!error <PATTERN must be a string> startsWith ("hi", 152)
+%!error <PATTERN must be a .* cell array of strings> startsWith ("hi", {152})
+%!error <third input must be "IgnoreCase"> startsWith ("hello", "he", 1, 1)
+%!error <third input must be "IgnoreCase"> startsWith ("hello", "he", "", 1)
+%!error <third input must be "IgnoreCase"> startsWith ("hello", "he", "foo", 1)
+%!error <"IgnoreCase" value must be a logical scalar>
+%! startsWith ("hello", "hi", "i", "true");
+%!error <"IgnoreCase" value must be a logical scalar>
+%! startsWith ("hello", "hi", "i", {true});
--- a/src/mkoctfile.in.cc	Tue Jul 07 18:34:23 2020 -0400
+++ b/src/mkoctfile.in.cc	Tue Jul 07 19:40:20 2020 -0400
@@ -61,6 +61,7 @@
 #  endif
 #else
 #  include "mkostemps-wrapper.h"
+#  include "uniconv-wrappers.h"
 #  include "unistd-wrappers.h"
 #  include "wait-wrappers.h"
 #endif
@@ -89,6 +90,14 @@
   return mkostemps (tmpl, suffixlen, 0);
 }
 
+static char *
+octave_u8_conv_to_encoding (const char *tocode, const uint8_t *src,
+                            size_t srclen, size_t *lengthp)
+{
+  // FIXME: Do we need to provide the conversion here?
+  return nullptr;
+}
+
 static int
 octave_unlink_wrapper (const char *nm)
 {
@@ -601,6 +610,32 @@
 }
 
 static std::string
+create_interleaved_complex_file (void)
+{
+  std::string tmpl = get_temp_directory () + "/oct-XXXXXX.c";
+
+  char *ctmpl = new char [tmpl.length () + 1];
+
+  ctmpl = strcpy (ctmpl, tmpl.c_str ());
+
+  // mkostemps will open the file and return a file descriptor.  We
+  // won't worry about closing it because we will need the file until we
+  // are done and then the file will be closed when mkoctfile exits.
+  int fd = octave_mkostemps_wrapper (ctmpl, 2);
+
+  // Make C++ string from filled-in template.
+  std::string retval (ctmpl);
+  delete [] ctmpl;
+
+  // Write symbol definition to file.
+  FILE *fid = fdopen (fd, "w");
+  fputs ("const int __mx_has_interleaved_complex__ = 1;\n", fid);
+  fclose (fid);
+
+  return retval;
+}
+
+static std::string
 tmp_objfile_name (void)
 {
   std::string tmpl = get_temp_directory () + "/oct-XXXXXX.o";
@@ -657,6 +692,11 @@
   bool depend = false;
   bool printonly = false;
   bool output_file_option = false;
+  bool creating_mex_file = false;
+  bool r2017b_option = false;
+  bool r2018a_option = false;
+  // The default for this may change in the future.
+  bool mx_has_interleaved_complex = false;
 
   for (int i = 1; i < argc; i++)
     {
@@ -737,6 +777,27 @@
         {
           std::cerr << "warning: -largeArrayDims and -compatibleArrayDims are accepted for compatibility, but ignored" << std::endl;
         }
+      else if (arg == "-R2017b")
+        {
+          if (r2018a_option)
+            {
+              std::cerr << "mkoctfile: only one of -R2017b and -R2018a may be used" << std::endl;
+              return 1;
+            }
+
+          r2017b_option = true;
+        }
+      else if (arg == "-R2018a")
+        {
+          if (r2017b_option)
+            {
+              std::cerr << "mkoctfile: only one of -R2017b and -R2018a may be used" << std::endl;
+              return 1;
+            }
+
+          r2018a_option = true;
+          mx_has_interleaved_complex = true;
+        }
       else if (starts_with (arg, "-Wl,") || starts_with (arg, "-l")
                || starts_with (arg, "-L") || starts_with (arg, "-R"))
         {
@@ -807,6 +868,8 @@
         }
       else if (arg == "-mex" || arg == "--mex")
         {
+          creating_mex_file = true;
+
           incflags += " -I.";
 #if defined (_MSC_VER)
           ldflags += " -Wl,-export:mexFunction";
@@ -847,10 +910,37 @@
         octfile = file;
     }
 
-  if (output_ext ==  ".mex"
-      && vars["ALL_CFLAGS"].find ("-g") != std::string::npos)
+  if (creating_mex_file)
     {
-      defs += " -DMEX_DEBUG";
+      if (vars["ALL_CFLAGS"].find ("-g") != std::string::npos)
+        defs += " -DMEX_DEBUG";
+
+      if (mx_has_interleaved_complex)
+        {
+          defs += " -DMX_HAS_INTERLEAVED_COMPLEX=1";
+
+          if (! compile_only)
+            {
+              // Create tmp C source file that defines an extern symbol
+              // that can be checked when loading the mex file to
+              // determine that the file was compiled expecting
+              // interleaved complex values.
+
+              std::string tmp_file = create_interleaved_complex_file ();
+
+              cfiles.push_back (tmp_file);
+            }
+        }
+    }
+  else
+    {
+      if (r2017b_option)
+        std::cerr << "warning: -R2017b option ignored unless creating mex file"
+                  << std::endl;
+
+      if (r2018a_option)
+        std::cerr << "warning: -R2018a option ignored unless creating mex file"
+                  << std::endl;
     }
 
   if (compile_only && output_file_option
@@ -899,8 +989,33 @@
                + vars["CPPFLAGS"] + ' ' + vars["ALL_CFLAGS"] + ' '
                + incflags  + ' ' + defs + ' ' + quote_path (f));
 
+          // FIXME: Use wide character API for popen on Windows.
           FILE *fd = popen (cmd.c_str (), "r");
+
+#if defined (OCTAVE_USE_WINDOWS_API)
+          // FIXME: liboctinterp isn't linked in to mkoctfile.
+          // So we cannot use octave::sys::ofstream. Instead we fall back
+          // on using the functions available from libwrappers.
+          size_t srclen = dfile.length ();
+          const uint8_t *src = reinterpret_cast<const uint8_t *>
+                               (dfile.c_str ());
+
+          size_t length = 0;
+          wchar_t *wchar = reinterpret_cast<wchar_t *>
+                           (octave_u8_conv_to_encoding ("wchar_t", src, srclen,
+                                                        &length));
+
+          std::ofstream fo;
+          if (wchar != nullptr)
+            {
+              fo.open (wchar);
+              free (static_cast<void *> (wchar));
+            }
+          else
+            fo.open (dfile.c_str ());
+#else
           std::ofstream fo (dfile.c_str ());
+#endif
           size_t pos;
           while (! feof (fd))
             {
@@ -933,8 +1048,33 @@
                + vars["CPPFLAGS"] + ' ' + vars["ALL_CXXFLAGS"] + ' '
                + incflags  + ' ' + defs + ' ' + quote_path (f));
 
+          // FIXME: Use wide character API for popen on Windows.
           FILE *fd = popen (cmd.c_str (), "r");
+
+#if defined (OCTAVE_USE_WINDOWS_API)
+          // FIXME: liboctinterp isn't linked in to mkoctfile.
+          // So we cannot use octave::sys::ofstream. Instead we fall back
+          // on using the functions available from libwrappers.
+          size_t srclen = dfile.length ();
+          const uint8_t *src = reinterpret_cast<const uint8_t *>
+                               (dfile.c_str ());
+
+          size_t length = 0;
+          wchar_t *wchar = reinterpret_cast<wchar_t *>
+                           (octave_u8_conv_to_encoding ("wchar_t", src, srclen,
+                                                        &length));
+
+          std::ofstream fo;
+          if (wchar != nullptr)
+            {
+              fo.open (wchar);
+              free (static_cast<void *> (wchar));
+            }
+          else
+            fo.open (dfile.c_str ());
+#else
           std::ofstream fo (dfile.c_str ());
+#endif
           size_t pos;
           while (! feof (fd))
             {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/colon-op/@legacy_colon_op/colon.m	Tue Jul 07 19:40:20 2020 -0400
@@ -0,0 +1,7 @@
+function r = colon (a, b, c)
+  if (nargin == 2)
+    r = sprintf ("%s:%s", class (a), class (b));
+  else
+    r = sprintf ("%s:%s:%s", class (a), class (b), class (c));
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/colon-op/@legacy_colon_op/legacy_colon_op.m	Tue Jul 07 19:40:20 2020 -0400
@@ -0,0 +1,3 @@
+function obj = legacy_colon_op ()
+  obj = class (struct (), "legacy_colon_op");
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/colon-op/colon-op.tst	Tue Jul 07 19:40:20 2020 -0400
@@ -0,0 +1,25 @@
+%!test
+%! x = colon_op ();
+%! assert (x:2:3, "colon_op:double:double");
+%! assert (1:x:3, "double:colon_op:double");
+%! assert (1:2:x, "double:double:colon_op");
+%! assert (x:x:3, "colon_op:colon_op:double");
+%! assert (1:x:x, "double:colon_op:colon_op");
+%! assert (x:2:x, "colon_op:double:colon_op");
+%! assert (x:x:x, "colon_op:colon_op:colon_op");
+%! assert (x:2, "colon_op:double");
+%! assert (1:x, "double:colon_op");
+%! assert (x:x, "colon_op:colon_op");
+
+%!test
+%! x = legacy_colon_op ();
+%! assert (x:2:3, "legacy_colon_op:double:double");
+%! assert (1:x:3, "double:legacy_colon_op:double");
+%! assert (1:2:x, "double:double:legacy_colon_op");
+%! assert (x:x:3, "legacy_colon_op:legacy_colon_op:double");
+%! assert (1:x:x, "double:legacy_colon_op:legacy_colon_op");
+%! assert (x:2:x, "legacy_colon_op:double:legacy_colon_op");
+%! assert (x:x:x, "legacy_colon_op:legacy_colon_op:legacy_colon_op");
+%! assert (x:2, "legacy_colon_op:double");
+%! assert (1:x, "double:legacy_colon_op");
+%! assert (x:x, "legacy_colon_op:legacy_colon_op");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/colon-op/colon_op.m	Tue Jul 07 19:40:20 2020 -0400
@@ -0,0 +1,11 @@
+classdef colon_op
+  methods
+    function r = colon (a, b, c)
+      if (nargin == 2)
+        r = sprintf ("%s:%s", class (a), class (b));
+      else
+        r = sprintf ("%s:%s:%s", class (a), class (b), class (c));
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/colon-op/module.mk	Tue Jul 07 19:40:20 2020 -0400
@@ -0,0 +1,7 @@
+colon_op_TEST_FILES = \
+  %reldir%/@legacy_colon_op/colon.m \
+  %reldir%/@legacy_colon_op/legacy_colon_op.m \
+  %reldir%/colon-op.tst \
+  %reldir%/colon_op.m
+
+TEST_FILES += $(colon_op_TEST_FILES)
--- a/test/deprecate-props.tst	Tue Jul 07 18:34:23 2020 -0400
+++ b/test/deprecate-props.tst	Tue Jul 07 19:40:20 2020 -0400
@@ -37,25 +37,3 @@
 %!    endif
 %!  endif
 %!endfunction
-
-## text/uicontrol/uipanel/uibuttongroup/uitable  "oblique" value for
-## "fontangle" property was deprecated in 5.0, remove from version 7:
-##   * remove "oblique" options in graphics.in.h, QtHandlesUtils.cc,
-##     and ft-text-renderer.cc
-##   * remove warnings from update_fontangle in graphics.in.h
-%!test
-%! hf = figure ("visible", "off");
-%! unwind_protect
-%!   ht = text ();
-%!   testprop (ht, "fontangle", "7.0", "oblique");
-%!   hui = uicontrol ();
-%!   testprop (hui, "fontangle", "7.0", "oblique");
-%!   hui = uipanel ();
-%!   testprop (hui, "fontangle", "7.0", "oblique");
-%!   hui = uibuttongroup ();
-%!   testprop (hui, "fontangle", "7.0", "oblique");
-%!   hui = uitable ();
-%!   testprop (hui, "fontangle", "7.0", "oblique");
-%! unwind_protect_cleanup
-%!   close (hf);
-%! end_unwind_protect
--- a/test/io.tst	Tue Jul 07 18:34:23 2020 -0400
+++ b/test/io.tst	Tue Jul 07 19:40:20 2020 -0400
@@ -196,7 +196,7 @@
 %! [load_status, load_files] = testls (1);
 %!
 %! for f = [save_files, load_files]
-%!   unlink (f{1});
+%!   sts = unlink (f{1});
 %! endfor
 %!
 %! assert (save_status && load_status);
@@ -228,7 +228,7 @@
 %!   assert (s64, s64t);
 %!   assert (u64, u64t);
 %! unwind_protect_cleanup
-%!   unlink (h5file);
+%!   sts = unlink (h5file);
 %! end_unwind_protect
 
 %!test
@@ -407,11 +407,11 @@
 %% Note use fprintf so output not sent to stdout
 %!test
 %! nm = tempname ();
-%! fid1 = fopen (nm,"w");
+%! fid1 = fopen (nm, "w");
 %! x = fprintf (fid1, "%s: %d\n", "test", 1);
 %! fclose (fid1);
-%! fid2 = fopen (nm,"r");
-%! str = fscanf (fid2,"%s");
+%! fid2 = fopen (nm, "r");
+%! str = fscanf (fid2, "%s");
 %! fclose (fid2);
 %! unlink (nm);
 %! assert (x, 8);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/mex/mexnumtst.c	Tue Jul 07 19:40:20 2020 -0400
@@ -0,0 +1,91 @@
+#include "mex.h"
+
+// To be called with
+//
+//   single array
+//   complex single array
+//   double array
+//   complex double array
+//
+// Will return arrays of the same type, but created internally to test
+// the mxArray -> octave_value conversion
+
+void
+mexFunction (int nlhs, mxArray *plhs[],
+             int nrhs, const mxArray *prhs[])
+{
+  if (nrhs != 4 || nlhs != 4)
+    mexErrMsgTxt ("invalid arguments");
+
+  const mxArray *sngl_ra = prhs[0];
+  const mxArray *cplx_sngl_ra = prhs[1];
+  const mxArray *dble_ra = prhs[2];
+  const mxArray *cplx_dble_ra = prhs[3];
+
+#if MX_HAS_INTERLEAVED_COMPLEX
+
+  mxSingle *sngl_data = mxGetSingles (sngl_ra);
+  size_t sngl_data_nr = mxGetM (sngl_ra);
+  size_t sngl_data_nc = mxGetN (sngl_ra);
+
+  plhs[0] = mxCreateNumericMatrix (sngl_data_nr, sngl_data_nc, mxSINGLE_CLASS, mxREAL);
+  mxSetSingles (plhs[0], sngl_data);
+
+  mxComplexSingle *cplx_sngl_data = mxGetComplexSingles (cplx_sngl_ra);
+  size_t cplx_sngl_data_nr = mxGetM (cplx_sngl_ra);
+  size_t cplx_sngl_data_nc = mxGetN (cplx_sngl_ra);
+
+  plhs[1] = mxCreateNumericMatrix (cplx_sngl_data_nr, cplx_sngl_data_nc, mxSINGLE_CLASS, mxCOMPLEX);
+  mxSetComplexSingles (plhs[1], cplx_sngl_data);
+
+  mxDouble *dble_data = mxGetDoubles (dble_ra);
+  size_t dble_data_nr = mxGetM (dble_ra);
+  size_t dble_data_nc = mxGetN (dble_ra);
+
+  plhs[2] = mxCreateNumericMatrix (dble_data_nr, dble_data_nc, mxDOUBLE_CLASS, mxREAL);
+  mxSetDoubles (plhs[2], dble_data);
+
+  mxComplexDouble *cplx_dble_data = mxGetComplexDoubles (cplx_dble_ra);
+  size_t cplx_dble_data_nr = mxGetM (cplx_dble_ra);
+  size_t cplx_dble_data_nc = mxGetN (cplx_dble_ra);
+
+  plhs[3] = mxCreateNumericMatrix (cplx_dble_data_nr, cplx_dble_data_nc, mxDOUBLE_CLASS, mxCOMPLEX);
+  mxSetComplexDoubles (plhs[3], cplx_dble_data);
+
+#else
+
+  mxSingle *sngl_data = (mxSingle *) mxGetData (sngl_ra);
+  size_t sngl_data_nr = mxGetM (sngl_ra);
+  size_t sngl_data_nc = mxGetN (sngl_ra);
+
+  mxSingle *cplx_sngl_data_real = (mxSingle *) mxGetData (cplx_sngl_ra);
+  mxSingle *cplx_sngl_data_imag = (mxSingle *) mxGetImagData (cplx_sngl_ra);
+  size_t cplx_sngl_data_nr = mxGetM (cplx_sngl_ra);
+  size_t cplx_sngl_data_nc = mxGetN (cplx_sngl_ra);
+
+  mxDouble *dble_data = (mxDouble *) mxGetData (dble_ra);
+  size_t dble_data_nr = mxGetM (dble_ra);
+  size_t dble_data_nc = mxGetN (dble_ra);
+
+  mxDouble *cplx_dble_data_real = (mxDouble *) mxGetData (cplx_dble_ra);
+  mxDouble *cplx_dble_data_imag = (mxDouble *) mxGetImagData (cplx_dble_ra);
+  size_t cplx_dble_data_nr = mxGetM (cplx_dble_ra);
+  size_t cplx_dble_data_nc = mxGetN (cplx_dble_ra);
+
+  plhs[0] = mxCreateNumericMatrix (sngl_data_nr, sngl_data_nc, mxSINGLE_CLASS, mxREAL);
+  mxSetData (plhs[0], sngl_data);
+
+  plhs[1] = mxCreateNumericMatrix (cplx_sngl_data_nr, cplx_sngl_data_nc, mxSINGLE_CLASS, mxCOMPLEX);
+  mxSetData (plhs[1], cplx_sngl_data_real);
+  mxSetImagData (plhs[1], cplx_sngl_data_imag);
+
+  plhs[2] = mxCreateNumericMatrix (dble_data_nr, dble_data_nc, mxDOUBLE_CLASS, mxREAL);
+  mxSetData (plhs[2], dble_data);
+
+  plhs[3] = mxCreateNumericMatrix (cplx_dble_data_nr, cplx_dble_data_nc, mxDOUBLE_CLASS, mxCOMPLEX);
+  mxSetData (plhs[3], cplx_dble_data_real);
+  mxSetImagData (plhs[3], cplx_dble_data_imag);
+
+#endif
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/mex/mexnumtst.tst	Tue Jul 07 19:40:20 2020 -0400
@@ -0,0 +1,11 @@
+%!test
+%! s = rand (3, 4, "single");
+%! sc = s + i * rand (3, 4, "single");
+%! d = rand (3, 4, "double");
+%! dc = d + i * rand (3, 4, "double");
+%!
+%! [sx, scx, dx, dcx] = mexnumtst (s, sc, d, dc);
+%! assert (s, sx)
+%! assert (sc, scx)
+%! assert (d, dx)
+%! assert (dc, dcx)
--- a/test/mex/module.mk	Tue Jul 07 18:34:23 2020 -0400
+++ b/test/mex/module.mk	Tue Jul 07 19:40:20 2020 -0400
@@ -1,11 +1,13 @@
 mex_TEST_FILES = \
   %reldir%/bug-54096.tst \
   %reldir%/bug-51725.tst \
+  %reldir%/mexnumtst.tst \
   $(MEX_TEST_SRC)
 
 MEX_TEST_SRC = \
   %reldir%/bug_54096.c \
-  %reldir%/bug_51725.c
+  %reldir%/bug_51725.c \
+  %reldir%/mexnumtst.c
 
 MEX_TEST_FUNCTIONS = $(MEX_TEST_SRC:%.c=%.mex)
 
--- a/test/module.mk	Tue Jul 07 18:34:23 2020 -0400
+++ b/test/module.mk	Tue Jul 07 19:40:20 2020 -0400
@@ -87,6 +87,7 @@
 include %reldir%/classdef/module.mk
 include %reldir%/classdef-multiple-inheritance/module.mk
 include %reldir%/classes/module.mk
+include %reldir%/colon-op/module.mk
 include %reldir%/ctor-vs-method/module.mk
 include %reldir%/fcn-handle/module.mk
 include %reldir%/local-functions/module.mk
--- a/test/pkg/pkg.tst	Tue Jul 07 18:34:23 2020 -0400
+++ b/test/pkg/pkg.tst	Tue Jul 07 19:40:20 2020 -0400
@@ -31,6 +31,11 @@
 
 %!shared old_prefix, old_archprefix, old_local_list, old_global_list, prefix, restorecfg, restorecache, restoreglobalcache, rmtmpdir, mfile_pkg_name, mfile_pkg_tgz
 
+%!function test_cleanup (prefix)
+%! confirm_recursive_rmdir (0, "local");
+%! sts = rmdir (prefix, "s");
+%!endfunction
+
 %!testif HAVE_Z
 %! ## Do all tests in a temporary directory
 %! [old_prefix, old_archprefix] = pkg ("prefix");
@@ -48,7 +53,7 @@
 %! pkg ("prefix", prefix, prefix);
 %! pkg ("local_list", fullfile (prefix, "octave_packages"));
 %! pkg ("global_list", fullfile (prefix, "octave_packages"));
-%! rmtmpdir = @onCleanup (@() confirm_recursive_rmdir (0, "local") && rmdir (prefix, "s"));
+%! rmtmpdir = @onCleanup (@() test_cleanup (prefix));
 %!
 %! ## Create tar.gz file packages of testing directories in prefix directory
 %! mfile_pkg_name = {"mfile_basic_test", "mfile_minimal_test"};
--- a/test/publish/publish.tst	Tue Jul 07 18:34:23 2020 -0400
+++ b/test/publish/publish.tst	Tue Jul 07 19:40:20 2020 -0400
@@ -49,7 +49,7 @@
 %!     publish (fname{1}, opts);
 %!   endfor
 %!   confirm_recursive_rmdir (false, "local");
-%!   rmdir (tmpDir, "s");
+%!   sts = rmdir (tmpDir, "s");
 %! unwind_protect_cleanup
 %!   set (0, "defaultfigurevisible", visibility);
 %!   graphics_toolkit (toolkit);
@@ -81,7 +81,7 @@
 %!   str1 = fileread ("test_script.m");
 %!   str2 = grabcode (fullfile (tmpDir, "test_script.html"));
 %!   confirm_recursive_rmdir (false, "local");
-%!   rmdir (tmpDir, "s");
+%!   sts = rmdir (tmpDir, "s");
 %!   ## Canonicalize strings
 %!   str1 = strjoin (deblank (strsplit (str1, "\n")), "\n");
 %!   str2 = strjoin (deblank (strsplit (str2, "\n")), "\n");
--- a/test/system.tst	Tue Jul 07 18:34:23 2020 -0400
+++ b/test/system.tst	Tue Jul 07 19:40:20 2020 -0400
@@ -104,7 +104,7 @@
 %!test
 %! crr = confirm_recursive_rmdir ();
 %! confirm_recursive_rmdir (0);
-%! assert (!rmdir ("foo", "s"));
+%! assert (! rmdir ("foo", "s"));
 %! confirm_recursive_rmdir (crr);
 
 %!test