changeset 33138:801e5f2f84f3 bytecode-interpreter

maint: Merge default to bytecode-interpreter
author Arun Giridhar <arungiridhar@gmail.com>
date Sun, 03 Mar 2024 20:13:08 -0500
parents 6b0f33f522ad (current diff) 0a8166b45c29 (diff)
children 980bd18d962c
files configure.ac
diffstat 35 files changed, 667 insertions(+), 406 deletions(-) [+]
line wrap: on
line diff
--- a/configure.ac	Sat Mar 02 15:36:26 2024 -0500
+++ b/configure.ac	Sun Mar 03 20:13:08 2024 -0500
@@ -302,6 +302,14 @@
 
 ### Determine which C++ compiler to use (we expect to find g++ or clang++).
 
+# AC_PROG_CXX attempts to find the compiler flags for activating support for
+# C++11.  As of autoconf version 2.71, the source code that it uses for that
+# test includes parts that are invalid in C++20.
+# We are using AX_CXX_COMPILE_STDCXX to determine the potentially needed flags
+# for the C++ version that Octave requires.  So, skip the (unnecessary and
+# broken) test for C++11 in AC_PROG_CXX by setting the following (undocumented)
+# flag:
+ac_cv_prog_cxx_cxx11=""
 AC_PROG_CXX
 AC_PROG_CXXCPP
 
@@ -2341,13 +2349,32 @@
   LIBS="$save_LIBS"
 fi
 
+### Check for SUNDIALS core library and header.
+
+if test -n "$SUNDIALS_IDA_LIBS" && test -n "$SUNDIALS_NVECSERIAL_LIBS"; then
+
+  save_CPPFLAGS="$CPPFLAGS"
+  save_LDFLAGS="$LDFLAGS"
+  save_LIBS="$LIBS"
+  LIBS="$SUNDIALS_CORE_LIBS $LIBS"
+  LDFLAGS="$SUNDIALS_CORE_LDFLAGS $LDFLAGS"
+  CPPFLAGS="$SUNDIALS_CORE_CPPFLAGS $CPPFLAGS"
+  OCTAVE_CHECK_LIB(sundials_core, [SUNDIALS core],
+    [SUNDIALS core library not found.],
+    [sundials_core.h sundials/sundials_core.h], [SUNContext_Create],
+    [], [])
+  CPPFLAGS="$save_CPPFLAGS"
+  LDFLAGS="$save_LDFLAGS"
+  LIBS="$save_LIBS"
+fi
+
 ### Check for SUNDIALS library features, some required, some optional.
 
 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"
+  CPPFLAGS="$SUNDIALS_IDA_CPPFLAGS $SUNDIALS_NVECSERIAL_CPPFLAGS $SUNDIALS_CORE_CPPFLAGS $KLU_CPPFLAGS $BLAS_CPPFLAGS $CPPFLAGS"
+  LDFLAGS="$SUNDIALS_IDA_LDFLAGS $SUNDIALS_NVECSERIAL_LDFLAGS $SUNDIALS_CORE_LDFLAGS $KLU_LDFLAGS $BLAS_LDFLAGS $LDFLAGS"
+  LIBS="$SUNDIALS_IDA_LIBS $SUNDIALS_NVECSERIAL_LIBS $SUNDIALS_CORE_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
     dnl incompatible and should be disabled.  In that event, they all populate
@@ -2359,6 +2386,7 @@
       OCTAVE_CHECK_SUNDIALS_COMPATIBLE_API
     fi
     if test -z "$warn_sundials_disabled"; then
+      OCTAVE_CHECK_SUNDIALS_SUNREALTYPE
       OCTAVE_CHECK_SUNDIALS_SIZEOF_REALTYPE
     fi
     if test -z "$warn_sundials_disabled"; then
@@ -2389,9 +2417,9 @@
     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"
+    SUNDIALS_XCPPFLAGS="$SUNDIALS_IDA_CPPFLAGS $SUNDIALS_SUNLINSOLKLU_CPPFLAGS $SUNDIALS_NVECSERIAL_CPPFLAGS $SUNDIALS_CORE_CPPFLAGS $KLU_CPPFLAGS"
+    SUNDIALS_XLDFLAGS="$SUNDIALS_IDA_LDFLAGS $SUNDIALS_SUNLINSOLKLU_LDFLAGS $SUNDIALS_NVECSERIAL_LDFLAGS $SUNDIALS_CORE_LDFLAGS $KLU_LDFLAGS"
+    SUNDIALS_XLIBS="$SUNDIALS_IDA_LIBS $SUNDIALS_SUNLINSOLKLU_LIBS $SUNDIALS_NVECSERIAL_LIBS $SUNDIALS_CORE_LIBS $KLU_LIBS"
   else
     SUNDIALS_IDA_CPPFLAGS=
     SUNDIALS_IDA_LDFLAGS=
@@ -2402,6 +2430,9 @@
     SUNDIALS_NVECSERIAL_CPPFLAGS=
     SUNDIALS_NVECSERIAL_LDFLAGS=
     SUNDIALS_NVECSERIAL_LIBS=
+    SUNDIALS_CORE_CPPFLAGS=
+    SUNDIALS_CORE_LDFLAGS=
+    SUNDIALS_CORE_LIBS=
     SUNDIALS_XCPPFLAGS=
     SUNDIALS_XLDFLAGS=
     SUNDIALS_XLIBS=
@@ -3350,6 +3381,9 @@
   SPQR LDFLAGS:                  $SPQR_LDFLAGS
   SPQR libraries:                $SPQR_LIBS
   SuiteSparse config libraries:  $SUITESPARSECONFIG_LIBS
+  SUNDIALS core CPPFLAGS:        $SUNDIALS_CORE_CPPFLAGS
+  SUNDIALS core LDFLAGS:         $SUNDIALS_CORE_LDFLAGS
+  SUNDIALS core libraries:       $SUNDIALS_CORE_LIBS
   SUNDIALS IDA CPPFLAGS:         $SUNDIALS_IDA_CPPFLAGS
   SUNDIALS IDA LDFLAGS:          $SUNDIALS_IDA_LDFLAGS
   SUNDIALS IDA libraries:        $SUNDIALS_IDA_LIBS
--- a/doc/interpreter/plot.txi	Sat Mar 02 15:36:26 2024 -0500
+++ b/doc/interpreter/plot.txi	Sun Mar 03 20:13:08 2024 -0500
@@ -299,10 +299,10 @@
 
 @DOCSTRING(axis)
 
-Similarly the axis limits of the colormap can be changed with the caxis
+Similarly the axis limits of the colormap can be changed with the @code{clim}
 function.
 
-@DOCSTRING(caxis)
+@DOCSTRING(clim)
 
 The @code{xlim}, @code{ylim}, and @code{zlim} functions may be used to
 get or set individual axis limits.  Each has the same form.
--- a/etc/NEWS.10.md	Sat Mar 02 15:36:26 2024 -0500
+++ b/etc/NEWS.10.md	Sun Mar 03 20:13:08 2024 -0500
@@ -43,6 +43,7 @@
 
 ### Alphabetical list of new functions added in Octave 10
 
+* `clim`
 * `rticklabels`
 * `tticklabels`
 
--- a/libinterp/corefcn/graphics.in.h	Sat Mar 02 15:36:26 2024 -0500
+++ b/libinterp/corefcn/graphics.in.h	Sun Mar 03 20:13:08 2024 -0500
@@ -4770,7 +4770,9 @@
     { return m_aliminclude.current_value (); }
 
     bool is_climinclude () const
-    { return (m_climinclude.is_on () && m_cdatamapping.is ("scaled")); }
+    { return (m_climinclude.is_on ()
+              && ! (m_cdatamapping.is ("direct")
+                    || m_cdata.get ().ndims () == 3)); }
     std::string get_climinclude () const
     { return m_climinclude.current_value (); }
 
@@ -5055,7 +5057,9 @@
     { return m_aliminclude.current_value (); }
 
     bool is_climinclude () const
-    { return (m_climinclude.is_on () && m_cdatamapping.is ("scaled")); }
+    { return (m_climinclude.is_on ()
+              && ! (m_cdatamapping.is ("direct")
+                    || m_cdata.get ().ndims () == 3)); }
     std::string get_climinclude () const
     { return m_climinclude.current_value (); }
 
@@ -5558,7 +5562,9 @@
     { return m_aliminclude.current_value (); }
 
     bool is_climinclude () const
-    { return (m_climinclude.is_on () && m_cdatamapping.is ("scaled")); }
+    { return (m_climinclude.is_on ()
+              && ! (m_cdatamapping.is ("direct")
+                    || m_cdata.get ().ndims () == 3)); }
     std::string get_climinclude () const
     { return m_climinclude.current_value (); }
 
--- a/libinterp/corefcn/oct-stream.cc	Sat Mar 02 15:36:26 2024 -0500
+++ b/libinterp/corefcn/oct-stream.cc	Sun Mar 03 20:13:08 2024 -0500
@@ -4390,8 +4390,6 @@
 octave_scan<>
 (std::istream& is, const scanf_format_elt& fmt, double *valptr)
 {
-  double& ref = *valptr;
-
   switch (fmt.type)
     {
     case 'e':
@@ -4401,19 +4399,24 @@
     case 'G':
       {
         is >> std::ws;  // skip through whitespace and advance stream pointer
-        if (is.good ())
+
+        std::streampos pos = is.tellg ();
+
+        double value = read_value<double> (is);
+
+        std::ios::iostate status = is.rdstate ();
+        if (! (status & std::ios::failbit))
           {
-            std::streampos pos = is.tellg ();
-
-            ref = read_value<double> (is);
-
-            std::ios::iostate status = is.rdstate ();
-            if (status & std::ios::failbit)
-              {
-                is.clear ();
-                is.seekg (pos);
-                is.setstate (status & ~std::ios_base::eofbit);
-              }
+            // Copy the converted value if the stream is in a good state
+            *valptr = value;
+          }
+        else
+          {
+            // True error.
+            // Reset stream to original position, clear eof bit, pass status on.
+            is.clear ();
+            is.seekg (pos);
+            is.setstate (status & ~std::ios_base::eofbit);
           }
       }
       break;
--- a/libinterp/dldfcn/__ode15__.cc	Sat Mar 02 15:36:26 2024 -0500
+++ b/libinterp/dldfcn/__ode15__.cc	Sun Mar 03 20:13:08 2024 -0500
@@ -121,7 +121,7 @@
 #    endif
 #  endif
 
-static inline realtype *
+static inline OCTAVE_SUNREALTYPE *
 nv_data_s (N_Vector& v)
 {
 #  if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
@@ -147,26 +147,27 @@
   typedef
   ColumnVector (*DAERHSFuncIDA) (const ColumnVector& x,
                                  const ColumnVector& xdot,
-                                 realtype t, const octave_value& idaf);
+                                 OCTAVE_SUNREALTYPE t,
+                                 const octave_value& idaf);
 
   typedef
   Matrix (*DAEJacFuncDense) (const ColumnVector& x,
-                             const ColumnVector& xdot, realtype t,
-                             realtype cj, const octave_value& idaj);
+                             const ColumnVector& xdot, OCTAVE_SUNREALTYPE t,
+                             OCTAVE_SUNREALTYPE cj, const octave_value& idaj);
 
   typedef
   SparseMatrix (*DAEJacFuncSparse) (const ColumnVector& x,
                                     const ColumnVector& xdot,
-                                    realtype t, realtype cj,
+                                    OCTAVE_SUNREALTYPE t, OCTAVE_SUNREALTYPE cj,
                                     const octave_value& idaj);
 
   typedef
   Matrix (*DAEJacCellDense) (Matrix *dfdy, Matrix *dfdyp,
-                             realtype cj);
+                             OCTAVE_SUNREALTYPE cj);
 
   typedef
   SparseMatrix (*DAEJacCellSparse) (SparseMatrix *dfdy,
-                                    SparseMatrix *dfdyp, realtype cj);
+                                    SparseMatrix *dfdyp, OCTAVE_SUNREALTYPE cj);
 
   //Default
   IDA ()
@@ -179,7 +180,7 @@
   { }
 
 
-  IDA (realtype t, ColumnVector y, ColumnVector yp,
+  IDA (OCTAVE_SUNREALTYPE t, ColumnVector y, ColumnVector yp,
        const octave_value& ida_fcn, DAERHSFuncIDA daefun)
     : m_t0 (t), m_y0 (y), m_yp0 (yp), m_havejac (false), m_havejacfcn (false),
       m_havejacsparse (false), m_mem (nullptr), m_num (), m_ida_fcn (ida_fcn),
@@ -268,21 +269,21 @@
   set_up (const ColumnVector& y);
 
   void
-  set_tolerance (ColumnVector& abstol, realtype reltol);
+  set_tolerance (ColumnVector& abstol, OCTAVE_SUNREALTYPE reltol);
 
   void
-  set_tolerance (realtype abstol, realtype reltol);
+  set_tolerance (OCTAVE_SUNREALTYPE abstol, OCTAVE_SUNREALTYPE reltol);
 
   static int
-  resfun (realtype t, N_Vector yy, N_Vector yyp,
+  resfun (OCTAVE_SUNREALTYPE t, N_Vector yy, N_Vector yyp,
           N_Vector rr, void *user_data);
 
   void
-  resfun_impl (realtype t, N_Vector& yy,
+  resfun_impl (OCTAVE_SUNREALTYPE t, N_Vector& yy,
                N_Vector& yyp, N_Vector& rr);
   static int
-  jacdense (realtype t, realtype cj, N_Vector yy, N_Vector yyp,
-            N_Vector, SUNMatrix JJ, void *user_data, N_Vector,
+  jacdense (OCTAVE_SUNREALTYPE t, OCTAVE_SUNREALTYPE cj, N_Vector yy,
+            N_Vector yyp, N_Vector, SUNMatrix JJ, void *user_data, N_Vector,
             N_Vector, N_Vector)
   {
     IDA *self = static_cast <IDA *> (user_data);
@@ -291,13 +292,13 @@
   }
 
   void
-  jacdense_impl (realtype t, realtype cj,
+  jacdense_impl (OCTAVE_SUNREALTYPE t, OCTAVE_SUNREALTYPE cj,
                  N_Vector& yy, N_Vector& yyp, SUNMatrix& JJ);
 
 #  if defined (HAVE_SUNDIALS_SUNLINSOL_KLU)
   static int
-  jacsparse (realtype t, realtype cj, N_Vector yy, N_Vector yyp,
-             N_Vector, SUNMatrix Jac, void *user_data, N_Vector,
+  jacsparse (OCTAVE_SUNREALTYPE t, OCTAVE_SUNREALTYPE cj, N_Vector yy,
+             N_Vector yyp, N_Vector, SUNMatrix Jac, void *user_data, N_Vector,
              N_Vector, N_Vector)
   {
     IDA *self = static_cast <IDA *> (user_data);
@@ -306,17 +307,17 @@
   }
 
   void
-  jacsparse_impl (realtype t, realtype cj,
+  jacsparse_impl (OCTAVE_SUNREALTYPE t, OCTAVE_SUNREALTYPE cj,
                   N_Vector& yy, N_Vector& yyp, SUNMatrix& Jac);
 #  endif
 
-  void set_maxstep (realtype maxstep);
+  void set_maxstep (OCTAVE_SUNREALTYPE maxstep);
 
-  void set_initialstep (realtype initialstep);
+  void set_initialstep (OCTAVE_SUNREALTYPE initialstep);
 
   bool
   interpolate (octave_idx_type& cont, Matrix& output, ColumnVector& tout,
-               int refine, realtype tend, bool haveoutputfcn,
+               int refine, OCTAVE_SUNREALTYPE tend, bool haveoutputfcn,
                bool haveoutputsel, const octave_value& output_fcn,
                ColumnVector& outputsel, bool haveeventfunction,
                const octave_value& event_fcn, ColumnVector& te,
@@ -327,17 +328,18 @@
 
   bool
   outputfun (const octave_value& output_fcn, bool haveoutputsel,
-             const ColumnVector& output, realtype tout, realtype tend,
-             ColumnVector& outputsel, const std::string& flag);
+             const ColumnVector& output, OCTAVE_SUNREALTYPE tout,
+             OCTAVE_SUNREALTYPE tend, ColumnVector& outputsel,
+             const std::string& flag);
 
 
   bool
   event (const octave_value& event_fcn,
          ColumnVector& te, Matrix& ye, ColumnVector& ie,
-         realtype tsol, const ColumnVector& y, const std::string& flag,
-         const ColumnVector& yp, ColumnVector& oldval,
+         OCTAVE_SUNREALTYPE tsol, const ColumnVector& y,
+         const std::string& flag, const ColumnVector& yp, ColumnVector& oldval,
          ColumnVector& oldisterminal, ColumnVector& olddir,
-         octave_idx_type cont, octave_idx_type& temp, realtype told,
+         octave_idx_type cont, octave_idx_type& temp, OCTAVE_SUNREALTYPE told,
          ColumnVector& yold,
          const octave_idx_type num_event_args);
 
@@ -356,7 +358,7 @@
 
 private:
 
-  realtype m_t0;
+  OCTAVE_SUNREALTYPE m_t0;
   ColumnVector m_y0;
   ColumnVector m_yp0;
   bool m_havejac;
@@ -383,7 +385,7 @@
 };
 
 int
-IDA::resfun (realtype t, N_Vector yy, N_Vector yyp, N_Vector rr,
+IDA::resfun (OCTAVE_SUNREALTYPE t, N_Vector yy, N_Vector yyp, N_Vector rr,
              void *user_data)
 {
   IDA *self = static_cast <IDA *> (user_data);
@@ -392,7 +394,7 @@
 }
 
 void
-IDA::resfun_impl (realtype t, N_Vector& yy,
+IDA::resfun_impl (OCTAVE_SUNREALTYPE t, N_Vector& yy,
                   N_Vector& yyp, N_Vector& rr)
 {
   ColumnVector y = IDA::NVecToCol (yy, m_num);
@@ -401,7 +403,7 @@
 
   ColumnVector res = (*m_fcn) (y, yp, t, m_ida_fcn);
 
-  realtype *puntrr = nv_data_s (rr);
+  OCTAVE_SUNREALTYPE *puntrr = nv_data_s (rr);
 
   for (octave_idx_type i = 0; i < m_num; i++)
     puntrr[i] = res(i);
@@ -476,7 +478,7 @@
 }
 
 void
-IDA::jacdense_impl (realtype t, realtype cj,
+IDA::jacdense_impl (OCTAVE_SUNREALTYPE t, OCTAVE_SUNREALTYPE cj,
                     N_Vector& yy, N_Vector& yyp, SUNMatrix& JJ)
 
 {
@@ -501,8 +503,8 @@
 
 #  if defined (HAVE_SUNDIALS_SUNLINSOL_KLU)
 void
-IDA::jacsparse_impl (realtype t, realtype cj, N_Vector& yy, N_Vector& yyp,
-                     SUNMatrix& Jac)
+IDA::jacsparse_impl (OCTAVE_SUNREALTYPE t, OCTAVE_SUNREALTYPE cj, N_Vector& yy,
+                     N_Vector& yyp, SUNMatrix& Jac)
 
 {
   ColumnVector y = NVecToCol (yy, m_num);
@@ -550,7 +552,7 @@
 IDA::NVecToCol (N_Vector& v, octave_f77_int_type n)
 {
   ColumnVector data (n);
-  realtype *punt = nv_data_s (v);
+  OCTAVE_SUNREALTYPE *punt = nv_data_s (v);
 
   for (octave_f77_int_type i = 0; i < n; i++)
     data(i) = punt[i];
@@ -563,7 +565,7 @@
 {
   N_Vector v = N_VNew_Serial (n OCTAVE_SUNCONTEXT);
 
-  realtype *punt = nv_data_s (v);
+  OCTAVE_SUNREALTYPE *punt = nv_data_s (v);
 
   for (octave_f77_int_type i = 0; i < n; i++)
     punt[i] = data(i);
@@ -585,7 +587,10 @@
 {
   m_num = to_f77_int (m_y0.numel ());
 #  if defined (HAVE_SUNDIALS_SUNCONTEXT)
-  if (SUNContext_Create (nullptr, &m_sunContext) < 0)
+#    if ! defined (SUN_COMM_NULL)
+#      define SUN_COMM_NULL nullptr
+#    endif
+  if (SUNContext_Create (SUN_COMM_NULL, &m_sunContext) < 0)
     error ("__ode15__: unable to create context for SUNDIALS");
   m_mem = IDACreate (m_sunContext);
 #  else
@@ -606,7 +611,7 @@
 }
 
 void
-IDA::set_tolerance (ColumnVector& abstol, realtype reltol)
+IDA::set_tolerance (ColumnVector& abstol, OCTAVE_SUNREALTYPE reltol)
 {
   N_Vector abs_tol = ColToNVec (abstol, m_num);
   octave::unwind_action act ([&abs_tol] () { N_VDestroy_Serial (abs_tol); });
@@ -616,7 +621,7 @@
 }
 
 void
-IDA::set_tolerance (realtype abstol, realtype reltol)
+IDA::set_tolerance (OCTAVE_SUNREALTYPE abstol, OCTAVE_SUNREALTYPE reltol)
 {
   if (IDASStolerances (m_mem, reltol, abstol) != 0)
     error ("IDA: Tolerance not set");
@@ -640,8 +645,8 @@
   std::string string = "";
   ColumnVector yold = y;
 
-  realtype tsol = tspan(0);
-  realtype tend = tspan(numt-1);
+  OCTAVE_SUNREALTYPE tsol = tspan(0);
+  OCTAVE_SUNREALTYPE tend = tspan(numt-1);
 
   N_Vector yyp = ColToNVec (yp, m_num);
   N_Vector yy = ColToNVec (y, m_num);
@@ -796,12 +801,12 @@
 
 bool
 IDA::event (const octave_value& event_fcn,
-            ColumnVector& te, Matrix& ye, ColumnVector& ie, realtype tsol,
-            const ColumnVector& y, const std::string& flag,
-            const ColumnVector& yp, ColumnVector& oldval,
-            ColumnVector& oldisterminal, ColumnVector& olddir,
-            octave_idx_type cont, octave_idx_type& temp, realtype told,
-            ColumnVector& yold,
+            ColumnVector& te, Matrix& ye, ColumnVector& ie,
+            OCTAVE_SUNREALTYPE tsol, const ColumnVector& y,
+            const std::string& flag, const ColumnVector& yp,
+            ColumnVector& oldval, ColumnVector& oldisterminal,
+            ColumnVector& olddir, octave_idx_type cont, octave_idx_type& temp,
+            OCTAVE_SUNREALTYPE told, ColumnVector& yold,
             const octave_idx_type num_event_args)
 {
   bool status = false;
@@ -911,7 +916,7 @@
 
 bool
 IDA::interpolate (octave_idx_type& cont, Matrix& output, ColumnVector& tout,
-                  int refine, realtype tend, bool haveoutputfcn,
+                  int refine, OCTAVE_SUNREALTYPE tend, bool haveoutputfcn,
                   bool haveoutputsel, const octave_value& output_fcn,
                   ColumnVector& outputsel, bool haveeventfunction,
                   const octave_value& event_fcn, ColumnVector& te,
@@ -920,7 +925,7 @@
                   octave_idx_type& temp, ColumnVector& yold,
                   const octave_idx_type num_event_args)
 {
-  realtype h = 0, tcur = 0;
+  OCTAVE_SUNREALTYPE h = 0, tcur = 0;
   bool status = false;
 
   N_Vector dky = N_VNew_Serial (m_num OCTAVE_SUNCONTEXT);
@@ -940,9 +945,9 @@
   if (IDAGetCurrentTime (m_mem, &tcur) != 0)
     error ("IDA failed to return the current time");
 
-  realtype tin = tcur - h;
+  OCTAVE_SUNREALTYPE tin = tcur - h;
 
-  realtype step = h / refine;
+  OCTAVE_SUNREALTYPE step = h / refine;
 
   for (octave_idx_type i = 1;
        i < refine && tin + step * i < tend && status == 0;
@@ -981,8 +986,8 @@
 
 bool
 IDA::outputfun (const octave_value& output_fcn, bool haveoutputsel,
-                const ColumnVector& yout, realtype tsol,
-                realtype tend, ColumnVector& outputsel,
+                const ColumnVector& yout, OCTAVE_SUNREALTYPE tsol,
+                OCTAVE_SUNREALTYPE tend, ColumnVector& outputsel,
                 const std::string& flag)
 {
   bool status = false;
@@ -1029,14 +1034,14 @@
 }
 
 void
-IDA::set_maxstep (realtype maxstep)
+IDA::set_maxstep (OCTAVE_SUNREALTYPE maxstep)
 {
   if (IDASetMaxStep (m_mem, maxstep) != 0)
     error ("IDA: Max Step not set");
 }
 
 void
-IDA::set_initialstep (realtype initialstep)
+IDA::set_initialstep (OCTAVE_SUNREALTYPE initialstep)
 {
   if (IDASetInitStep (m_mem, initialstep) != 0)
     error ("IDA: Initial Step not set");
@@ -1148,7 +1153,7 @@
 do_ode15 (const octave_value& ida_fcn,
           const ColumnVector& tspan,
           const octave_idx_type numt,
-          const realtype t0,
+          const OCTAVE_SUNREALTYPE t0,
           const ColumnVector& y0,
           const ColumnVector& yp0,
           const octave_scalar_map& options,
@@ -1206,7 +1211,7 @@
   dae.initialize ();
 
   // Set tolerances
-  realtype rel_tol = options.getfield ("RelTol").double_value ();
+  OCTAVE_SUNREALTYPE rel_tol = options.getfield ("RelTol").double_value ();
 
   bool haveabstolvec = options.getfield ("haveabstolvec").bool_value ();
 
@@ -1218,20 +1223,20 @@
     }
   else
     {
-      realtype abs_tol = options.getfield ("AbsTol").double_value ();
+      OCTAVE_SUNREALTYPE abs_tol = options.getfield ("AbsTol").double_value ();
 
       dae.set_tolerance (abs_tol, rel_tol);
     }
 
   //Set max step
-  realtype maxstep = options.getfield ("MaxStep").double_value ();
+  OCTAVE_SUNREALTYPE maxstep = options.getfield ("MaxStep").double_value ();
 
   dae.set_maxstep (maxstep);
 
   //Set initial step
   if (! options.getfield ("InitialStep").isempty ())
     {
-      realtype initialstep = options.getfield ("InitialStep").double_value ();
+      OCTAVE_SUNREALTYPE initialstep = options.getfield ("InitialStep").double_value ();
 
       dae.set_initialstep (initialstep);
     }
@@ -1316,7 +1321,7 @@
 
   octave_idx_type numt = tspan.numel ();
 
-  realtype t0 = tspan(0);
+  OCTAVE_SUNREALTYPE t0 = tspan(0);
 
   if (numt < 2)
     error ("__ode15__: TRANGE must contain at least 2 elements");
--- a/m4/acinclude.m4	Sat Mar 02 15:36:26 2024 -0500
+++ b/m4/acinclude.m4	Sun Mar 03 20:13:08 2024 -0500
@@ -2333,6 +2333,31 @@
   fi
 ])
 dnl
+dnl Check whether SUNDIALS IDA uses sunrealtype.
+dnl
+AC_DEFUN([OCTAVE_CHECK_SUNDIALS_SUNREALTYPE], [
+  AC_CACHE_CHECK([whether SUNDIALS IDA uses sunrealtype],
+    [octave_cv_sundials_has_sunrealtype],
+    [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+        #if defined (HAVE_IDA_IDA_H)
+        #  include <ida/ida.h>
+        #endif
+        ]], [[
+        sunrealtype test;
+      ]])],
+      octave_cv_sundials_has_sunrealtype=yes,
+      octave_cv_sundials_has_sunrealtype=no)
+  ])
+  if test $octave_cv_sundials_has_sunrealtype = no; then
+    OCTAVE_SUNREALTYPE=realtype
+  else
+    OCTAVE_SUNREALTYPE=sunrealtype
+  fi
+  AC_SUBST(OCTAVE_SUNREALTYPE)
+  AC_DEFINE_UNQUOTED(OCTAVE_SUNREALTYPE, [$OCTAVE_SUNREALTYPE],
+    [Define to the type used for real numbers by SUNDIALS.])
+])
+dnl
 dnl Check whether SUNDIALS IDA library is configured with double
 dnl precision realtype.
 dnl
@@ -2345,7 +2370,7 @@
         #endif
         #include <assert.h>
         ]], [[
-        static_assert (sizeof (realtype) == sizeof (double),
+        static_assert (sizeof (OCTAVE_SUNREALTYPE) == sizeof (double),
                        "SUNDIALS is not configured for double precision");
       ]])],
       octave_cv_sundials_realtype_is_double=yes,
--- a/scripts/image/image.m	Sat Mar 02 15:36:26 2024 -0500
+++ b/scripts/image/image.m	Sun Mar 03 20:13:08 2024 -0500
@@ -186,15 +186,6 @@
       if (isempty (get (hax, "children")))
         axis (hax, "tight");
       endif
-
-      if (ndims (img) == 3)
-        if (isinteger (img))
-          mn = intmin (img);
-          mx = intmax (img);
-          set (hax, "clim", double ([mn, mx]));
-        endif
-      endif
-
     endif  # ! isempty (img)
 
     set (hax, "view", [0, 90], "ydir", "reverse", "layer", "top", "box", "on");
--- a/scripts/image/imagesc.m	Sat Mar 02 15:36:26 2024 -0500
+++ b/scripts/image/imagesc.m	Sun Mar 03 20:13:08 2024 -0500
@@ -55,7 +55,7 @@
 ## and inserts it in the current axes.  The full list of properties is
 ## documented at @ref{Image Properties}.
 ##
-## @seealso{image, imshow, caxis}
+## @seealso{image, imshow, clim}
 ## @end deftypefn
 
 function h = imagesc (varargin)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/legacy/caxis.m	Sun Mar 03 20:13:08 2024 -0500
@@ -0,0 +1,133 @@
+########################################################################
+##
+## Copyright (C) 2007-2024 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  {} {} caxis ([cmin cmax])
+## @deftypefnx {} {} caxis ("auto")
+## @deftypefnx {} {} caxis ("manual")
+## @deftypefnx {} {} caxis (@var{hax}, @dots{})
+## @deftypefnx {} {@var{limits} =} caxis ()
+##
+## This function is not recommended.  Use @code{clim} instead.
+##
+## Query or set color axis limits for plots.
+##
+## The limits argument should be a 2-element vector specifying the lower and
+## upper limits to assign to the first and last value in the colormap.  Data
+## values outside this range are clamped to the first and last colormap
+## entries.
+##
+## If the @qcode{"auto"} option is given then automatic colormap limits are
+## applied.  The automatic algorithm sets @var{cmin} to the minimum data value
+## and @var{cmax} to the maximum data value.  If @qcode{"manual"} is specified
+## then the @qcode{"climmode"} property is set to @qcode{"manual"} and the
+## numeric values in the @qcode{"clim"} property are used for limits.
+##
+## If the first argument @var{hax} is an axes handle, then operate on
+## this axes rather than the current axes returned by @code{gca}.
+##
+## Called without arguments the current color axis limits are returned.
+##
+## Programming Note: The color axis affects the display of image, patch, and
+## surface graphics objects, but @strong{only} if the @qcode{"cdata"} property
+## has indexed data and the @qcode{"cdatamapping"} property is set to
+## @qcode{"scaled"}.  Graphic objects with true color @code{cdata}, or
+## @qcode{"direct"} @code{cdatamapping} are not affected.
+## @seealso{clim, colormap, axis}
+## @end deftypefn
+
+function limits = caxis (varargin)
+
+  [hax, varargin, nargin] = __plt_get_axis_arg__ ("caxis", varargin{:});
+
+  if (nargin > 1)
+    print_usage ();
+  endif
+
+  oldfig = [];
+  if (! isempty (hax))
+    oldfig = get (0, "currentfigure");
+  endif
+  unwind_protect
+    if (isempty (hax))
+      hax = gca ();
+    endif
+    if (nargin == 0)
+      limits = get (hax, "clim");
+    else
+      arg1 = varargin{1};
+      if (ischar (arg1))
+        if (strcmpi (arg1, "auto"))
+          set (hax, "climmode", "auto");
+        elseif (strcmpi (arg1, "manual"))
+          set (hax, "climmode", "manual");
+        else
+          error ("caxis: invalid mode '%s'", arg1);
+        endif
+      elseif (isvector (arg1))
+        if (numel (arg1) != 2 || ! isnumeric (arg1) || arg1(1) >= arg1(2))
+          error ("caxis: LIMITS must be a numeric 2-element vector where LIM1 < LIM2");
+        endif
+        set (hax, "clim", arg1);
+      else
+        print_usage ();
+      endif
+    endif
+  unwind_protect_cleanup
+    if (! isempty (oldfig))
+      set (0, "currentfigure", oldfig);
+    endif
+  end_unwind_protect
+
+endfunction
+
+
+%!test
+%! hf = figure ("visible", "off");
+%! hax = gca ();
+%! unwind_protect
+%!   caxis ([e, pi]);
+%!   assert (caxis (), [e, pi]);
+%!   caxis (hax, [-1, 1]);
+%!   assert (caxis (hax), [-1, 1]);
+%!   assert (get (hax, "climmode"), "manual");
+%!   caxis ("auto");
+%!   assert (get (hax, "climmode"), "auto");
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+## Test input validation
+%!error caxis (1,2,3)
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   fail ("caxis ('foo')", "invalid mode 'foo'");
+%!   fail ("caxis ([1 2 3])", "2-element vector");
+%!   fail ("caxis ({1 2 3})", "numeric 2-element vector");
+%!   fail ("caxis ([1 0])", "LIM1 < LIM2");
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
--- a/scripts/legacy/module.mk	Sat Mar 02 15:36:26 2024 -0500
+++ b/scripts/legacy/module.mk	Sun Mar 03 20:13:08 2024 -0500
@@ -3,6 +3,7 @@
 %canon_reldir%_FCN_FILES = \
   %reldir%/.oct-config \
   %reldir%/__vectorize__.m \
+  %reldir%/caxis.m \
   %reldir%/findstr.m \
   %reldir%/flipdim.m \
   %reldir%/genvarname.m \
--- a/scripts/plot/appearance/axis.m	Sat Mar 02 15:36:26 2024 -0500
+++ b/scripts/plot/appearance/axis.m	Sun Mar 03 20:13:08 2024 -0500
@@ -158,7 +158,7 @@
 ## axis ("tic", "labely");
 ## @end example
 ##
-## @seealso{xlim, ylim, zlim, caxis, daspect, pbaspect, box, grid}
+## @seealso{xlim, ylim, zlim, clim, daspect, pbaspect, box, grid}
 ## @end deftypefn
 
 function limits = axis (varargin)
@@ -390,7 +390,7 @@
       endif
 
       if (len > 7)
-        caxis (ca, opt(7:8));
+        clim (ca, opt(7:8));
       endif
 
     else
--- a/scripts/plot/appearance/caxis.m	Sat Mar 02 15:36:26 2024 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,130 +0,0 @@
-########################################################################
-##
-## Copyright (C) 2007-2024 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  {} {} caxis ([cmin cmax])
-## @deftypefnx {} {} caxis ("auto")
-## @deftypefnx {} {} caxis ("manual")
-## @deftypefnx {} {} caxis (@var{hax}, @dots{})
-## @deftypefnx {} {@var{limits} =} caxis ()
-## Query or set color axis limits for plots.
-##
-## The limits argument should be a 2-element vector specifying the lower and
-## upper limits to assign to the first and last value in the colormap.  Data
-## values outside this range are clamped to the first and last colormap
-## entries.
-##
-## If the @qcode{"auto"} option is given then automatic colormap limits are
-## applied.  The automatic algorithm sets @var{cmin} to the minimum data value
-## and @var{cmax} to the maximum data value.  If @qcode{"manual"} is specified
-## then the @qcode{"climmode"} property is set to @qcode{"manual"} and the
-## numeric values in the @qcode{"clim"} property are used for limits.
-##
-## If the first argument @var{hax} is an axes handle, then operate on
-## this axes rather than the current axes returned by @code{gca}.
-##
-## Called without arguments the current color axis limits are returned.
-##
-## Programming Note: The color axis affects the display of image, patch, and
-## surface graphics objects, but @strong{only} if the @qcode{"cdata"} property
-## has indexed data and the @qcode{"cdatamapping"} property is set to
-## @qcode{"scaled"}.  Graphic objects with true color @code{cdata}, or
-## @qcode{"direct"} @code{cdatamapping} are not affected.
-## @seealso{colormap, axis}
-## @end deftypefn
-
-function limits = caxis (varargin)
-
-  [hax, varargin, nargin] = __plt_get_axis_arg__ ("caxis", varargin{:});
-
-  if (nargin > 1)
-    print_usage ();
-  endif
-
-  oldfig = [];
-  if (! isempty (hax))
-    oldfig = get (0, "currentfigure");
-  endif
-  unwind_protect
-    if (isempty (hax))
-      hax = gca ();
-    endif
-    if (nargin == 0)
-      limits = get (hax, "clim");
-    else
-      arg1 = varargin{1};
-      if (ischar (arg1))
-        if (strcmpi (arg1, "auto"))
-          set (hax, "climmode", "auto");
-        elseif (strcmpi (arg1, "manual"))
-          set (hax, "climmode", "manual");
-        else
-          error ("caxis: invalid mode '%s'", arg1);
-        endif
-      elseif (isvector (arg1))
-        if (numel (arg1) != 2 || ! isnumeric (arg1) || arg1(1) >= arg1(2))
-          error ("caxis: LIMITS must be a numeric 2-element vector where LIM1 < LIM2");
-        endif
-        set (hax, "clim", arg1);
-      else
-        print_usage ();
-      endif
-    endif
-  unwind_protect_cleanup
-    if (! isempty (oldfig))
-      set (0, "currentfigure", oldfig);
-    endif
-  end_unwind_protect
-
-endfunction
-
-
-%!test
-%! hf = figure ("visible", "off");
-%! hax = gca ();
-%! unwind_protect
-%!   caxis ([e, pi]);
-%!   assert (caxis (), [e, pi]);
-%!   caxis (hax, [-1, 1]);
-%!   assert (caxis (hax), [-1, 1]);
-%!   assert (get (hax, "climmode"), "manual");
-%!   caxis ("auto");
-%!   assert (get (hax, "climmode"), "auto");
-%! unwind_protect_cleanup
-%!   close (hf);
-%! end_unwind_protect
-
-## Test input validation
-%!error caxis (1,2,3)
-%!test
-%! hf = figure ("visible", "off");
-%! unwind_protect
-%!   fail ("caxis ('foo')", "invalid mode 'foo'");
-%!   fail ("caxis ([1 2 3])", "2-element vector");
-%!   fail ("caxis ({1 2 3})", "numeric 2-element vector");
-%!   fail ("caxis ([1 0])", "LIM1 < LIM2");
-%! unwind_protect_cleanup
-%!   close (hf);
-%! end_unwind_protect
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/appearance/clim.m	Sun Mar 03 20:13:08 2024 -0500
@@ -0,0 +1,130 @@
+########################################################################
+##
+## Copyright (C) 2024 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  {} {} clim ([cmin cmax])
+## @deftypefnx {} {} clim ("auto")
+## @deftypefnx {} {} clim ("manual")
+## @deftypefnx {} {} clim (@var{hax}, @dots{})
+## @deftypefnx {} {@var{limits} =} clim ()
+## Query or set color axis limits for plots.
+##
+## The limits argument should be a 2-element vector specifying the lower and
+## upper limits to assign to the first and last value in the colormap.  Data
+## values outside this range are clamped to the first and last colormap
+## entries.
+##
+## If the @qcode{"auto"} option is given then automatic colormap limits are
+## applied.  The automatic algorithm sets @var{cmin} to the minimum data value
+## and @var{cmax} to the maximum data value.  If @qcode{"manual"} is specified
+## then the @qcode{"climmode"} property is set to @qcode{"manual"} and the
+## numeric values in the @qcode{"clim"} property are used for limits.
+##
+## If the first argument @var{hax} is an axes handle, then operate on
+## this axes rather than the current axes returned by @code{gca}.
+##
+## Called without arguments the current color axis limits are returned.
+##
+## Programming Note: The color axis affects the display of image, patch, and
+## surface graphics objects, but @strong{only} if the @qcode{"cdata"} property
+## has indexed data and the @qcode{"cdatamapping"} property is set to
+## @qcode{"scaled"}.  Graphic objects with true color @code{cdata}, or
+## @qcode{"direct"} @code{cdatamapping} are not affected.
+## @seealso{colormap, axis}
+## @end deftypefn
+
+function limits = clim (varargin)
+
+  [hax, varargin, nargin] = __plt_get_axis_arg__ ("clim", varargin{:});
+
+  if (nargin > 1)
+    print_usage ();
+  endif
+
+  oldfig = [];
+  if (! isempty (hax))
+    oldfig = get (0, "currentfigure");
+  endif
+  unwind_protect
+    if (isempty (hax))
+      hax = gca ();
+    endif
+    if (nargin == 0)
+      limits = get (hax, "clim");
+    else
+      arg1 = varargin{1};
+      if (ischar (arg1))
+        if (strcmpi (arg1, "auto"))
+          set (hax, "climmode", "auto");
+        elseif (strcmpi (arg1, "manual"))
+          set (hax, "climmode", "manual");
+        else
+          error ("clim: invalid mode '%s'", arg1);
+        endif
+      elseif (isvector (arg1))
+        if (numel (arg1) != 2 || ! isnumeric (arg1) || arg1(1) >= arg1(2))
+          error ("clim: LIMITS must be a numeric 2-element vector where LIM1 < LIM2");
+        endif
+        set (hax, "clim", arg1);
+      else
+        print_usage ();
+      endif
+    endif
+  unwind_protect_cleanup
+    if (! isempty (oldfig))
+      set (0, "currentfigure", oldfig);
+    endif
+  end_unwind_protect
+
+endfunction
+
+
+%!test
+%! hf = figure ("visible", "off");
+%! hax = gca ();
+%! unwind_protect
+%!   clim ([e, pi]);
+%!   assert (clim (), [e, pi]);
+%!   clim (hax, [-1, 1]);
+%!   assert (clim (hax), [-1, 1]);
+%!   assert (get (hax, "climmode"), "manual");
+%!   clim ("auto");
+%!   assert (get (hax, "climmode"), "auto");
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+## Test input validation
+%!error clim (1,2,3)
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   fail ("clim ('foo')", "invalid mode 'foo'");
+%!   fail ("clim ([1 2 3])", "2-element vector");
+%!   fail ("clim ({1 2 3})", "numeric 2-element vector");
+%!   fail ("clim ([1 0])", "LIM1 < LIM2");
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
--- a/scripts/plot/appearance/module.mk	Sat Mar 02 15:36:26 2024 -0500
+++ b/scripts/plot/appearance/module.mk	Sun Mar 03 20:13:08 2024 -0500
@@ -24,8 +24,8 @@
   %reldir%/camup.m \
   %reldir%/camva.m \
   %reldir%/camzoom.m \
-  %reldir%/caxis.m \
   %reldir%/clabel.m \
+  %reldir%/clim.m \
   %reldir%/daspect.m \
   %reldir%/datetick.m \
   %reldir%/diffuse.m \
--- a/scripts/plot/appearance/text.m	Sat Mar 02 15:36:26 2024 -0500
+++ b/scripts/plot/appearance/text.m	Sun Mar 03 20:13:08 2024 -0500
@@ -280,7 +280,7 @@
 %!                    "edgecolor", "k", ...
 %!                    "verticalalignment", "bottom");
 %! endfor
-%! caxis ([-100 100]);
+%! clim ([-100 100]);
 %! title ("Vertically Aligned at Bottom");
 
 %!demo
--- a/scripts/plot/draw/contour.m	Sat Mar 02 15:36:26 2024 -0500
+++ b/scripts/plot/draw/contour.m	Sun Mar 03 20:13:08 2024 -0500
@@ -62,7 +62,7 @@
 ## @end example
 ##
 ## @seealso{ezcontour, contourc, contourf, contour3, clabel, meshc, surfc,
-## caxis, colormap, plot}
+## clim, colormap, plot}
 ##
 ## @end deftypefn
 
--- a/scripts/plot/draw/contour3.m	Sat Mar 02 15:36:26 2024 -0500
+++ b/scripts/plot/draw/contour3.m	Sun Mar 03 20:13:08 2024 -0500
@@ -66,7 +66,7 @@
 ## @end group
 ## @end example
 ##
-## @seealso{contour, contourc, contourf, clabel, meshc, surfc, caxis, colormap,
+## @seealso{contour, contourc, contourf, clabel, meshc, surfc, clim, colormap,
 ## plot}
 ## @end deftypefn
 
--- a/scripts/plot/draw/contourf.m	Sat Mar 02 15:36:26 2024 -0500
+++ b/scripts/plot/draw/contourf.m	Sun Mar 03 20:13:08 2024 -0500
@@ -62,7 +62,7 @@
 ## @end group
 ## @end example
 ## @seealso{ezcontourf, contour, contourc, contour3, clabel, meshc, surfc,
-## caxis, colormap, plot}
+## clim, colormap, plot}
 ## @end deftypefn
 
 function [c, h] = contourf (varargin)
--- a/scripts/plot/draw/fill.m	Sat Mar 02 15:36:26 2024 -0500
+++ b/scripts/plot/draw/fill.m	Sun Mar 03 20:13:08 2024 -0500
@@ -40,7 +40,7 @@
 ## is a single color specification such as a @code{plot} format or an
 ## RGB-triple.  In this case the polygon(s) will have one unique color.  If
 ## @var{c} is a vector or matrix then the color data is first scaled using
-## @code{caxis} and then indexed into the current colormap.  A row vector will
+## @code{clim} and then indexed into the current colormap.  A row vector will
 ## color each polygon (a column from matrices @var{x} and @var{y}) with a
 ## single computed color.  A matrix @var{c} of the same size as @var{x} and
 ## @var{y} will compute the color of each vertex and then interpolate the face
@@ -70,7 +70,7 @@
 ## @end group
 ## @end example
 ##
-## @seealso{patch, fill3, caxis, colormap}
+## @seealso{patch, fill3, clim, colormap}
 ## @end deftypefn
 
 function h = fill (varargin)
--- a/scripts/plot/draw/fill3.m	Sat Mar 02 15:36:26 2024 -0500
+++ b/scripts/plot/draw/fill3.m	Sun Mar 03 20:13:08 2024 -0500
@@ -40,7 +40,7 @@
 ## is a single color specification such as a @code{plot} format or an
 ## RGB-triple.  In this case the polygon(s) will have one unique color.  If
 ## @var{c} is a vector or matrix then the color data is first scaled using
-## @code{caxis} and then indexed into the current colormap.  A row vector will
+## @code{clim} and then indexed into the current colormap.  A row vector will
 ## color each polygon (a column from matrices @var{x}, @var{y}, and @var{z})
 ## with a single computed color.  A matrix @var{c} of the same size as @var{x},
 ## @var{y}, and @var{z} will compute the color of each vertex and then
@@ -72,7 +72,7 @@
 ## @end group
 ## @end example
 ##
-## @seealso{patch, fill, caxis, colormap}
+## @seealso{patch, fill, clim, colormap}
 ## @end deftypefn
 
 function h = fill3 (varargin)
--- a/scripts/plot/draw/mesh.m	Sat Mar 02 15:36:26 2024 -0500
+++ b/scripts/plot/draw/mesh.m	Sun Mar 03 20:13:08 2024 -0500
@@ -42,7 +42,7 @@
 ## of @var{z} correspond to different @var{y} values.
 ##
 ## The color of the mesh is computed by linearly scaling the @var{z} values
-## to fit the range of the current colormap.  Use @code{caxis} and/or
+## to fit the range of the current colormap.  Use @code{clim} and/or
 ## change the colormap to control the appearance.
 ##
 ## Optionally, the color of the mesh can be specified independently of @var{z}
@@ -59,7 +59,7 @@
 ## surface object.
 ##
 ## @seealso{ezmesh, meshc, meshz, trimesh, contour, surf, surface, meshgrid,
-## hidden, shading, colormap, caxis}
+## hidden, shading, colormap, clim}
 ## @end deftypefn
 
 function h = mesh (varargin)
--- a/scripts/plot/draw/meshc.m	Sat Mar 02 15:36:26 2024 -0500
+++ b/scripts/plot/draw/meshc.m	Sun Mar 03 20:13:08 2024 -0500
@@ -42,7 +42,7 @@
 ## of @var{z} correspond to different @var{y} values.
 ##
 ## The color of the mesh is computed by linearly scaling the @var{z} values
-## to fit the range of the current colormap.  Use @code{caxis} and/or
+## to fit the range of the current colormap.  Use @code{clim} and/or
 ## change the colormap to control the appearance.
 ##
 ## Optionally the color of the mesh can be specified independently of @var{z}
@@ -59,7 +59,7 @@
 ## handle to the created surface object and to the created contour plot.
 ##
 ## @seealso{ezmeshc, mesh, meshz, contour, surfc, surface, meshgrid, hidden,
-## shading, colormap, caxis}
+## shading, colormap, clim}
 ## @end deftypefn
 
 function h = meshc (varargin)
--- a/scripts/plot/draw/meshz.m	Sat Mar 02 15:36:26 2024 -0500
+++ b/scripts/plot/draw/meshz.m	Sun Mar 03 20:13:08 2024 -0500
@@ -42,7 +42,7 @@
 ## of @var{z} correspond to different @var{y} values.
 ##
 ## The color of the mesh is computed by linearly scaling the @var{z} values
-## to fit the range of the current colormap.  Use @code{caxis} and/or
+## to fit the range of the current colormap.  Use @code{clim} and/or
 ## change the colormap to control the appearance.
 ##
 ## Optionally the color of the mesh can be specified independently of @var{z}
@@ -59,7 +59,7 @@
 ## surface object.
 ##
 ## @seealso{mesh, meshc, contour, surf, surface, waterfall, meshgrid, hidden,
-## shading, colormap, caxis}
+## shading, colormap, clim}
 ## @end deftypefn
 
 function h = meshz (varargin)
--- a/scripts/plot/draw/patch.m	Sat Mar 02 15:36:26 2024 -0500
+++ b/scripts/plot/draw/patch.m	Sun Mar 03 20:13:08 2024 -0500
@@ -42,11 +42,11 @@
 ##
 ## The color argument @var{c} can take many forms.  To create polygons
 ## which all share a single color use a string value (e.g., @qcode{"r"} for
-## red), a scalar value which is scaled by @code{caxis} and indexed into the
+## red), a scalar value which is scaled by @code{clim} and indexed into the
 ## current colormap, or a 3-element RGB vector with the precise TrueColor.
 ##
 ## If @var{c} is a vector of length N then the ith polygon will have a color
-## determined by scaling entry @var{c}(i) according to @code{caxis} and then
+## determined by scaling entry @var{c}(i) according to @code{clim} and then
 ## indexing into the current colormap.  More complicated coloring situations
 ## require directly manipulating patch property/value pairs.
 ##
--- a/scripts/plot/draw/pcolor.m	Sat Mar 02 15:36:26 2024 -0500
+++ b/scripts/plot/draw/pcolor.m	Sun Mar 03 20:13:08 2024 -0500
@@ -40,7 +40,7 @@
 ##
 ## The values in @var{c} are scaled to span the range of the current
 ## colormap.  Limits may be placed on the color axis by the command
-## @code{caxis}, or by setting the @code{clim} property of the parent axis.
+## @code{clim}, or by setting the @code{clim} property of the parent axis.
 ##
 ## The face color of each cell of the mesh is determined by interpolating
 ## the values of @var{c} for each of the cell's vertices; Contrast this with
@@ -58,7 +58,7 @@
 ## The optional return value @var{h} is a graphics handle to the created
 ## surface object.
 ##
-## @seealso{caxis, shading, meshgrid, contour, imagesc}
+## @seealso{clim, shading, meshgrid, contour, imagesc}
 ## @end deftypefn
 
 function h = pcolor (varargin)
--- a/scripts/plot/draw/surf.m	Sat Mar 02 15:36:26 2024 -0500
+++ b/scripts/plot/draw/surf.m	Sun Mar 03 20:13:08 2024 -0500
@@ -42,7 +42,7 @@
 ## of @var{z} correspond to different @var{y} values.
 ##
 ## The color of the surface is computed by linearly scaling the @var{z} values
-## to fit the range of the current colormap.  Use @code{caxis} and/or
+## to fit the range of the current colormap.  Use @code{clim} and/or
 ## change the colormap to control the appearance.
 ##
 ## Optionally, the color of the surface can be specified independently of
@@ -62,7 +62,7 @@
 ## @code{shading} command or by using @code{set} to control surface object
 ## properties.
 ## @seealso{ezsurf, surfc, surfl, surfnorm, trisurf, contour, mesh, surface,
-## meshgrid, hidden, shading, colormap, caxis}
+## meshgrid, hidden, shading, colormap, clim}
 ## @end deftypefn
 
 function h = surf (varargin)
--- a/scripts/plot/draw/surfc.m	Sat Mar 02 15:36:26 2024 -0500
+++ b/scripts/plot/draw/surfc.m	Sun Mar 03 20:13:08 2024 -0500
@@ -42,7 +42,7 @@
 ## of @var{z} correspond to different @var{y} values.
 ##
 ## The color of the surface is computed by linearly scaling the @var{z} values
-## to fit the range of the current colormap.  Use @code{caxis} and/or
+## to fit the range of the current colormap.  Use @code{clim} and/or
 ## change the colormap to control the appearance.
 ##
 ## Optionally, the color of the surface can be specified independently of
@@ -62,7 +62,7 @@
 ## @code{shading} command or by using @code{set} to control surface object
 ## properties.
 ## @seealso{ezsurfc, surf, surfl, surfnorm, trisurf, contour, mesh, surface,
-## meshgrid, hidden, shading, colormap, caxis}
+## meshgrid, hidden, shading, colormap, clim}
 ## @end deftypefn
 
 function h = surfc (varargin)
--- a/scripts/plot/draw/surfl.m	Sat Mar 02 15:36:26 2024 -0500
+++ b/scripts/plot/draw/surfl.m	Sun Mar 03 20:13:08 2024 -0500
@@ -83,7 +83,7 @@
 ## shading interp;
 ## @end group
 ## @end example
-## @seealso{diffuse, specular, surf, shading, colormap, caxis}
+## @seealso{diffuse, specular, surf, shading, colormap, clim}
 ## @end deftypefn
 
 function h = surfl (varargin)
--- a/scripts/plot/draw/trimesh.m	Sat Mar 02 15:36:26 2024 -0500
+++ b/scripts/plot/draw/trimesh.m	Sun Mar 03 20:13:08 2024 -0500
@@ -42,7 +42,7 @@
 ## the triangles are plotted as a 2-D figure.
 ##
 ## The color of the trimesh is computed by linearly scaling the @var{z} values
-## to fit the range of the current colormap.  Use @code{caxis} and/or
+## to fit the range of the current colormap.  Use @code{clim} and/or
 ## change the colormap to control the appearance.
 ##
 ## Optionally, the color of the mesh can be specified independently of @var{z}
--- a/scripts/plot/draw/trisurf.m	Sat Mar 02 15:36:26 2024 -0500
+++ b/scripts/plot/draw/trisurf.m	Sun Mar 03 20:13:08 2024 -0500
@@ -40,7 +40,7 @@
 ## plane of each vertex.
 ##
 ## The color of the trisurf is computed by linearly scaling the @var{z} values
-## to fit the range of the current colormap.  Use @code{caxis} and/or change
+## to fit the range of the current colormap.  Use @code{clim} and/or change
 ## the colormap to control the appearance.
 ##
 ## Optionally, the color of the mesh can be specified independently of @var{z}
--- a/scripts/plot/draw/waterfall.m	Sat Mar 02 15:36:26 2024 -0500
+++ b/scripts/plot/draw/waterfall.m	Sun Mar 03 20:13:08 2024 -0500
@@ -45,7 +45,7 @@
 ## of @var{z} correspond to different @var{y} values.
 ##
 ## The color of the mesh is computed by linearly scaling the @var{z} values
-## to fit the range of the current colormap.  Use @code{caxis} and/or
+## to fit the range of the current colormap.  Use @code{clim} and/or
 ## change the colormap to control the appearance.
 ##
 ## Optionally the color of the mesh can be specified independently of @var{z}
@@ -62,7 +62,7 @@
 ## surface object.
 ##
 ## @seealso{meshz, mesh, meshc, contour, surf, surface, ribbon, meshgrid,
-## hidden, shading, colormap, caxis}
+## hidden, shading, colormap, clim}
 ## @end deftypefn
 
 function h = waterfall (varargin)
--- a/scripts/statistics/mad.m	Sat Mar 02 15:36:26 2024 -0500
+++ b/scripts/statistics/mad.m	Sun Mar 03 20:13:08 2024 -0500
@@ -123,12 +123,12 @@
 %!assert (mad (123), 0)
 %!assert (mad (Inf), NaN)
 %!assert (mad ([3, Inf]),Inf)
-%!assert (mad ([0 0 1 2 100]), 31.76)
-%!assert (mad (single ([0 0 1 2 100])), single (31.76))
-%!assert (mad ([0 0 1 2 100]'), 31.76)
-%!assert (mad ([0 0 1 2 100], 1), 1)
-%!assert (mad (single ([0 0 1 2 100]), 1), single (1))
-%!assert (mad ([0 0 1 2 100]', 1), 1)
+%!assert (mad ([0, 0, 1, 2, 100]), 31.76)
+%!assert (mad (single ([0, 0, 1, 2, 100])), single (31.76))
+%!assert (mad ([0, 0, 1, 2, 100]'), 31.76)
+%!assert (mad ([0, 0, 1, 2, 100], 1), 1)
+%!assert (mad (single ([0, 0, 1, 2, 100]), 1), single (1))
+%!assert (mad ([0, 0, 1, 2, 100]', 1), 1)
 %!assert (mad (magic (4)), [4, 4, 4, 4])
 %!assert (mad (magic (4), [], 2), [6; 2; 2; 6])
 %!assert (mad (magic (4), 1), [2.5, 3.5, 3.5, 2.5])
@@ -141,22 +141,22 @@
 %!assert (mad (magic (4), 0, "all"), 4)
 %!assert (mad (magic (4), 1, "all"), 4)
 %!assert (mad (magic (4), 0, [1 2]), 4)
-%!assert (mad (magic (4), 0, [1 3]), mad (magic(4), 0, 1))
+%!assert (mad (magic (4), 0, [1 3]), mad (magic (4), 0, 1))
 %!assert (mad (magic (4), 0, [1 2 3]), 4)
 %!assert (mad (magic (4), 1, [1 2]), 4)
-%!assert (mad (magic (4), 1, [1 3]), mad (magic(4), 1, 1))
+%!assert (mad (magic (4), 1, [1 3]), mad (magic (4), 1, 1))
 %!assert (mad (magic (4), 1, [1 2 3]), 4)
 %!assert (mad (magic (4), 0, [3 4 99]), zeros (4))
 %!assert (mad (magic (4), 1, [3 4 99]), zeros (4))
 
 ## Verify ignoring NaN values unless all NaN
 %!assert (mad (NaN), NaN)
-%!assert (mad (NaN (2)), NaN(1,2))
-%!assert (mad ([1,2;3,NaN]), [1, 0])
-%!assert (mad ([1,2;3,NaN], [], 1), [1, 0])
-%!assert (mad ([1,2;3,NaN], [], 2), [0.5; 0], eps)
-%!assert (mad ([1,NaN;3,NaN], [], 1), [1, NaN])
-%!assert (mad ([1,NaN;3,NaN], [], 2), [0; 0])
+%!assert (mad (NaN (2)), NaN (1, 2))
+%!assert (mad ([1, 2; 3, NaN]), [1, 0])
+%!assert (mad ([1, 2; 3, NaN], [], 1), [1, 0])
+%!assert (mad ([1, 2; 3, NaN], [], 2), [0.5; 0], eps)
+%!assert (mad ([1, NaN; 3, NaN], [], 1), [1, NaN])
+%!assert (mad ([1, NaN; 3, NaN], [], 2), [0; 0])
 
 ## Verify compatible empty handling
 %!assert (mad ([]), NaN)
@@ -164,24 +164,45 @@
 %!assert (mad ([], 0, 2), NaN (0,1))
 %!assert (mad ([], 0, 3), NaN (0,0))
 %!assert (mad (single ([])), NaN ('single'))
-%!assert (mad (ones (0,1)), NaN)
-%!assert (mad (ones (0,1), 0, 1), NaN (1,1))
-%!assert (mad (ones (0,1), 0, 2), NaN (0,1))
-%!assert (mad (ones (0,1), 0, 3), NaN (0,1))
-%!assert (mad (ones (1,0)), NaN)
-%!assert (mad (ones (1,0), 0, 1), NaN (1,0))
-%!assert (mad (ones (1,0), 0, 2), NaN (1,1))
-%!assert (mad (ones (1,0), 0, 3), NaN (1,0))
-%!assert (mad (ones (0,0,0)), NaN (1,0,0))
-%!assert (mad (ones (1,0,0)), NaN (1,1,0))
-%!assert (mad (ones (0,1,0)), NaN (1,1,0))
-%!assert (mad (ones (0,0,0)), NaN (1,0,0))
-%!assert (mad (ones (0,1,0), 0, 1), NaN (1,1,0))
-%!assert (mad (ones (0,1,0), 0, 2), NaN (0,1,0))
-%!assert (mad (ones (0,1,0), 0, 3), NaN (0,1,1))
-%!assert (mad (ones (0,1,0), 0, 4), NaN (0,1,0))
-%!assert (mad (ones (0,2,1,0)), ones (1,2,1,0))
-%!assert (mad (ones (2,0,1,0)), ones (1,0,1,0))
+%!assert (mad (ones (0, 1)), NaN)
+%!assert (mad (ones (0, 1), 0, 1), NaN (1, 1))
+%!assert (mad (ones (0, 1), 0, 2), NaN (0, 1))
+%!assert (mad (ones (0, 1), 0, 3), NaN (0, 1))
+%!assert (mad (ones (1, 0)), NaN)
+%!assert (mad (ones (1, 0), 0, 1), NaN (1, 0))
+%!assert (mad (ones (1, 0), 0, 2), NaN (1, 1))
+%!assert (mad (ones (1, 0), 0, 3), NaN (1, 0))
+%!assert (mad (ones (0, 0, 0)), NaN (1, 0, 0))
+%!assert (mad (ones (1, 0, 0)), NaN (1, 1, 0))
+%!assert (mad (ones (0, 1, 0)), NaN (1, 1, 0))
+%!assert (mad (ones (0, 0, 0)), NaN (1, 0, 0))
+%!assert (mad (ones (0, 1, 0), 0, 1), NaN (1, 1, 0))
+%!assert (mad (ones (0, 1, 0), 0, 2), NaN (0, 1, 0))
+%!assert (mad (ones (0, 1, 0), 0, 3), NaN (0, 1, 1))
+%!assert (mad (ones (0, 1, 0), 0, 4), NaN (0, 1, 0))
+%!assert (mad (ones (0, 2, 1, 0)), ones (1, 2, 1, 0))
+%!assert (mad (ones (2, 0, 1, 0)), ones (1, 0, 1, 0))
+
+## Test Inf handling
+%!assert <*65405> (mad ([-Inf, Inf]), NaN)
+%!assert <*65405> (mad ([-Inf, Inf], 0), NaN)
+%!assert <*65405> (mad ([-Inf, Inf], 1), NaN)
+%!assert <*65405> (mad ([-Inf, Inf]', 0), NaN)
+%!assert <*65405> (mad ([-Inf, Inf]', 1), NaN)
+%!assert <*65405> (mad ([-Inf, Inf]', 0, 1), NaN)
+%!assert <*65405> (mad ([-Inf, Inf]', 0, 2), [NaN; NaN])
+%!assert <*65405> (mad ([-Inf, Inf]', 0, 3), [NaN; NaN])
+%!assert <*65405> (mad ([-Inf, Inf]', 1, 1), NaN)
+%!assert <*65405> (mad ([-Inf, Inf]', 1, 2), [NaN; NaN])
+%!assert <*65405> (mad ([-Inf, Inf]', 1, 3), [NaN; NaN])
+%!assert <*65405> (mad (Inf (2), 0), [NaN, NaN])
+%!assert <*65405> (mad (Inf (2), 1), [NaN, NaN])
+%!assert <*65405> (mad (Inf (2), 0, 1), [NaN, NaN])
+%!assert <*65405> (mad (Inf (2), 0, 2), [NaN; NaN])
+%!assert <*65405> (mad (Inf (2), 0, 3), NaN (2))
+%!assert <*65405> (mad (Inf (2), 1, 1), [NaN, NaN])
+%!assert <*65405> (mad (Inf (2), 1, 2), [NaN; NaN])
+%!assert <*65405> (mad (Inf (2), 1, 3), NaN (2))
 
 ## Test input case insensitivity
 %!assert (mad ([1 2 3], 0, "aLL"), 2/3, eps)
--- a/scripts/statistics/median.m	Sat Mar 02 15:36:26 2024 -0500
+++ b/scripts/statistics/median.m	Sun Mar 03 20:13:08 2024 -0500
@@ -267,6 +267,12 @@
     return;
   endif
 
+  if (all (isnan (x(:))))
+    ## all NaN input, output single or double NaNs in pre-determined size
+    m = NaN (sz_out, outtype);
+    return;
+  endif
+
   if (szx(dim) == 1)
     ## Operation along singleton dimension - nothing to do
     if (! strcmp (class (x), outtype))
@@ -307,6 +313,7 @@
 
   ## Find column locations of NaNs
   nanfree = ! any (isnan (x), dim);
+
   if (omitnan && nanfree(:))
     ## Don't use omitnan path if no NaNs are present.  Prevents any data types
     ## without a defined NaN from following slower omitnan codepath.
@@ -438,14 +445,14 @@
 
 
 %!assert (median (1), 1)
-%!assert (median ([1,2,3]), 2)
-%!assert (median ([1,2,3]'), 2)
-%!assert (median (cat(3,3,1,2)), 2)
-%!assert (median ([3,1,2]), 2)
-%!assert (median ([2,4,6,8]), 5)
-%!assert (median ([8,2,6,4]), 5)
-%!assert (median (single ([1,2,3])), single (2))
-%!assert (median ([1,2], 3), [1,2])
+%!assert (median ([1, 2, 3]), 2)
+%!assert (median ([1, 2, 3]'), 2)
+%!assert (median (cat (3, 3, 1, 2)), 2)
+%!assert (median ([3, 1, 2]), 2)
+%!assert (median ([2, 4, 6, 8]), 5)
+%!assert (median ([8, 2, 6, 4]), 5)
+%!assert (median (single ([1, 2, 3])), single (2))
+%!assert (median ([1, 2], 3), [1, 2])
 
 %!test
 %! x = [1, 2, 3, 4, 5, 6];
@@ -460,39 +467,39 @@
 
 ## Test outtype option
 %!test
-%! in = [1 2 3];
+%! in = [1, 2, 3];
 %! out = 2;
 %! assert (median (in, "default"), median (in));
 %! assert (median (in, "default"), out);
 %!test
-%! in = single ([1 2 3]);
+%! in = single ([1, 2, 3]);
 %! out = 2;
 %! assert (median (in, "default"), single (median (in)));
 %! assert (median (in, "default"), single (out));
 %! assert (median (in, "double"), double (out));
 %! assert (median (in, "native"), single (out));
 %!test
-%! in = uint8 ([1 2 3]);
+%! in = uint8 ([1, 2, 3]);
 %! out = 2;
 %! assert (median (in, "default"), double (median (in)));
 %! assert (median (in, "default"), double (out));
 %! assert (median (in, "double"), out);
 %! assert (median (in, "native"), uint8 (out));
 %!test
-%! in = logical ([1 0 1]);
+%! in = logical ([1, 0, 1]);
 %! out = 1;
 %! assert (median (in, "default"), double (median (in)));
 %! assert (median (in, "default"), double (out));
 %! assert (median (in, "double"), double (out));
 %! assert (median (in, "native"), double (out));
 
-## Test single input and optional arguments "all", DIM, "omitnan")
+## Test single input and optional arguments "all", DIM, "omitnan"
 %!test
 %! x = repmat ([2 2.1 2.2 2 NaN; 3 1 2 NaN 5; 1 1.1 1.4 5 3], [1, 1, 4]);
 %! y = repmat ([2 1.1 2 NaN NaN], [1, 1, 4]);
 %! assert (median (x), y);
 %! assert (median (x, 1), y);
-%! y = repmat ([2 1.1 2 3.5 4], [1, 1, 4]);
+%! y = repmat ([2, 1.1, 2, 3.5, 4], [1, 1, 4]);
 %! assert (median (x, "omitnan"), y);
 %! assert (median (x, 1, "omitnan"), y);
 %! y = repmat ([2.05; 2.5; 1.4], [1, 1, 4]);
@@ -508,78 +515,96 @@
 %!test
 %! assert (median (true, "all"), logical (1));
 %! assert (median (false), logical (0));
-%! assert (median ([true false true]), true);
-%! assert (median ([true false true], 2), true);
-%! assert (median ([true false true], 1), logical ([1 0 1]));
-%! assert (median ([true false NaN], 1), [1 0 NaN]);
-%! assert (median ([true false NaN], 2), NaN);
-%! assert (median ([true false NaN], 2, "omitnan"), 0.5);
-%! assert (median ([true false NaN], 2, "omitnan", "native"), double(0.5));
+%! assert (median ([true, false, true]), true);
+%! assert (median ([true, false, true], 2), true);
+%! assert (median ([true, false, true], 1), logical ([1 0 1]));
+%! assert (median ([true, false, NaN], 1), [1, 0, NaN]);
+%! assert (median ([true, false, NaN], 2), NaN);
+%! assert (median ([true, false, NaN], 2, "omitnan"), 0.5);
+%! assert (median ([true, false, NaN], 2, "omitnan", "native"), double (0.5));
 
 ## Test dimension indexing with vecdim in n-dimensional arrays
 %!test
-%! x = repmat ([1:20;6:25], [5 2 6 3]);
-%! assert (size (median (x, [3 2])), [10 1 1 3]);
-%! assert (size (median (x, [1 2])), [1 1 6 3]);
-%! assert (size (median (x, [1 2 4])), [1 1 6]);
-%! assert (size (median (x, [1 4 3])), [1 40]);
-%! assert (size (median (x, [1 2 3 4])), [1 1]);
+%! x = repmat ([1:20; 6:25], [5, 2, 6, 3]);
+%! assert (size (median (x, [3, 2])), [10, 1, 1, 3]);
+%! assert (size (median (x, [1, 2])), [1, 1, 6, 3]);
+%! assert (size (median (x, [1, 2, 4])), [1, 1, 6]);
+%! assert (size (median (x, [1, 4, 3])), [1, 40]);
+%! assert (size (median (x, [1, 2, 3, 4])), [1, 1]);
 
 ## Test exceeding dimensions
-%!assert (median (ones (2,2), 3), ones (2,2))
-%!assert (median (ones (2,2,2), 99), ones (2,2,2))
+%!assert (median (ones (2, 2), 3), ones (2, 2))
+%!assert (median (ones (2, 2, 2), 99), ones (2, 2, 2))
 %!assert (median (magic (3), 3), magic (3))
-%!assert (median (magic (3), [1 3]), [4, 5, 6])
-%!assert (median (magic (3), [1 99]), [4, 5, 6])
+%!assert (median (magic (3), [1, 3]), [4, 5, 6])
+%!assert (median (magic (3), [1, 99]), [4, 5, 6])
 
-## Test results with vecdim in n-dimensional arrays and "omitnan"
+## Test results with vecdim in N-dimensional arrays and "omitnan"
 %!test
 %! x = repmat ([2 2.1 2.2 2 NaN; 3 1 2 NaN 5; 1 1.1 1.4 5 3], [1, 1, 4]);
-%! assert (median (x, [3 2]), [NaN NaN 1.4]');
-%! assert (median (x, [3 2], "omitnan"), [2.05 2.5 1.4]');
-%! assert (median (x, [1 3]), [2 1.1 2 NaN NaN]);
-%! assert (median (x, [1 3], "omitnan"), [2 1.1 2 3.5 4]);
+%! assert (median (x, [3, 2]), [NaN, NaN, 1.4]');
+%! assert (median (x, [3, 2], "omitnan"), [2.05, 2.5, 1.4]');
+%! assert (median (x, [1, 3]), [2, 1.1, 2, NaN, NaN]);
+%! assert (median (x, [1, 3], "omitnan"), [2, 1.1, 2, 3.5, 4]);
 
 ## Test empty, NaN, Inf inputs
 %!assert (median (NaN), NaN)
 %!assert (median (NaN, "omitnan"), NaN)
-%!assert (median (NaN (2)), [NaN NaN])
-%!assert (median (NaN (2), "omitnan"), [NaN NaN])
-%!assert (median ([1 NaN 3]), NaN)
-%!assert (median ([1 NaN 3], 1), [1 NaN 3])
-%!assert (median ([1 NaN 3], 2), NaN)
-%!assert (median ([1 NaN 3]'), NaN)
-%!assert (median ([1 NaN 3]', 1), NaN)
-%!assert (median ([1 NaN 3]', 2), [1; NaN; 3])
-%!assert (median ([1 NaN 3], "omitnan"), 2)
-%!assert (median ([1 NaN 3]', "omitnan"), 2)
-%!assert (median ([1 NaN 3], 1, "omitnan"), [1 NaN 3])
-%!assert (median ([1 NaN 3], 2, "omitnan"), 2)
-%!assert (median ([1 NaN 3]', 1, "omitnan"), 2)
-%!assert (median ([1 NaN 3]', 2, "omitnan"), [1; NaN; 3])
-%!assert (median ([1 2 NaN 3]), NaN)
-%!assert (median ([1 2 NaN 3], "omitnan"), 2)
+%!assert (median (NaN (2)), [NaN, NaN])
+%!assert (median (NaN (2), "omitnan"), [NaN, NaN])
+%!assert (median ([1, NaN, 3]), NaN)
+%!assert (median ([1, NaN, 3], 1), [1, NaN, 3])
+%!assert (median ([1, NaN, 3], 2), NaN)
+%!assert (median ([1, NaN, 3]'), NaN)
+%!assert (median ([1, NaN, 3]', 1), NaN)
+%!assert (median ([1, NaN, 3]', 2), [1; NaN; 3])
+%!assert (median ([1, NaN, 3], "omitnan"), 2)
+%!assert (median ([1, NaN, 3]', "omitnan"), 2)
+%!assert (median ([1, NaN, 3], 1, "omitnan"), [1, NaN, 3])
+%!assert (median ([1, NaN, 3], 2, "omitnan"), 2)
+%!assert (median ([1, NaN, 3]', 1, "omitnan"), 2)
+%!assert (median ([1, NaN, 3]', 2, "omitnan"), [1; NaN; 3])
+%!assert (median ([1, 2, NaN, 3]), NaN)
+%!assert (median ([1, 2, NaN, 3], "omitnan"), 2)
 %!assert (median ([1,2,NaN;4,5,6;NaN,8,9]), [NaN, 5, NaN])
 %!assert <*64011> (median ([1,2,NaN;4,5,6;NaN,8,9], "omitnan"), [2.5, 5, 7.5], eps)
-%!assert (median ([1 2 ; NaN 4]), [NaN 3])
-%!assert (median ([1 2 ; NaN 4], "omitnan"), [1 3])
-%!assert (median ([1 2 ; NaN 4], 1, "omitnan"), [1 3])
-%!assert (median ([1 2 ; NaN 4], 2, "omitnan"), [1.5; 4], eps)
-%!assert (median ([1 2 ; NaN 4], 3, "omitnan"), [1 2 ; NaN 4])
-%!assert (median ([NaN 2 ; NaN 4]), [NaN 3])
-%!assert (median ([NaN 2 ; NaN 4], "omitnan"), [NaN 3])
+%!assert (median ([1, 2 ; NaN, 4]), [NaN, 3])
+%!assert (median ([1, 2 ; NaN, 4], "omitnan"), [1, 3])
+%!assert (median ([1, 2 ; NaN, 4], 1, "omitnan"), [1, 3])
+%!assert (median ([1, 2 ; NaN, 4], 2, "omitnan"), [1.5; 4], eps)
+%!assert (median ([1, 2 ; NaN, 4], 3, "omitnan"), [1, 2 ; NaN, 4])
+%!assert (median ([NaN, 2 ; NaN, 4]), [NaN, 3])
+%!assert (median ([NaN, 2 ; NaN, 4], "omitnan"), [NaN, 3])
 %!assert (median (ones (1, 0, 3)), NaN (1, 1, 3))
 
-%!assert (median (NaN("single")), NaN("single"))
-%!assert (median (NaN("single"), "omitnan"), NaN("single"))
-%!assert (median (NaN("single"), "double"), NaN("double"))
-%!assert (median (single([1 2 ; NaN 4])), single([NaN 3]))
-%!assert (median (single([1 2 ; NaN 4]), "double"), double([NaN 3]))
-%!assert (median (single([1 2 ; NaN 4]), "omitnan"), single([1 3]))
-%!assert (median (single([1 2 ; NaN 4]), "omitnan", "double"), double([1 3]))
-%!assert (median (single([NaN 2 ; NaN 4]), "double"), double([NaN 3]))
-%!assert (median (single([NaN 2 ; NaN 4]), "omitnan"), single([NaN 3]))
-%!assert (median (single([NaN 2 ; NaN 4]), "omitnan", "double"), double([NaN 3]))
+## Test all NaN vectors and arrays
+%!assert <*65405> (median ([NaN, NaN], 1, "omitnan"), [NaN, NaN])
+%!assert <*65405> (median ([NaN, NaN], 2, "omitnan"), NaN)
+%!assert <*65405> (median ([NaN, NaN]', 1, "omitnan"), NaN)
+%!assert <*65405> (median ([NaN, NaN]', 2, "omitnan"), [NaN; NaN])
+%!assert <*65405> (median ([NaN, NaN], "omitnan"), NaN)
+%!assert <*65405> (median ([NaN, NaN]', "omitnan"), NaN)
+%!assert <*65405> (median (NaN (1, 9), 1, "omitnan"), NaN (1, 9))
+%!assert <*65405> (median (NaN (1, 9), 2, "omitnan"), NaN)
+%!assert <*65405> (median (NaN (1, 9), 3, "omitnan"), NaN (1, 9))
+%!assert <*65405> (median (NaN (9, 1), 1, "omitnan"), NaN)
+%!assert <*65405> (median (NaN (9, 1), 2, "omitnan"), NaN (9, 1))
+%!assert <*65405> (median (NaN (9, 1), 3, "omitnan"), NaN (9, 1))
+%!assert <*65405> (median (NaN (9, 2), 1, "omitnan"), NaN (1, 2))
+%!assert <*65405> (median (NaN (9, 2), 2, "omitnan"), NaN (9, 1))
+%!assert <*65405> (median (NaN (9, 2), "omitnan"), NaN (1, 2))
+
+## Test single inputs
+%!assert (median (NaN ("single")), NaN ("single"))
+%!assert (median (NaN ("single"), "omitnan"), NaN ("single"))
+%!assert (median (NaN ("single"), "double"), NaN ("double"))
+%!assert (median (single ([1, 2 ; NaN, 4])), single ([NaN, 3]))
+%!assert (median (single ([1, 2 ; NaN, 4]), "double"), double ([NaN, 3]))
+%!assert (median (single ([1, 2 ; NaN, 4]), "omitnan"), single ([1, 3]))
+%!assert (median (single ([1, 2 ; NaN, 4]), "omitnan", "double"), double ([1, 3]))
+%!assert (median (single ([NaN, 2 ; NaN, 4]), "double"), double ([NaN 3]))
+%!assert (median (single ([NaN, 2 ; NaN, 4]), "omitnan"), single ([NaN 3]))
+%!assert (median (single ([NaN, 2 ; NaN, 4]), "omitnan", "double"), double ([NaN 3]))
 
 ## Test omitnan with 2D & 3D inputs to confirm correct sub2ind orientation
 %!test <*64011>
@@ -594,51 +619,51 @@
 
 %!assert (median (Inf), Inf)
 %!assert (median (-Inf), -Inf)
-%!assert (median ([-Inf Inf]), NaN)
-%!assert (median ([3 Inf]), Inf)
-%!assert (median ([3 4 Inf]), 4)
-%!assert (median ([Inf 3 4]), 4)
-%!assert (median ([Inf 3 Inf]), Inf)
+%!assert (median ([-Inf, Inf]), NaN)
+%!assert (median ([3, Inf]), Inf)
+%!assert (median ([3, 4, Inf]), 4)
+%!assert (median ([Inf, 3, 4]), 4)
+%!assert (median ([Inf, 3, Inf]), Inf)
 
 %!assert (median ([]), NaN)
-%!assert (median (ones(1,0)), NaN)
-%!assert (median (ones(0,1)), NaN)
-%!assert (median ([], 1), NaN(1,0))
-%!assert (median ([], 2), NaN(0,1))
-%!assert (median ([], 3), NaN(0,0))
-%!assert (median (ones(1,0), 1), NaN(1,0))
-%!assert (median (ones(1,0), 2), NaN(1,1))
-%!assert (median (ones(1,0), 3), NaN(1,0))
-%!assert (median (ones(0,1), 1), NaN(1,1))
-%!assert (median (ones(0,1), 2), NaN(0,1))
-%!assert (median (ones(0,1), 3), NaN(0,1))
-%!assert (median (ones(0,1,0,1), 1), NaN(1,1,0))
-%!assert (median (ones(0,1,0,1), 2), NaN(0,1,0))
-%!assert (median (ones(0,1,0,1), 3), NaN(0,1,1))
-%!assert (median (ones(0,1,0,1), 4), NaN(0,1,0))
+%!assert (median (ones (1, 0)), NaN) 
+%!assert (median (ones (0, 1)), NaN)
+%!assert (median ([], 1), NaN (1, 0))
+%!assert (median ([], 2), NaN (0, 1))
+%!assert (median ([], 3), NaN (0, 0))
+%!assert (median (ones (1, 0), 1), NaN (1, 0))
+%!assert (median (ones (1, 0), 2), NaN (1, 1))
+%!assert (median (ones (1, 0), 3), NaN (1, 0))
+%!assert (median (ones (0, 1), 1), NaN (1, 1))
+%!assert (median (ones (0, 1), 2), NaN (0, 1))
+%!assert (median (ones (0, 1), 3), NaN (0, 1))
+%!assert (median (ones (0, 1, 0, 1), 1), NaN (1, 1, 0))
+%!assert (median (ones (0, 1, 0, 1), 2), NaN (0, 1, 0))
+%!assert (median (ones (0, 1, 0, 1), 3), NaN (0, 1, 1))
+%!assert (median (ones (0, 1, 0, 1), 4), NaN (0, 1, 0))
 
 ## Test complex inputs (should sort by abs(a))
-%!assert (median([1 3 3i 2 1i]), 2)
-%!assert (median([1 2 4i; 3 2i 4]), [2, 1+1i, 2+2i])
+%!assert (median ([1, 3, 3i, 2, 1i]), 2)
+%!assert (median ([1, 2, 4i; 3, 2i, 4]), [2, 1+1i, 2+2i])
 
 ## Test multidimensional arrays
 %!shared a, b, x, y
 %! old_state = rand ("state");
 %! restore_state = onCleanup (@() rand ("state", old_state));
 %! rand ("state", 2);
-%! a = rand (2,3,4,5);
-%! b = rand (3,4,6,5);
+%! a = rand (2, 3, 4, 5);
+%! b = rand (3, 4, 6, 5);
 %! x = sort (a, 4);
 %! y = sort (b, 3);
 %!assert <*35679> (median (a, 4), x(:, :, :, 3))
 %!assert <*35679> (median (b, 3), (y(:, :, 3, :) + y(:, :, 4, :))/2)
-%!shared   ## Clear shared to prevent variable echo for any later test failures
+%!shared   # Clear shared to prevent variable echo for any later test failures
 
-## Test n-dimensional arrays with odd non-NaN data points
+## Test N-dimensional arrays with odd non-NaN data points
 %!test
-%! x = ones(15,1,4);
-%! x([13,15],1,:) = NaN;
-%! assert (median (x, 1, "omitnan"), ones (1,1,4))
+%! x = ones (15, 1, 4);
+%! x([13,15], 1, :) = NaN;
+%! assert (median (x, 1, "omitnan"), ones (1, 1, 4))
 
 ## Test non-floating point types
 %!assert (median ([true, false]), true)
@@ -655,43 +680,43 @@
 %!assert <*54567> (median (uint8 ([253, 255])), uint8 (254))
 %!assert <*54567> (median (uint8 ([253, 254])), uint8 (254))
 %!assert <*54567> (median (int8 ([127, 126, 125, 124; 1 3 5 9])), ...
-%!                  int8 ([64 65 65 67]))
+%!                 int8 ([64 65 65 67]))
 %!assert <*54567> (median (int8 ([127, 126, 125, 124; 1 3 5 9]), 2), ...
-%!                  int8 ([126; 4]))
+%!                 int8 ([126; 4]))
 %!assert <*54567> (median (int64 ([intmax("int64"), intmax("int64")-2])), ...
-%!                  intmax ("int64") - 1)
+%!                 intmax ("int64") - 1)
 %!assert <*54567> (median ( ...
 %!                 int64 ([intmax("int64"), intmax("int64")-2; 1 2]), 2), ...
 %!                 int64([intmax("int64") - 1; 2]))
 %!assert <*54567> (median (uint64 ([intmax("uint64"), intmax("uint64")-2])), ...
-%!                  intmax ("uint64") - 1)
+%!                 intmax ("uint64") - 1)
 %!assert <*54567> (median ( ...
 %!                 uint64 ([intmax("uint64"), intmax("uint64")-2; 1 2]), 2), ...
 %!                 uint64([intmax("uint64") - 1; 2]))
 
 ## Test opposite sign int overflow when getting mean of even number of values
 %!assert <*54567> (median (...
-%! [intmin('int8') intmin('int8')+5 intmax('int8')-5 intmax('int8')]), ...
-%! int8(-1))
+%! [intmin('int8'), intmin('int8')+5, intmax('int8')-5, intmax('int8')]), ...
+%! int8 (-1))
 %!assert <*54567> (median ([int8([1 2 3 4]); ...
-%! intmin('int8') intmin('int8')+5 intmax('int8')-5 intmax('int8')], 2), ...
-%! int8([3;-1]))
+%! intmin('int8'), intmin('int8')+5, intmax('int8')-5, intmax('int8')], 2), ...
+%! int8 ([3;-1]))
 %!assert <*54567> (median (...
-%! [intmin('int64') intmin('int64')+5 intmax('int64')-5 intmax('int64')]), ...
-%! int64(-1))
-%!assert <*54567> (median ([int64([1 2 3 4]); ...
-%! intmin('int64') intmin('int64')+5 intmax('int64')-5 intmax('int64')], 2), ...
-%! int64([3;-1]))
+%! [intmin('int64'), intmin('int64')+5, intmax('int64')-5, intmax('int64')]), ...
+%! int64 (-1))
+%!assert <*54567> (median ([int64([1, 2, 3, 4]); ...
+%! intmin('int64'), intmin('int64')+5, intmax('int64')-5, intmax('int64')], 2), ...
+%! int64 ([3;-1]))
 
 ## Test int accuracy loss doing mean of close int64/uint64 values as double
 %!assert <*54567> (median ([intmax("uint64"), intmax("uint64")-2]), ...
-%!  intmax("uint64")-1)
+%!                 intmax ("uint64")-1)
 %!assert <*54567> (median ([intmax("uint64"), intmax("uint64")-2], "default"), ...
-%!  double(intmax("uint64")-1))
+%!                 double (intmax ("uint64")-1))
 %!assert <*54567> (median ([intmax("uint64"), intmax("uint64")-2], "double"), ...
-%!  double(intmax("uint64")-1))
+%!                 double (intmax ("uint64")-1))
 %!assert <*54567> (median ([intmax("uint64"), intmax("uint64")-2], "native"), ...
-%!  intmax("uint64")-1)
+%!                 intmax ("uint64")-1)
 
 ## Test input case insensitivity
 %!assert (median ([1 2 3], "aLL"), 2)
--- a/test/io.tst	Sat Mar 02 15:36:26 2024 -0500
+++ b/test/io.tst	Sun Mar 03 20:13:08 2024 -0500
@@ -600,7 +600,7 @@
 %! assert (pos, 5);
 
 ## Test '-' within string
-%!test <63383>
+%!test <*63383>
 %! [val, count, msg, pos] = sscanf ('1 2 - 3', '%d');
 %! assert (val, [1; 2]);
 %! assert (count, 2);
@@ -626,7 +626,7 @@
 %! assert (pos, 5);
 
 ## Test '+' within string
-%!test <63383>
+%!test <*63383>
 %! [val, count, msg, pos] = sscanf ('1 2 + 3', '%d');
 %! assert (val, [1; 2]);
 %! assert (count, 2);
@@ -638,7 +638,7 @@
 %! assert (msg, 'sscanf: format failed to match');
 %! assert (pos, 5);
 
-%## Test +NA, -NA, +NAN, -NAN
+## Test +NA, -NA, +NAN, -NAN
 %!test <*63383>
 %! [val, count, msg, pos] = sscanf ('+NA -NA 1 +NAN -NAN', '%f');
 %! assert (val, [NA; NA; 1; NaN; NaN]);
@@ -666,6 +666,22 @@
 %! assert (msg, '');
 %! assert (pos, 5);
 
+## Test space at end of input string
+%!test <63467>
+%! [val, count, msg, pos] = sscanf ('1 2 ', '%f');
+%! assert (val, [1; 2]);
+%! assert (count, 2);
+%! assert (msg, '');
+%! assert (pos, 5);
+
+## Test newline at end of input string
+%!test <65390>
+%! [val, count, msg, pos] = sscanf ("1 2\n", '%f');
+%! assert (val, [1; 2]);
+%! assert (count, 2);
+%! assert (msg, '');
+%! assert (pos, 5);
+
 %!test
 %! [a, b, c] = sscanf ("1.2 3 foo", "%f%d%s", "C");
 %! [v1, c1, m1] = sscanf ("1 2 3 4 5 6", "%d");